Esempio n. 1
0
 def SetUp(self):
     self.remote_instance = ssh.Remote('i2')
     self.remote_file_1 = ssh.FileReference('rem_1', remote=self.remote)
     self.remote_file_2 = ssh.FileReference('rem_2', remote=self.remote)
     self.other_remote_file = ssh.FileReference('rem_3',
                                                remote=ssh.Remote('i5'))
     self.local_file_1 = ssh.FileReference('local_1')
     self.local_file_2 = ssh.FileReference('local_2')
Esempio n. 2
0
def CreateSSHPoller(remote,
                    identity_file,
                    options,
                    iap_tunnel_helper,
                    extra_flags=None,
                    port=None):
    """Creates and returns an SSH poller."""

    ssh_poller_args = {
        'remote': remote,
        'identity_file': identity_file,
        'options': options,
        'extra_flags': extra_flags,
        'max_wait_ms': SSH_KEY_PROPAGATION_TIMEOUT_SEC
    }

    # Do not include default port since that will prevent users from
    # specifying a custom port (b/121998342).
    if port:
        ssh_poller_args['port'] = str(port)

    if iap_tunnel_helper:
        ssh_poller_args['remote'] = ssh.Remote('localhost', remote.user)
        ssh_poller_args['port'] = str(iap_tunnel_helper.GetLocalPort())

    return ssh.SSHPoller(**ssh_poller_args)
Esempio n. 3
0
    def Run(self, args):
        command_list = args.command.split(' ') if args.command else ['bash -l']
        project = properties.VALUES.core.project.Get()
        connection_info = util.PrepareEnvironment(args)
        command = ssh.SSHCommand(
            remote=ssh.Remote(host=connection_info.host,
                              user=connection_info.user),
            port=six.text_type(connection_info.port),
            identity_file=connection_info.key,
            remote_command=(['DEVSHELL_PROJECT_ID=' +
                             project] if project else []) + command_list,
            extra_flags=args.ssh_flag,
            tty=not args.command,
            options={'StrictHostKeyChecking': 'no'},
        )

        if args.dry_run:
            log.Print(' '.join(command.Build(connection_info.ssh_env)))
        else:
            self.done = threading.Event()
            thread = threading.Thread(target=self.Reauthorize, args=())
            thread.daemon = True
            thread.start()
            command.Run(connection_info.ssh_env)
            self.done.set()
 def SetUp(self):
   self.remote = ssh.Remote('75.251.133.23', user='******')
   self.instance = MESSAGES.Instance(
       id=11111,
       name='instance-1',
       networkInterfaces=[
           MESSAGES.NetworkInterface(
               accessConfigs=[
                   MESSAGES.AccessConfig(
                       name='external-nat', natIP='75.251.133.23'),
               ],),
       ],
       status=MESSAGES.Instance.StatusValueValuesEnum.RUNNING,
       selfLink=(
           'https://compute.googleapis.com/compute/v1/projects/asdf-project/'
           'zones/zone-1/instances/instance-1'),
       zone=('https://compute.googleapis.com/compute/v1/projects/asdf-project/'
             'zones/zone-1'))
   self.project = self.v1_messages.Project(
       commonInstanceMetadata=self.v1_messages.Metadata(items=[
           self.v1_messages.Metadata.ItemsValueListEntry(key='a', value='b'),
           self.v1_messages.Metadata.ItemsValueListEntry(
               key='ssh-keys',
               value='me:{0}\n'.format(self.public_key_material)),
       ]),
       name='asdf-project',
   )
  def testWithExtraArgs(self):
    self.make_requests.side_effect = iter([
        [INSTANCE_WITH_EXTERNAL_ADDRESS],
        [self.project_resource],
    ])
    self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE

    self.Run("""
        compute connect-to-serial-port instance-1 --zone zone-1 --extra-args foo=bar
        """)

    self.CheckRequests(
        [(self.GetCompute().instances,
          'Get',
          self.GetMessages().ComputeInstancesGetRequest(
              instance='instance-1',
              project='my-project',
              zone='zone-1'))],
        [(self.GetCompute().projects,
          'Get',
          self.GetMessages().ComputeProjectsGetRequest(
              project='my-project'))],
    )
    # SSH Command
    self.ssh_init.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        ssh.Remote(self.gateway,
                   user='******'),
        identity_file=self.private_key_file,
        options=self.options,
        port='9600')
