Example #1
0
    def _GetDiagnosticsServiceAccount(self, project):
        """Locates or creates a service account with the correct permissions.

    Attempts to locate the service account meant for creating the signed url.
    If not found, it will subsequently create the service account. It will then
    give the service account the correct IAM permissions to create a signed url
    to a GCS Bucket.

    Args:
      project: The project to search for the service account in.

    Returns:
      A string email of the service account to use.
    """
        # Search for service account by name.
        service_account = None
        for account in self._diagnose_client.ListServiceAccounts(project):
            if account.email.startswith('{}@'.format(_SERVICE_ACCOUNT_NAME)):
                service_account = account.email

        if service_account is None:
            service_account = self._diagnose_client.CreateServiceAccount(
                project, _SERVICE_ACCOUNT_NAME)

        # We can apply the correct IAM permissions for accessing the GCS Bucket
        # regardless of whether or not the account already has them.
        project_ref = projects_util.ParseProject(project)
        service_account_ref = 'serviceAccount:{}'.format(service_account)
        projects_api.AddIamPolicyBinding(project_ref, service_account_ref,
                                         'roles/storage.objectCreator')
        projects_api.AddIamPolicyBinding(project_ref, service_account_ref,
                                         'roles/storage.objectViewer')

        return service_account
Example #2
0
def _VerifyRolesAndPromptIfMissing(project_id, account, applied_roles,
                                   required_roles):
    """Check for IAM permissions for an account and prompt to add if missing.

  Args:
    project_id: A string with the id of the project.
    account: A string with the identifier of an account.
    applied_roles: A set of strings containing the current roles for the
      account.
    required_roles: A set of strings containing the required roles for the
      account. If a role isn't found, then the user is prompted to add the role.
  """

    # If there were unsatisfied roles, then prompt the user to add them.
    missing_roles = required_roles - applied_roles
    if missing_roles:
        ep_table = ['{0} {1}'.format(role, account) for role in missing_roles]
        prompt_message = (
            'The following IAM permissions are needed for this operation:\n'
            '[{0}]\n'.format('\n'.join(ep_table)))
        console_io.PromptContinue(
            message=prompt_message,
            prompt_string='Would you like to add the permissions',
            throw_if_unattended=True,
            cancel_on_no=False)

        for role in missing_roles:
            log.info('Adding [{0}] to [{1}]'.format(account, role))
            projects_api.AddIamPolicyBinding(project_id, account, role)
