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')
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)
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')
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')
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)
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)
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)
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()
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()
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()
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]')
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')
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()
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()
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)
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)
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)
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)
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)
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)
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)
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)
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)