Esempio n. 6
0
    def testWithAlternateUser(self):
        project_resource = self.messages.Project(name='my-project', )
        self.make_requests.side_effect = iter([
            [self.instance],
            [project_resource],
            [],
        ])

        self.Run("""\
        compute scp
          hapoo@instance-1:~/remote-file
          ~/local-dir --zone zone-1
        """)

        self.CheckRequests(
            [(self.compute.instances, 'Get',
              self.messages.ComputeInstancesGetRequest(instance='instance-1',
                                                       project='my-project',
                                                       zone='zone-1'))],
            [(self.compute.projects, 'Get',
              self.messages.ComputeProjectsGetRequest(project='my-project'))],
            [(self.compute.projects, 'SetCommonInstanceMetadata',
              self.messages.ComputeProjectsSetCommonInstanceMetadataRequest(
                  metadata=self.messages.Metadata(items=[
                      self.messages.Metadata.ItemsValueListEntry(
                          key='ssh-keys',
                          value='hapoo:' + self.public_key_material),
                  ]),
                  project='my-project'))],
        )

        remote = ssh.Remote(self.remote.host, user='******')
        remote_file = ssh.FileReference('~/remote-file', remote=remote)
        # Polling
        self.poller_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SSHPoller),
            remote=remote,
            identity_file=self.private_key_file,
            max_wait_ms=ssh_utils.SSH_KEY_PROPAGATION_TIMEOUT_MS,
            options=dict(self.options, HostKeyAlias='compute.11111'),
            extra_flags=None,
            iap_tunnel_args=None)
        self.poller_poll.assert_called_once()

        # SCP Command
        self.scp_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SCPCommand), [remote_file],
            self.local_dir,
            identity_file=self.private_key_file,
            extra_flags=[],
            port=None,
            recursive=False,
            compress=False,
            options=dict(self.options, HostKeyAlias='compute.11111'),
            iap_tunnel_args=None)

        self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher(
            ssh.SCPCommand),
                                             self.env,
                                             force_connect=True)
def RunSSHCommandToInstance(command_list,
                            instance,
                            user,
                            args,
                            ssh_helper,
                            explicit_output_file=None,
                            explicit_error_file=None,
                            dry_run=False):
    """Runs a SSH command to a Google Compute Engine VM.

  Args:
    command_list: List with the ssh command to run.
    instance: The GCE VM object.
    user: The user to be used for the SSH command.
    args: The args used to call the gcloud instance.
    ssh_helper: ssh_utils.BaseSSHCLIHelper instance initialized
      for the command.
    explicit_output_file: Use this file for piping stdout of the SSH command,
                          instead of using stdout. This is useful for
                          capturing the command and analyzing it.
    explicit_error_file: Use this file for piping stdout of the SSH command,
                         instead of using stdout. This is useful for
                         capturing the command and analyzing it.
    dry_run: Whether or not this is a dry-run (only print, not run).
  Returns:
    The exit code of the SSH command
  Raises:
    ssh.CommandError: there was an error running a SSH command
  """
    external_ip_address = ssh_utils.GetExternalIPAddress(instance)
    remote = ssh.Remote(external_ip_address, user)

    identity_file = None
    options = None
    if not args.plain:
        identity_file = ssh_helper.keys.key_file
        options = ssh_helper.GetConfig(ssh_utils.HostKeyAlias(instance),
                                       args.strict_host_key_checking)
    extra_flags = ssh.ParseAndSubstituteSSHFlags(args, remote, user)
    remainder = []

    remote_command = containers.GetRemoteCommand(None, command_list)

    cmd = ssh.SSHCommand(remote,
                         identity_file=identity_file,
                         options=options,
                         extra_flags=extra_flags,
                         remote_command=remote_command,
                         remainder=remainder)
    if dry_run:
        DryRunLog(' '.join(cmd.Build(ssh_helper.env)))
        return 0

    return_code = cmd.Run(ssh_helper.env,
                          force_connect=True,
                          explicit_output_file=explicit_output_file,
                          explicit_error_file=explicit_error_file)
    log.out.flush()
    return return_code
  def testWithAbsoluteExpiration(self):
    self.make_requests.side_effect = iter([
        [INSTANCE_WITH_EXTERNAL_ADDRESS],
        [self.project_resource_without_metadata],
        [],
    ])
    self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE

    self.Run("""
        compute connect-to-serial-port instance-1 --zone zone-1
        --ssh-key-expiration 2015-01-23T12:34:56+0000
        """)

    self.CheckRequests(
        [(self.GetCompute().instances,
          'Get',
          self.GetMessages().ComputeInstancesGetRequest(
              instance='instance-1',
              project='my-project',
              zone='zone-1'))],
        [(self.GetCompute().projects,
          'Get',
          self.GetMessages().ComputeProjectsGetRequest(
              project='my-project'))],
        [(self.GetCompute().projects,
          'SetCommonInstanceMetadata',
          self.GetMessages().ComputeProjectsSetCommonInstanceMetadataRequest(
              metadata=self.GetMessages().Metadata(
                  items=[
                      self.GetMessages().Metadata.ItemsValueListEntry(
                          key='ssh-keys',
                          value=('me:{0} google-ssh {{"userName":"******",'
                                 '"expireOn":'
                                 '"2015-01-23T12:34:56+0000"}}').format(
                                     self.pubkey.ToEntry())),
                  ]),

              project='my-project'))],
    )
    # SSH Command
    self.ssh_init.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        ssh.Remote(self.gateway,
                   user='******'),
        identity_file=self.private_key_file,
        options=self.options,
        port='9600')

    self.ssh_run.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        self.env, force_connect=True)

    # Known Hosts
    self.known_hosts_add.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.KnownHosts),
        '[ssh-serialport.googleapis.com]:9600', PUBLIC_KEY, overwrite=True)
    self.known_hosts_write.assert_called_once()
    self.AssertErrContains('Updating project ssh metadata')
