def Run(self, args): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client name = args.name if not name: name = gaia.GetDefaultAccountName(client.http) user_ref = holder.resources.Parse( name, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.users') if args.fingerprints: fingerprints = args.fingerprints else: fetcher = users_client.UserResourceFetcher( client, user_ref.project, client.http, compute_holder.client.batch_url) fingerprints = [ k.fingerprint for k in fetcher.LookupUser(user_ref.Name()).publicKeys ] # Generate warning before deleting. prompt_list = [ '[{0}]'.format(fingerprint) for fingerprint in fingerprints ] prompt_title = ( 'The following public keys will be removed from the user ' + user_ref.Name()) utils.PromptForDeletionHelper(None, prompt_list, prompt_title=prompt_title) requests = [] for fingerprint in fingerprints: request = (client.MESSAGES_MODULE. ClouduseraccountsUsersRemovePublicKeyRequest( project=user_ref.project, fingerprint=fingerprint, user=user_ref.Name())) requests.append((client.users, 'RemovePublicKey', request)) return compute_holder.client.MakeRequests(requests)
def Run(self, args): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client name = args.name if not name: name = gaia.GetDefaultAccountName(client.http) user_ref = holder.resources.Parse( name, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.users') valid_key_types = [ 'ssh-rsa', 'ssh-dss', 'ecdsa-sha2-nistp256', 'ssh-ed25519' ] public_keys = [] for key_file in args.public_key_files: key_text = file_utils.ReadFile(key_file, 'public-key') if key_text.split(' ', 1)[0] not in valid_key_types: raise exceptions.ToolException( 'You must specify a public key file that contains a key of a ' 'supported form. Supported forms are {0}.'.format( ', '.join(valid_key_types))) public_keys.append(key_text) formatted_expiration = time_util.CalculateExpiration(args.expire) requests = [] for key in public_keys: public_key_message = client.MESSAGES_MODULE.PublicKey( description=args.description, expirationTimestamp=formatted_expiration, key=key) request = (client.MESSAGES_MODULE. ClouduseraccountsUsersAddPublicKeyRequest( project=user_ref.project, publicKey=public_key_message, user=user_ref.Name())) requests.append((client.users, 'AddPublicKey', request)) return compute_holder.client.MakeRequests(requests)
def Run(self, args): holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client user_refs = [ holder.resources.Parse( user, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.users') for user in args.members ] group_refs = [ holder.resources.Parse( group, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.groups') for group in args.names ] requests = [] for group_ref in group_refs: for user_ref in user_refs: remove_member = client.MESSAGES_MODULE.GroupsRemoveMemberRequest( users=[user_ref.SelfLink()]) request = (client.MESSAGES_MODULE. ClouduseraccountsGroupsRemoveMemberRequest( project=group_ref.project, groupsRemoveMemberRequest=remove_member, groupName=group_ref.Name())) requests.append((client.groups, 'RemoveMember', request)) errors = [] responses = list( request_helper.MakeRequests( requests=requests, http=client.http, batch_url='https://www.googleapis.com/batch/', errors=errors)) if errors: utils.RaiseToolException(errors, error_message='Could not fetch resource:') return responses
def Run(self, args): """See scp_utils.BaseScpCommand.Run.""" holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) cua_holder = base_classes.ComputeUserAccountsApiHolder( self.ReleaseTrack()) scp_helper = scp_utils.BaseScpHelper() extra_flags = [] # TODO(b/33467618): Add -C to SCPCommand if args.scp_flag: extra_flags.extend(args.scp_flag) return scp_helper.RunScp(holder, cua_holder, args, port=args.port, recursive=args.recurse, compress=args.compress, extra_flags=extra_flags, use_account_service=False)
def Run(self, args): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client group_refs = [ holder.resources.Parse( group, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.groups') for group in args.names ] utils.PromptForDeletion(group_refs) requests = [] for group_ref in group_refs: request = client.MESSAGES_MODULE.ClouduseraccountsGroupsDeleteRequest( project=group_ref.project, groupName=group_ref.Name()) requests.append((client.groups, 'Delete', request)) return compute_holder.client.MakeRequests(requests)
def Run(self, args): holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) cua_holder = base_classes.ComputeUserAccountsApiHolder( self.ReleaseTrack()) client = holder.client request_data = lister.ParseNamesAndRegexpFlags(args, holder.resources) errors = [] for item in lister.GetGlobalResourcesDicts( service=cua_holder.client.users, project=list(request_data.scope_set)[0].project, filter_expr=request_data.filter, http=client.apitools_client.http, batch_url='https://www.googleapis.com/batch/', errors=errors): yield item if errors: utils.RaiseToolException(errors)
def Run(self, args): """Issues requests necessary for describing users.""" compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client user = args.name if not user: user = gaia.GetDefaultAccountName( compute_holder.client.apitools_client.http) user_ref = holder.resources.Parse( user, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.users') request = client.MESSAGES_MODULE.ClouduseraccountsUsersGetRequest( project=user_ref.project, user=user_ref.Name()) return compute_holder.client.MakeRequests([(client.users, 'Get', request)])
def Run(self, args): """Issues requests necessary for adding users.""" holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client owner = args.owner if not owner: owner = gaia.GetAuthenticatedGaiaEmail(client.http) name = args.name if not name: name = gaia.MapGaiaEmailToDefaultAccountName(owner) user_ref = holder.resources.Parse( name, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.users') user = client.MESSAGES_MODULE.User( name=user_ref.Name(), description=args.description, owner=owner, ) request = client.MESSAGES_MODULE.ClouduseraccountsUsersInsertRequest( project=user_ref.project, user=user) errors = [] responses = list( request_helper.MakeRequests( requests=[(client.users, 'Insert', request)], http=client.http, batch_url='https://www.googleapis.com/batch/', errors=errors)) if errors: utils.RaiseToolException( errors, error_message='Could not fetch resource:') return responses
def Run(self, args): """Issues requests necessary for describing groups.""" holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client group_ref = holder.resources.Parse( args.name, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.groups') request = client.MESSAGES_MODULE.ClouduseraccountsGroupsGetRequest( project=group_ref.project, groupName=group_ref.Name()) errors = [] responses = list( request_helper.MakeRequests( requests=[(client.groups, 'Get', request)], http=client.http, batch_url='https://www.googleapis.com/batch/', errors=errors)) if errors: utils.RaiseToolException(errors, error_message='Could not fetch resource:') return responses
def Run(self, args): """Issues requests necessary for deleting users.""" holder = base_classes.ComputeUserAccountsApiHolder(self.ReleaseTrack()) client = holder.client if args.owners: names = self.GetOwnerAccounts(client, args.names) else: names = args.names user_refs = [ holder.resources.Parse( user, params={'project': properties.VALUES.core.project.GetOrFail}, collection='clouduseraccounts.users') for user in names ] utils.PromptForDeletion(user_refs) requests = [] for user_ref in user_refs: request = client.MESSAGES_MODULE.ClouduseraccountsUsersDeleteRequest( project=user_ref.project, user=user_ref.Name()) requests.append((client.users, 'Delete', request)) errors = [] responses = list( request_helper.MakeRequests( requests=requests, http=client.http, batch_url='https://www.googleapis.com/batch/', errors=errors)) if errors: utils.RaiseToolException(errors, error_message='Could not fetch resource:') return responses
def Run(self, args): """See ssh_utils.BaseSSHCommand.Run.""" holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) cua_holder = base_classes.ComputeUserAccountsApiHolder( self.ReleaseTrack()) client = holder.client ssh_helper = ssh_utils.BaseSSHHelper() ssh_helper.Run(args) ssh_helper.keys.EnsureKeysExist(args.force_key_file_overwrite, allow_passphrase=True) remote = ssh.Remote.FromArg(args.user_host) if not remote: raise ssh_utils.ArgumentError( 'Expected argument of the form [USER@]INSTANCE. Received [{0}].' .format(args.user_host)) if not remote.user: remote.user = ssh.GetDefaultSshUsername() hostname = '[{0}]:{1}'.format(args.serial_port_gateway, CONNECTION_PORT) # Update google_compute_known_hosts file with published host key if args.serial_port_gateway == SERIAL_PORT_GATEWAY: http_client = http.Http() http_response = http_client.request(HOST_KEY_URL) known_hosts = ssh.KnownHosts.FromDefaultFile() if http_response[0]['status'] == '200': host_key = http_response[1].strip() known_hosts.Add(hostname, host_key, overwrite=True) known_hosts.Write() elif known_hosts.ContainsAlias(hostname): log.warn( 'Unable to download and update Host Key for [{0}] from [{1}]. ' 'Attempting to connect using existing Host Key in [{2}]. If ' 'the connection fails, please try again to update the Host ' 'Key.'.format(SERIAL_PORT_GATEWAY, HOST_KEY_URL, known_hosts.file_path)) else: known_hosts.Add(hostname, DEFAULT_HOST_KEY) known_hosts.Write() log.warn( 'Unable to download Host Key for [{0}] from [{1}]. To ensure ' 'the security of the SSH connetion, gcloud will attempt to ' 'connect using a hard-coded Host Key value. If the connection ' 'fails, please try again. If the problem persists, try ' 'updating gcloud and connecting again.'.format( SERIAL_PORT_GATEWAY, HOST_KEY_URL)) instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources( [remote.host], compute_scope.ScopeEnum.ZONE, args.zone, holder.resources, scope_lister=instance_flags.GetInstanceZoneScopeLister(client))[0] instance = ssh_helper.GetInstance(client, instance_ref) project = ssh_helper.GetProject(client, instance_ref.project) # Determine the serial user, host tuple (remote) port = 'port={0}'.format(args.port) constructed_username_list = [ instance_ref.project, instance_ref.zone, instance_ref.Name(), remote.user, port ] if args.extra_args: for k, v in args.extra_args.items(): constructed_username_list.append('{0}={1}'.format(k, v)) serial_user = '******'.join(constructed_username_list) serial_remote = ssh.Remote(args.serial_port_gateway, user=serial_user) identity_file = ssh_helper.keys.key_file options = ssh_helper.GetConfig(hostname, strict_host_key_checking='yes') del options['HostKeyAlias'] cmd = ssh.SSHCommand(serial_remote, identity_file=identity_file, port=CONNECTION_PORT, options=options) if args.dry_run: log.out.Print(' '.join(cmd.Build(ssh_helper.env))) return ssh_helper.EnsureSSHKeyExists(client, cua_holder.client, remote.user, instance, project) # Don't wait for the instance to become SSHable. We are not connecting to # the instance itself through SSH, so the instance doesn't need to have # fully booted to connect to the serial port. Also, ignore exit code 255, # since the normal way to terminate the serial port connection is ~. and # that causes ssh to exit with 255. try: return_code = cmd.Run(ssh_helper.env, force_connect=True) except ssh.CommandError: return_code = 255 if return_code: sys.exit(return_code)
def Run(self, args): """See ssh_utils.BaseSSHCLICommand.Run.""" holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) cua_holder = base_classes.ComputeUserAccountsApiHolder( self.ReleaseTrack()) client = holder.client ssh_helper = ssh_utils.BaseSSHCLIHelper() ssh_helper.Run(args) user, instance_name = ssh_utils.GetUserAndInstance( args.user_host, self._use_account_service, client.apitools_client.http) instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources( [instance_name], compute_scope.ScopeEnum.ZONE, args.zone, holder.resources, scope_lister=instance_flags.GetInstanceZoneScopeLister(client))[0] instance = ssh_helper.GetInstance(client, instance_ref) project = ssh_helper.GetProject(client, instance_ref.project) if args.plain: use_oslogin = False else: user, use_oslogin = ssh_helper.CheckForOsloginAndGetUser( instance, project, user, self.ReleaseTrack(), client.apitools_client.http) if self._use_internal_ip: ip_address = ssh_utils.GetInternalIPAddress(instance) else: ip_address = ssh_utils.GetExternalIPAddress(instance) remote = ssh.Remote(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 = [] remainder = [] if args.ssh_flag: for flag in args.ssh_flag: for flag_part in flag.split(): # We want grouping here dereferenced_flag = (flag_part.replace( '%USER%', remote.user).replace('%INSTANCE%', ip_address)) extra_flags.append(dereferenced_flag) if args.ssh_args: remainder.extend(args.ssh_args) # Transform args.command into arg list or None if no command command_list = args.command.split(' ') if args.command else None tty = containers.GetTty(args.container, command_list) remote_command = containers.GetRemoteCommand(args.container, command_list) cmd = ssh.SSHCommand(remote, identity_file=identity_file, options=options, extra_flags=extra_flags, remote_command=remote_command, tty=tty, remainder=remainder) if args.dry_run: log.out.Print(' '.join(cmd.Build(ssh_helper.env))) return if args.plain or use_oslogin: keys_newly_added = False else: keys_newly_added = ssh_helper.EnsureSSHKeyExists( client, cua_holder.client, remote.user, instance, project, use_account_service=self._use_account_service) if keys_newly_added: poller = ssh.SSHPoller( remote, identity_file=identity_file, options=options, extra_flags=extra_flags, max_wait_ms=ssh_utils.SSH_KEY_PROPAGATION_TIMEOUT_SEC) log.status.Print('Waiting for SSH key to propagate.') # TODO(b/35355795): Don't force_connect try: poller.Poll(ssh_helper.env, force_connect=True) except retry.WaitException: raise ssh_utils.NetworkError() if self._use_internal_ip: ssh_helper.PreliminarylyVerifyInstance(instance.id, remote, identity_file, options) return_code = cmd.Run(ssh_helper.env, force_connect=True) if return_code: # Can't raise an exception because we don't want any "ERROR" message # printed; the output from `ssh` will be enough. sys.exit(return_code)
def Run(self, args): """Yields zonal, regional, and/or global resources.""" compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) cua_holder = base_classes.ComputeUserAccountsApiHolder( self.ReleaseTrack()) compute_client = compute_holder.client cua_client = cua_holder.client # This is True if the user provided no flags indicating scope. no_scope_flags = self.NoArguments(args) requests = [] request_data = lister.ParseNamesAndRegexpFlags( args, compute_holder.resources) # TODO(b/36050874): Start using aggregatedList for zones and regions when # the operations list API supports them. if no_scope_flags: requests.append( (compute_client.apitools_client.globalOperations, 'AggregatedList', compute_client.apitools_client.globalOperations. GetRequestType('AggregatedList')( filter=request_data.filter, maxResults=request_data.max_results, project=list(request_data.scope_set)[0].project))) if self.ReleaseTrack() != base.ReleaseTrack.GA: # Add a request to get all Compute Account operations. requests.append(( cua_client.globalAccountsOperations, 'List', cua_client.globalAccountsOperations.GetRequestType('List')( filter=request_data.filter, maxResults=request_data.max_results, project=list(request_data.scope_set)[0].project))) else: if getattr(args, 'global'): requests.append( (compute_client.apitools_client.globalOperations, 'List', compute_client.apitools_client.globalOperations. GetRequestType('List')( filter=request_data.filter, maxResults=request_data.max_results, project=list(request_data.scope_set)[0].project))) if args.regions is not None: args_region_names = [ compute_holder.resources.Parse( region, params={ 'project': properties.VALUES.core.project.GetOrFail }, collection='compute.regions').Name() for region in args.regions or [] ] # If no regions were provided by the user, fetch a list. errors = [] region_names = (args_region_names or [ res.name for res in lister.GetGlobalResources( service=compute_client.apitools_client.regions, project=properties.VALUES.core.project.GetOrFail(), filter_expr=None, http=compute_client.apitools_client.http, batch_url=compute_client.batch_url, errors=errors) ]) if errors: utils.RaiseToolException( errors, 'Unable to fetch a list of regions. Specifying [--regions] may ' 'fix this issue:') for region_name in region_names: requests.append( (compute_client.apitools_client.regionOperations, 'List', compute_client.apitools_client.regionOperations. GetRequestType('List')( filter=request_data.filter, maxResults=request_data.max_results, region=region_name, project=list(request_data.scope_set)[0].project))) if args.zones is not None: args_zone_names = [ compute_holder.resources.Parse( zone, params={ 'project': properties.VALUES.core.project.GetOrFail, }, collection='compute.zones').Name() for zone in args.zones or [] ] # If no zones were provided by the user, fetch a list. errors = [] zone_names = (args_zone_names or [ res.name for res in lister.GetGlobalResources( service=compute_client.apitools_client.zones, project=properties.VALUES.core.project.GetOrFail(), filter_expr=None, http=compute_client.apitools_client.http, batch_url=compute_client.batch_url, errors=errors) ]) if errors: utils.RaiseToolException( errors, 'Unable to fetch a list of zones. Specifying [--zones] may ' 'fix this issue:') for zone_name in zone_names: requests.append( (compute_client.apitools_client.zoneOperations, 'List', compute_client.apitools_client.zoneOperations. GetRequestType('List')( filter=request_data.filter, maxResults=request_data.max_results, zone=zone_name, project=list(request_data.scope_set)[0].project))) if self.ReleaseTrack() != base.ReleaseTrack.GA and args.accounts: requests.append(( cua_client.globalAccountsOperations, 'List', cua_client.globalAccountsOperations.GetRequestType('List')( filter=request_data.filter, maxResults=request_data.max_results, project=list(request_data.scope_set)[0].project))) errors = [] results = list( request_helper.ListJson(requests=requests, http=compute_client.apitools_client.http, batch_url=compute_client.batch_url, errors=errors)) if errors: utils.RaiseToolException(errors) return results