Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    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)])
Exemplo n.º 8
0
  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
Exemplo n.º 9
0
    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
Exemplo n.º 10
0
    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
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
    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)
Exemplo n.º 13
0
    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