Esempio n. 9
0
def CreateSSHPoller(remote, identity_file, options, iap_tunnel_helper,
                    extra_flags=None, port=DEFAULT_SSH_PORT):
  if iap_tunnel_helper:
    remote = ssh.Remote('localhost', remote.user)
    port = iap_tunnel_helper.GetLocalPort()
  return ssh.SSHPoller(
      remote, port=str(port) if port else None, identity_file=identity_file,
      options=options, extra_flags=extra_flags,
      max_wait_ms=SSH_KEY_PROPAGATION_TIMEOUT_SEC)
Esempio n. 10
0
    def testOsloginEnabledOnProjectButDisabledOnInstance(self, oslogin_mock):
        # Should fall through to alternate authentication.
        properties.VALUES.core.account.Set('*****@*****.**')
        self.remote = ssh.Remote('23.251.133.75', user='******')
        oslogin_mock.return_value = test_resources.MakeOsloginClient('v1')

        self.make_requests.side_effect = iter([
            [INSTANCE_WITH_OSLOGIN_DISABLED],
            [self.project_resource_with_oslogin_enabled],
            [],
        ])

        self.Run("""
        compute ssh instance-1 --zone zone-1
        """)

        self.CheckRequests(
            [(self.compute.instances, 'Get',
              self.messages.ComputeInstancesGetRequest(instance='instance-1',
                                                       project='my-project',
                                                       zone='zone-1'))],
            [(self.compute.projects, 'Get',
              self.messages.ComputeProjectsGetRequest(project='my-project'))],
            [(self.compute.projects, 'SetCommonInstanceMetadata',
              self.messages.ComputeProjectsSetCommonInstanceMetadataRequest(
                  metadata=self.messages.Metadata(items=[
                      self.messages.Metadata.ItemsValueListEntry(
                          key='enable-oslogin', value='true'),
                      self.messages.Metadata.ItemsValueListEntry(
                          key='ssh-keys',
                          value='me:' + self.public_key_material),
                  ]),
                  project='my-project'))],
        )

        # Require SSH keys
        self.ensure_keys.assert_called_once_with(self.keys,
                                                 None,
                                                 allow_passphrase=True)

        # SSH Command
        self.ssh_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SSHCommand),
            remote=self.remote,
            identity_file=self.private_key_file,
            extra_flags=[],
            tty=None,
            options=dict(self.options, HostKeyAlias='compute.55555'),
            remote_command=None,
            iap_tunnel_args=None,
            remainder=[])

        self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher(
            ssh.SSHCommand),
                                             self.env,
                                             force_connect=True)
Esempio n. 11
0
 def testPopulateKeyWithOsLoginUser(self):
   """OS Login is enabled, so different username and no key tranferred."""
   self.StartObjectPatch(ssh, 'CheckForOsloginAndGetUser', autospec=True,
                         return_value=('me_oslogin', 'True'))
   connection_details_expected = ssh_common.ConnectionDetails(
       ssh.Remote('127.0.0.1', user='******'), self.options)
   self._ExpectGetVersionCall('default', 'v1')
   self._ExpectGetInstanceCall('default', 'v1', 'i2', debug_enabled=True)
   connection_details = ssh_common.PopulatePublicKey(
       self.api_client, 'default', 'v1', 'i2', self.public_key, self.track)
   self.assertEqual(connection_details, connection_details_expected)