Example #3
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.
    """
        client = apis.GetClientInstance('ml', 'v1beta1')
        msgs = apis.GetMessagesModule('ml', 'v1beta1')

        project = properties.VALUES.core.project.Get(required=True)
        project_ref = resources.REGISTRY.Parse(
            project, collection='cloudresourcemanager.projects')
        console_io.PromptContinue(
            message=
            '\nCloud ML needs to add its service accounts to your project '
            '({0}) as Editors. This will enable Cloud Machine Learning to access '
            'resources in your project when running your training and '
            'prediction jobs.'.format(project),
            cancel_on_no=True)

        # Get service account information from cloud ml service.
        req = msgs.MlProjectsGetConfigRequest(projectsId=project)
        resp = client.projects.GetConfig(req)

        # Add cloud ml service account.
        cloud_ml_service_account = 'serviceAccount:' + resp.serviceAccount
        projects_api.AddIamPolicyBinding(project_ref, cloud_ml_service_account,
                                         EDITOR_ROLE)
        log.status.Print('Added {0} as an Editor to project \'{1}\'.'.format(
            cloud_ml_service_account, project))
Example #4
0
def _InitProject(version):
    """Initialize the current project."""
    client = apis.GetClientInstance('ml', version)
    msgs = apis.GetMessagesModule('ml', version)

    project = properties.VALUES.core.project.GetOrFail()
    project_ref = resources.REGISTRY.Create('ml.projects', projectsId=project)
    console_io.PromptContinue(
        message='\nCloud ML Engine needs to add its service accounts to your '
        'project [{0}] as Editors. This will enable Cloud Machine Learning to '
        'access resources in your project when running your training and '
        'prediction jobs. This operation requires OWNER permissions.'.format(
            project),
        cancel_on_no=True)

    # Get service account information from Cloud ML Engine service.
    req = msgs.MlProjectsGetConfigRequest(name=project_ref.RelativeName())
    resp = client.projects.GetConfig(req)

    # Add Cloud ML Engine service account.
    cloud_ml_service_account = 'serviceAccount:' + resp.serviceAccount
    cloudresourcemanager_project_ref = resources.REGISTRY.Create(
        'cloudresourcemanager.projects', projectId=project)
    projects_api.AddIamPolicyBinding(cloudresourcemanager_project_ref,
                                     cloud_ml_service_account, EDITOR_ROLE)
    log.status.Print('Added {0} as an Editor to project \'{1}\'.'.format(
        cloud_ml_service_account, project))
Example #5
0
def CheckIamPermissions(project_id):
    """Check for needed IAM permissions and prompt to add if missing.

  Args:
    project_id: A string with the name of the project.
  """
    project = projects_api.Get(project_id)
    service_account = 'serviceAccount:{0}@cloudbuild.gserviceaccount.com'.format(
        project.projectNumber)
    expected_permissions = {
        'roles/compute.admin': service_account,
        'roles/iam.serviceAccountActor': service_account
    }
    permissions = projects_api.GetIamPolicy(project_id)
    for binding in permissions.bindings:
        if expected_permissions.get(binding.role) in binding.members:
            del expected_permissions[binding.role]

    if expected_permissions:
        ep_table = [
            '{0} {1}'.format(role, account)
            for role, account in expected_permissions.items()
        ]
        prompt_message = (
            'The following IAM permissions are needed for this operation:\n'
            '[{0}]\n'.format('\n'.join(ep_table)))
        console_io.PromptContinue(
            message=prompt_message,
            prompt_string='Would you like to add the permissions',
            throw_if_unattended=True,
            cancel_on_no=True)

        for role, account in expected_permissions.items():
            log.info('Adding [{0}] to [{1}]'.format(account, role))
            projects_api.AddIamPolicyBinding(project_id, account, role)
Example #6
0
    def Run(self, args):
        project_ref = args.CONCEPTS.project.Parse()
        service_account = 'service-' + str(
            project_util.GetProjectNumber(project_ref.projectsId)
        ) + '@gcp-sa-dataplex.iam.gserviceaccount.com'

        if args.IsSpecified('storage_bucket_resource'):
            return storage_api.StorageClient().AddIamPolicyBinding(
                storage_util.BucketReference(args.storage_bucket_resource),
                'serviceAccount:' + service_account,
                'roles/dataplex.serviceAgent')

        if args.IsSpecified('bigquery_dataset_resource'):
            get_dataset_request = apis.GetMessagesModule(
                'bigquery', 'v2').BigqueryDatasetsGetRequest(
                    datasetId=args.bigquery_dataset_resource,
                    projectId=args.secondary_project)
            dataset = apis.GetClientInstance(
                'bigquery', 'v2').datasets.Get(request=get_dataset_request)
            lake.AddServiceAccountToDatasetPolicy(
                apis.GetMessagesModule('bigquery',
                                       'v2').Dataset.AccessValueListEntry,
                dataset, service_account, 'roles/dataplex.serviceAgent')
            return apis.GetClientInstance('bigquery', 'v2').datasets.Patch(
                apis.GetMessagesModule(
                    'bigquery', 'v2').BigqueryDatasetsPatchRequest(
                        datasetId=args.bigquery_dataset_resource,
                        projectId=args.secondary_project,
                        dataset=dataset))

        if args.IsSpecified('project_resource'):
            return projects_api.AddIamPolicyBinding(
                project_util.ParseProject(args.project_resource),
                'serviceAccount:' + service_account,
                'roles/dataplex.serviceAgent')
Example #7
0
def _CheckIamPermissions(project_id, service_account_roles):
  """Check for needed IAM permissions and prompt to add if missing.

  Args:
    project_id: A string with the name of the project.
    service_account_roles: roles to be used by service account in addition to
      compute.admin.
  """
  project = projects_api.Get(project_id)
  # If the user's project doesn't have cloudbuild enabled yet, then the service
  # account won't even exist. If so, then ask to enable it before continuing.
  # Also prompt them to enable Stackdriver Logging if they haven't yet.
  expected_services = ['cloudbuild.googleapis.com', 'logging.googleapis.com']
  for service_name in expected_services:
    if not services_api.IsServiceEnabled(project.projectId, service_name):
      # TODO(b/112757283): Split this out into a separate library.
      prompt_message = (
          'The "{0}" service is not enabled for this project. '
          'It is required for this operation.\n').format(service_name)
      console_io.PromptContinue(
          prompt_message,
          'Would you like to enable this service?',
          throw_if_unattended=True,
          cancel_on_no=True)
      operation = services_api.EnableServiceApiCall(project.projectId,
                                                    service_name)
      # Wait for the operation to finish.
      services_util.ProcessOperationResult(operation, is_async=False)

  # Now that we're sure the service account exists, actually check permissions.
  service_account = 'serviceAccount:{0}@cloudbuild.gserviceaccount.com'.format(
      project.projectNumber)
  expected_permissions = {'roles/compute.admin': service_account}
  if service_account_roles:
    for role in service_account_roles:
      expected_permissions[role] = service_account

  permissions = projects_api.GetIamPolicy(project_id)
  for binding in permissions.bindings:
    if expected_permissions.get(binding.role) in binding.members:
      del expected_permissions[binding.role]

  if expected_permissions:
    ep_table = [
        '{0} {1}'.format(role, account)
        for role, account in expected_permissions.items()
    ]
    prompt_message = (
        'The following IAM permissions are needed for this operation:\n'
        '[{0}]\n'.format('\n'.join(ep_table)))
    console_io.PromptContinue(
        message=prompt_message,
        prompt_string='Would you like to add the permissions',
        throw_if_unattended=True,
        cancel_on_no=True)

    for role, account in expected_permissions.items():
      log.info('Adding [{0}] to [{1}]'.format(account, role))
      projects_api.AddIamPolicyBinding(project_id, account, role)
def CheckIamPermissions(project_id):
    """Check for needed IAM permissions and prompt to add if missing.

  Args:
    project_id: A string with the name of the project.
  """
    project = projects_api.Get(project_id)
    # If the user's project doesn't have cloudbuild enabled yet, then the service
    # account won't even exist. If so, then ask to enable it before continuing.
    cloudbuild_service_name = 'cloudbuild.googleapis.com'
    if not services_api.IsServiceEnabled(project.projectId,
                                         cloudbuild_service_name):
        prompt_message = ('The Google Cloud Build service is not '
                          'enabled for this project. It is required for this '
                          'operation.\n')
        console_io.PromptContinue(
            prompt_message,
            'Would you like to enable Container Builder?',
            throw_if_unattended=True,
            cancel_on_no=True)
        operation = services_api.EnableServiceApiCall(project.projectId,
                                                      cloudbuild_service_name)
        # Wait for the operation to finish.
        services_util.ProcessOperationResult(operation, is_async=False)

    # Now that we're sure the service account exists, actually check permissions.
    service_account = 'serviceAccount:{0}@cloudbuild.gserviceaccount.com'.format(
        project.projectNumber)
    expected_permissions = {
        'roles/compute.admin': service_account,
        'roles/iam.serviceAccountActor': service_account
    }
    permissions = projects_api.GetIamPolicy(project_id)
    for binding in permissions.bindings:
        if expected_permissions.get(binding.role) in binding.members:
            del expected_permissions[binding.role]

    if expected_permissions:
        ep_table = [
            '{0} {1}'.format(role, account)
            for role, account in expected_permissions.items()
        ]
        prompt_message = (
            'The following IAM permissions are needed for this operation:\n'
            '[{0}]\n'.format('\n'.join(ep_table)))
        console_io.PromptContinue(
            message=prompt_message,
            prompt_string='Would you like to add the permissions',
            throw_if_unattended=True,
            cancel_on_no=True)

        for role, account in expected_permissions.items():
            log.info('Adding [{0}] to [{1}]'.format(account, role))
            projects_api.AddIamPolicyBinding(project_id, account, role)
Example #9
0
def _VerifyRolesAndPromptIfMissing(project_id, account, applied_roles,
                                   required_roles):
    """Check for IAM permissions for an account and prompt to add if missing.

  Args:
    project_id: A string with the id of the project.
    account: A string with the identifier of an account.
    applied_roles: A set of strings containing the current roles for the
      account.
    required_roles: A set of strings containing the required roles for the
      account. If a role isn't found, then the user is prompted to add the role.
  """
    # If there were unsatisfied roles, then prompt the user to add them.
    try:
        missing_roles = _FindMissingRoles(applied_roles, required_roles)
    except apitools_exceptions.HttpForbiddenError:
        missing_roles = required_roles - applied_roles

    if not missing_roles:
        return

    ep_table = [
        '{0} {1}'.format(role, account) for role in sorted(missing_roles)
    ]
    prompt_message = (
        'The following IAM permissions are needed for this operation:\n'
        '[{0}]\n'.format('\n'.join(ep_table)))
    add_roles = console_io.PromptContinue(
        message=prompt_message,
        prompt_string='Would you like to add the permissions',
        throw_if_unattended=True,
        cancel_on_no=False)

    if not add_roles:
        return

    for role in sorted(missing_roles):
        log.info('Adding [{0}] to [{1}]'.format(account, role))
        try:
            projects_api.AddIamPolicyBinding(project_id, account, role)
        except apitools_exceptions.HttpForbiddenError:
            log.warning(
                'Your account does not have permission to add roles to the '
                'service account {0}. If import fails, '
                'ensure "{0}" has the roles "{1}" before retrying.'.format(
                    account, required_roles))
            return
 def Run(self, args):
     project_ref = command_lib_util.ParseProject(args.id)
     return projects_api.AddIamPolicyBinding(project_ref, args.member,
                                             args.role)