Esempio n. 12
0
 def testBetaNoArguments(self):
     self.mockV1Connection(user="******", host="my-host", port=123)
     self.Run("beta cloud-shell ssh")
     self.ssh_init.assert_called_once_with(
         mock.ANY,
         remote=ssh.Remote(host="my-host", user="******"),
         port="123",
         identity_file=None,
         remote_command=["DEVSHELL_PROJECT_ID=fake-project", "bash -l"],
         extra_flags=None,
         tty=True,
         options={"StrictHostKeyChecking": "no"})
     self.authorize_v1.assert_not_called()
Esempio n. 13
0
 def testCommand(self):
   self.mockConnection(user="******", host="my-host", port=123)
   self.Run("alpha cloud-shell ssh --command=ls")
   self.ssh_init.assert_called_once_with(
       mock.ANY,
       remote=ssh.Remote(host="my-host", user="******"),
       port="123",
       identity_file=None,
       remote_command=["DEVSHELL_PROJECT_ID=fake-project", "ls"],
       extra_flags=None,
       tty=False,
       options={"StrictHostKeyChecking": "no"})
   self.authorize.assert_called()
  def testInstanceWithOsloginEnabled(self, oslogin_mock):
    properties.VALUES.core.account.Set('*****@*****.**')
    oslogin_mock.return_value = test_resources.MakeOsloginClient('v1')
    self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE
    self.make_requests.side_effect = iter([
        [INSTANCE_WITH_OSLOGIN_ENABLED],
        [self.project_resource],
    ])

    self.Run("""
        compute connect-to-serial-port instance-4 --zone zone-1
        """)
    self.CheckRequests(
        [(self.GetCompute().instances,
          'Get',
          self.GetMessages().ComputeInstancesGetRequest(
              instance='instance-4',
              project='my-project',
              zone='zone-1'))],
        [(self.GetCompute().projects,
          'Get',
          self.GetMessages().ComputeProjectsGetRequest(
              project='my-project'))],
    )

    # Require SSH keys
    self.ensure_keys.assert_called_once_with(
        self.keys, None, allow_passphrase=True)

    # No polling
    self.poller_poll.assert_not_called()

    # SSH Command
    self.ssh_init.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        ssh.Remote(self.gateway,
                   user='******'),
        identity_file=self.private_key_file,
        options=self.options,
        port='9600')

    self.ssh_run.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        self.env, force_connect=True)

    # Known Hosts
    self.known_hosts_add.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.KnownHosts),
        '[ssh-serialport.googleapis.com]:9600', PUBLIC_KEY, overwrite=True)
    self.known_hosts_write.assert_called_once()
    self.make_requests.assert_not_called()
Esempio n. 15
0
 def testSshFlag(self):
   self.mockConnection(user="******", host="my-host", port=123)
   self.Run(
       "alpha cloud-shell ssh --ssh-flag=-someFlag --ssh-flag=anotherFlag")
   self.ssh_init.assert_called_once_with(
       mock.ANY,
       remote=ssh.Remote(host="my-host", user="******"),
       port="123",
       identity_file=None,
       remote_command=["DEVSHELL_PROJECT_ID=fake-project", "bash -l"],
       extra_flags=["-someFlag", "anotherFlag"],
       tty=True,
       options={"StrictHostKeyChecking": "no"})
   self.authorize.assert_called()
Esempio n. 16
0
    def testRequestNonOsloginUser(self, oslogin_mock):
        properties.VALUES.core.account.Set('*****@*****.**')
        self.remote = ssh.Remote('23.251.133.75', user='******')
        oslogin_mock.return_value = test_resources.MakeOsloginClient('v1')

        self.make_requests.side_effect = iter([
            [INSTANCE_WITH_OSLOGIN_ENABLED],
            [self.project_resource],
        ])

        self.Run("""
        compute ssh someotheruser@instance-1 --zone zone-1
        """)

        self.CheckRequests(
            [(self.compute.instances, 'Get',
              self.messages.ComputeInstancesGetRequest(instance='instance-1',
                                                       project='my-project',
                                                       zone='zone-1'))],
            [(self.compute.projects, 'Get',
              self.messages.ComputeProjectsGetRequest(project='my-project'))],
        )

        # Require SSH keys
        self.ensure_keys.assert_called_once_with(self.keys,
                                                 None,
                                                 allow_passphrase=True)

        # No polling
        self.poller_poll.assert_not_called()

        # SSH Command
        self.ssh_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SSHCommand),
            remote=self.remote,
            identity_file=self.private_key_file,
            extra_flags=[],
            tty=None,
            options=dict(self.options, HostKeyAlias='compute.44444'),
            remote_command=None,
            iap_tunnel_args=None,
            remainder=[])

        self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher(
            ssh.SSHCommand),
                                             self.env,
                                             force_connect=True)

        self.AssertErrContains('Using OS Login user [user_google_com] instead '
                               'of requested user [someotheruser]')
Esempio n. 17
0
 def testNoProject(self):
   self.mockConnection(user="******", host="my-host", port=123)
   prop = properties.FromString("project")
   properties.PersistProperty(prop, None, scope=properties.Scope.USER)
   self.Run("alpha cloud-shell ssh")
   self.ssh_init.assert_called_once_with(
       mock.ANY,
       remote=ssh.Remote(host="my-host", user="******"),
       port="123",
       identity_file=None,
       remote_command=["bash -l"],
       extra_flags=None,
       tty=True,
       options={"StrictHostKeyChecking": "no"})
   self.authorize.assert_called()
  def testZonePrompting(self):
    self.StartPatch('googlecloudsdk.core.console.console_io.CanPrompt',
                    return_value=True)

    self.WriteInput('1\n')
    self.make_requests.side_effect = iter([
        [
            messages.Instance(name='instance-1', zone='zone-1'),
            messages.Instance(name='instance-1', zone='zone-2'),
        ],

        [INSTANCE_WITH_EXTERNAL_ADDRESS],

        [self.project_resource],
    ])
    self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE

    self.Run("""
        compute connect-to-serial-port instance-1
        """)

    self.CheckRequests(
        self.FilteredInstanceAggregateListRequest('instance-1'),

        [(self.GetCompute().instances,
          'Get',
          self.GetMessages().ComputeInstancesGetRequest(
              instance='instance-1',
              project='my-project',
              zone='zone-1'))],

        [(self.GetCompute().projects,
          'Get',
          self.GetMessages().ComputeProjectsGetRequest(
              project='my-project'))],
    )
    self.AssertErrContains('instance-1')
    self.AssertErrContains('zone-1')
    self.AssertErrContains('zone-2')

    # SSH Command
    self.ssh_init.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        ssh.Remote(self.gateway,
                   user='******'),
        identity_file=self.private_key_file,
        options=self.options,
        port='9600')
Esempio n. 19
0
    def SetUp(self):
        self.require_ssh = self.StartObjectPatch(ssh.Environment,
                                                 'RequireSSH',
                                                 autospec=True)
        self.public_key = ssh.Keys.PublicKey('ssh-rsa',
                                             'DATA',
                                             comment='comment')
        self.StartObjectPatch(ssh.Keys,
                              'GetPublicKey',
                              autospec=True,
                              return_value=self.public_key)
        self.ssh_env = self._FakeSSHEnvironment()
        self.env_current = self.StartObjectPatch(ssh.Environment,
                                                 'Current',
                                                 return_value=self.ssh_env)
        self.ensure_keys_exist = self.StartObjectPatch(ssh.Keys,
                                                       'EnsureKeysExist',
                                                       autospec=True)
        self.key_file = '/my/key'
        self.StartObjectPatch(ssh.Keys, 'key_file', self.key_file)

        self.remote = ssh.Remote('host', user='******')
        self.options = {'MyOption': 'Value'}
        connection_details = ssh_common.ConnectionDetails(
            self.remote, self.options)
        self.populate_public_key = self.StartObjectPatch(
            ssh_common,
            'PopulatePublicKey',
            autospec=True,
            return_value=connection_details)

        self.ssh_init = self.StartObjectPatch(ssh.SSHCommand,
                                              '__init__',
                                              return_value=None,
                                              autospec=True)
        self.ssh_run = self.StartObjectPatch(ssh.SSHCommand,
                                             'Run',
                                             autospec=True,
                                             return_value=0)

        self.scp_init = self.StartObjectPatch(ssh.SCPCommand,
                                              '__init__',
                                              return_value=None,
                                              autospec=True)
        self.scp_run = self.StartObjectPatch(ssh.SCPCommand,
                                             'Run',
                                             autospec=True,
                                             return_value=0)
  def testInstanceWithNoExternalIp(self):
    self.make_requests.side_effect = iter([
        [INSTANCE_WITH_NO_EXTERNAL_ADDRESS],
        [self.project_resource],
    ])
    self.mock_http_request.request.return_value = PUBLIC_KEY_RESPONSE

    self.Run("""
        compute connect-to-serial-port instance-2 --zone zone-1
        """)

    self.CheckRequests(
        [(self.GetCompute().instances,
          'Get',
          self.GetMessages().ComputeInstancesGetRequest(
              instance='instance-2',
              project='my-project',
              zone='zone-1'))],
        [(self.GetCompute().projects,
          'Get',
          self.GetMessages().ComputeProjectsGetRequest(
              project='my-project'))],
    )
    # Require SSH keys
    self.ensure_keys.assert_called_once_with(
        self.keys, None, allow_passphrase=True)

    # No polling
    self.poller_poll.assert_not_called()

    # SSH Command
    self.ssh_init.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        ssh.Remote(self.gateway, user='******'),
        identity_file=self.private_key_file,
        options=self.options,
        port='9600')

    self.ssh_run.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.SSHCommand),
        self.env, force_connect=True)

    # Known Hosts
    self.known_hosts_add.assert_called_once_with(
        mock_matchers.TypeMatcher(ssh.KnownHosts),
        '[ssh-serialport.googleapis.com]:9600', PUBLIC_KEY, overwrite=True)
    self.known_hosts_write.assert_called_once()
    self.make_requests.assert_not_called()
Esempio n. 21
0
    def testWithPollingTimeout(self):
        self.poller_poll.side_effect = retry.WaitException(
            'msg', 'result', 'state')
        project_resource = self.messages.Project(name='my-project', )
        self.make_requests.side_effect = iter([
            [self.instance],
            [project_resource],
            [],
        ])

        with self.AssertRaisesExceptionMatches(
                ssh_utils.NetworkError, 'Could not SSH into the instance'):
            self.Run("""\
          compute scp
            hapoo@instance-1:~/remote-file
            ~/local-dir --zone zone-1
          """)

        self.CheckRequests(
            [(self.compute.instances, 'Get',
              self.messages.ComputeInstancesGetRequest(instance='instance-1',
                                                       project='my-project',
                                                       zone='zone-1'))],
            [(self.compute.projects, 'Get',
              self.messages.ComputeProjectsGetRequest(project='my-project'))],
            [(self.compute.projects, 'SetCommonInstanceMetadata',
              self.messages.ComputeProjectsSetCommonInstanceMetadataRequest(
                  metadata=self.messages.Metadata(items=[
                      self.messages.Metadata.ItemsValueListEntry(
                          key='ssh-keys',
                          value='hapoo:' + self.public_key_material),
                  ]),
                  project='my-project'))],
        )

        remote = ssh.Remote(self.remote.host, user='******')
        # Polling
        self.poller_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SSHPoller),
            remote=remote,
            identity_file=self.private_key_file,
            max_wait_ms=ssh_utils.SSH_KEY_PROPAGATION_TIMEOUT_MS,
            options=dict(self.options, HostKeyAlias='compute.11111'),
            extra_flags=None,
            iap_tunnel_args=None)
        self.poller_poll.assert_called_once()

        self.scp_run.assert_not_called()
Esempio n. 22
0
    def testUnknownOsloginApiVarsion(self, oslogin_mock):
        # Should fall through to alternate authentication.
        properties.VALUES.core.account.Set('*****@*****.**')
        self.remote = ssh.Remote('23.251.133.75', user='******')
        oslogin_mock.side_effect = apis_util.UnknownVersionError(
            'oslogin', 'v1')

        self.make_requests.side_effect = iter([
            [INSTANCE_WITH_OSLOGIN_ENABLED],
            [self.project_resource],
        ])

        self.Run("""
        compute ssh instance-1 --zone zone-1
        """)

        self.CheckRequests(
            [(self.compute.instances, 'Get',
              self.messages.ComputeInstancesGetRequest(instance='instance-1',
                                                       project='my-project',
                                                       zone='zone-1'))],
            [(self.compute.projects, 'Get',
              self.messages.ComputeProjectsGetRequest(project='my-project'))],
        )

        # Require SSH keys
        self.ensure_keys.assert_called_once_with(self.keys,
                                                 None,
                                                 allow_passphrase=True)

        # SSH Command
        self.ssh_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SSHCommand),
            remote=self.remote,
            identity_file=self.private_key_file,
            extra_flags=[],
            tty=None,
            options=dict(self.options, HostKeyAlias='compute.44444'),
            remote_command=None,
            iap_tunnel_args=None,
            remainder=[])

        self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher(
            ssh.SSHCommand),
                                             self.env,
                                             force_connect=True)
Esempio n. 23
0
  def Run(self, args):
    command_list = args.command.split(' ') if args.command else None
    connection_info = util.PrepareEnvironment(args)
    command = ssh.SSHCommand(
        remote=ssh.Remote(host=connection_info.host, user=connection_info.user),
        port=str(connection_info.port),
        identity_file=connection_info.key,
        remote_command=containers.GetRemoteCommand(None, command_list),
        extra_flags=args.ssh_flag,
        tty=containers.GetTty(None, args.command),
        options={'StrictHostKeyChecking': 'no'},
    )

    if args.dry_run:
      log.Print(' '.join(command.Build(connection_info.ssh_env)))
    else:
      command.Run(connection_info.ssh_env)
Esempio n. 24
0
    def testWithManyRemoteFilesToLocalDestination(self):
        self.make_requests.side_effect = iter([
            [self.instance],
            [self.project_resource],
        ])

        self.Run(r"""
        compute scp
          instance-1:~/remote-file-1
          instance-1:~/remote-file-2
          instance-1:~/remote-file-3
          ~/local-dir
          --zone zone-1
        """)

        self.CheckRequests(
            [(self.compute.instances, 'Get',
              self.messages.ComputeInstancesGetRequest(instance='instance-1',
                                                       project='my-project',
                                                       zone='zone-1'))],
            [(self.compute.projects, 'Get',
              self.messages.ComputeProjectsGetRequest(project='my-project'))],
        )

        remote = ssh.Remote('23.251.133.1', user='******')

        # SCP Command
        self.scp_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SCPCommand), [
                ssh.FileReference('~/remote-file-1', remote=remote),
                ssh.FileReference('~/remote-file-2', remote=remote),
                ssh.FileReference('~/remote-file-3', remote=remote),
            ],
            self.local_dir,
            identity_file=self.private_key_file,
            extra_flags=[],
            port=None,
            recursive=False,
            compress=False,
            options=dict(self.options, HostKeyAlias='compute.11111'),
            iap_tunnel_args=None)

        self.scp_run.assert_called_once_with(mock_matchers.TypeMatcher(
            ssh.SCPCommand),
                                             self.env,
                                             force_connect=True)
Esempio n. 25
0
  def Run(self, args):
    connection_info = util.PrepareEnvironment(args)
    remote = ssh.Remote(host=connection_info.host, user=connection_info.user)
    command = ssh.SCPCommand(
        sources=[ToFileReference(src, remote) for src in args.sources],
        destination=ToFileReference(args.destination, remote),
        recursive=args.recurse,
        compress=False,
        port=str(connection_info.port),
        identity_file=connection_info.key,
        extra_flags=args.scp_flag,
        options={'StrictHostKeyChecking': 'no'},
    )

    if args.dry_run:
      log.Print(' '.join(command.Build(connection_info.ssh_env)))
    else:
      command.Run(connection_info.ssh_env)
Esempio n. 26
0
    def SSHToInstance(self, args, instance):
        """Helper to manage authentication followed by SSH to the instance."""
        args = self._DefaultArgsForSSH(args)

        external_nat = ssh_utils.GetExternalIPAddress(instance)
        log.status.Print(
            'Trying to SSH to VM with NAT IP:{}'.format(external_nat))
        remote = ssh.Remote(external_nat, ssh.GetDefaultSshUsername())
        args.ssh_key_file = ssh.Keys.DEFAULT_KEY_FILE

        ssh_helper = ssh_utils.BaseSSHCLIHelper()
        ssh_helper.Run(args)
        identity_file = ssh_helper.keys.key_file

        user, _ = ssh_utils.GetUserAndInstance(args.name)
        host_keys = self._GetHostKeyFromInstance(args.zone, ssh_helper,
                                                 instance)
        options = self._GetSSHOptions(args.name, ssh_helper, instance,
                                      host_keys)
        self._WaitForSSHKeysToPropagate(ssh_helper, remote, identity_file,
                                        user, instance, options)

        extra_flags = []
        # Ctpu seems to be forwarding some other ports on what
        # seems like the TPU node. Need to understand better before enabling.
        if args.forward_ports:
            extra_flags.extend([
                '-A', '-L', '6006:localhost:6006', '-L', '8888:localhost:8888'
            ])
        ssh_cmd_args = {
            'remote': remote,
            'identity_file': identity_file,
            'options': options,
            'extra_flags': extra_flags
        }
        cmd = ssh.SSHCommand(**ssh_cmd_args)
        # Errors from SSH itself result in an ssh.CommandError being raised
        return_code = cmd.Run(
            ssh_helper.env,
            force_connect=properties.VALUES.ssh.putty_force_connect.GetBool())
        if return_code:
            # This is the return code of the remote command.  Problems with SSH itself
            # will result in ssh.CommandError being raised above.
            sys.exit(return_code)
Esempio n. 27
0
  def SetUp(self):
    self.api_client = appengine_api_client.AppengineApiClient.GetApiClient()
    self.user = '******'
    self.public_key = ssh.Keys.PublicKey('ssh-rsa', 'DATA', comment='comment')
    self.key_field = '{user}:ssh-rsa DATA {user}'.format(user=self.user)
    self.StartObjectPatch(ssh, 'GetDefaultSshUsername', autospec=True,
                          return_value=self.user)
    self.StartObjectPatch(ssh.KnownHosts, 'DEFAULT_PATH', '/my/hosts')

    mock_project = mock.MagicMock()
    mock_project.CommonInstanceMetadata = {}
    self.StartObjectPatch(ssh_common, '_GetComputeProject', autospec=True,
                          return_value=mock_project)
    self.options = {
        'IdentitiesOnly': 'yes',
        'UserKnownHostsFile': '/my/hosts',
        'CheckHostIP': 'no',
        'HostKeyAlias': 'gae.fakeproject.i2'}
    self.connection_details = ssh_common.ConnectionDetails(
        ssh.Remote('127.0.0.1', user='******'), self.options)
Esempio n. 28
0
    def Run(self, args):
        command_list = args.command.split(' ') if args.command else ['bash -l']
        project = properties.VALUES.core.project.Get()
        connection_info = util.PrepareEnvironment(args)
        command = ssh.SSHCommand(
            remote=ssh.Remote(host=connection_info.host,
                              user=connection_info.user),
            port=str(connection_info.port),
            identity_file=connection_info.key,
            remote_command=(['DEVSHELL_PROJECT_ID=' +
                             project] if project else []) + command_list,
            extra_flags=args.ssh_flag,
            tty=not args.command,
            options={'StrictHostKeyChecking': 'no'},
        )

        if args.dry_run:
            log.Print(' '.join(command.Build(connection_info.ssh_env)))
        else:
            command.Run(connection_info.ssh_env)
Esempio n. 29
0
    def testSSHToInstance(self):
        ssh_util = tpu_utils.SSH(self.track)
        args = SSHTest.Args('fake-name', 'central2-a', True)
        instance = self._makeFakeInstance('fake-instance')

        self.make_requests.side_effect = iter([
            [self._makeFakeProjectResource()],
            [self._makeFakeProjectResource()],
            [self._makeFakeProjectResource()],
        ])

        ssh_util.SSHToInstance(args, instance)

        self.ensure_keys.assert_called_once_with(self.keys,
                                                 None,
                                                 allow_passphrase=True)

        self.poller_poll.assert_called_once_with(mock_matchers.TypeMatcher(
            ssh.SSHPoller),
                                                 self.env,
                                                 force_connect=True)

        # SSH Command
        self.ssh_init.assert_called_once_with(
            mock_matchers.TypeMatcher(ssh.SSHCommand),
            remote=ssh.Remote('23.251.133.75', ssh.GetDefaultSshUsername()),
            identity_file=self.private_key_file,
            extra_flags=[
                '-A', '-L', '6006:localhost:6006', '-L', '8888:localhost:8888'
            ],
            options=dict(
                self.options,
                HostKeyAlias='compute.1111',
                SendEnv='TPU_NAME',
            ))

        self.ssh_run.assert_called_once_with(mock_matchers.TypeMatcher(
            ssh.SSHCommand),
                                             self.env,
                                             force_connect=True)
Esempio n. 30
0
    def Run(self, args):
        if not args.authorize_session:
            log.Print(
                'Automatic authentication with GCP CLI tools in Cloud Shell is '
                'disabled. To enable, please rerun command with '
                '`--authorize-session` flag.')
        command_list = args.command.split(' ') if args.command else ['bash -l']
        project = properties.VALUES.core.project.Get()
        connection_info = util.PrepareEnvironment(args)
        if args.authorize_session:
            util.AuthorizeEnvironment()
        command = ssh.SSHCommand(
            remote=ssh.Remote(host=connection_info.host,
                              user=connection_info.user),
            port=six.text_type(connection_info.port),
            identity_file=connection_info.key,
            remote_command=(['DEVSHELL_PROJECT_ID=' +
                             project] if project else []) + command_list,
            extra_flags=args.ssh_flag,
            tty=not args.command,
            options={'StrictHostKeyChecking': 'no'},
        )

        if args.dry_run:
            elems = command.Build(connection_info.ssh_env)
            log.Print(' '.join([six.moves.shlex_quote(elem)
                                for elem in elems]))
        elif args.authorize_session:
            self.done = threading.Event()
            thread = threading.Thread(target=self.Reauthorize, args=())
            thread.daemon = True
            thread.start()
            command.Run(connection_info.ssh_env)
            self.done.set()
        else:
            command.Run(connection_info.ssh_env)