Ejemplo n.º 1
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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
 def testGetHttpError(self):
   test_project = util.GetTestActiveProject()
   test_project_ref = command_lib_util.ParseProject(test_project.projectId)
   self.mock_client.projects.Get.Expect(
       self.messages.CloudresourcemanagerProjectsGetRequest(
           projectId=test_project.projectId),
       exception=self.HttpError())
   with self.assertRaises(exceptions.HttpError):
     projects_api.Get(test_project_ref)
Ejemplo n.º 4
0
 def testGet(self):
   test_project = util.GetTestActiveProject()
   test_project_ref = command_lib_util.ParseProject(test_project.projectId)
   self.mock_client.projects.Get.Expect(
       self.messages.CloudresourcemanagerProjectsGetRequest(
           projectId=test_project.projectId),
       test_project)
   response = projects_api.Get(test_project_ref)
   self.assertEqual(response, test_project)
Ejemplo n.º 5
0
def _CheckIamPermissions(project_id):
  """Check for needed IAM permissions and prompt to add if missing.

  Args:
    project_id: A string with the id 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.
  # 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)
      services_api.EnableService(project.projectId, service_name)

  # Now that we're sure the service account exists, actually check permissions.
  policy = projects_api.GetIamPolicy(project_id)
  build_account = 'serviceAccount:{0}@cloudbuild.gserviceaccount.com'.format(
      project.projectNumber)
  _VerifyRolesAndPromptIfMissing(
      project_id, build_account, _CurrentRolesForAccount(policy, build_account),
      {
          'roles/compute.admin', 'roles/iam.serviceAccountUser',
          'roles/iam.serviceAccountTokenCreator'
      })

  # https://cloud.google.com/compute/docs/access/service-accounts#default_service_account
  compute_account = (
      'serviceAccount:{0}[email protected]'.format(
          project.projectNumber))
  current_compute_account_roles = _CurrentRolesForAccount(
      policy, compute_account)

  # By default, the Compute Engine service account has the role `roles/editor`
  # applied to it, which is sufficient for import and export. If that's not
  # present, then request the minimal number of permissions.
  if 'roles/editor' not in current_compute_account_roles:
    try:
      _VerifyRolesAndPromptIfMissing(
          project_id, compute_account, current_compute_account_roles,
          {'roles/compute.storageAdmin', 'roles/storage.objectViewer'})
    except apitools_exceptions.HttpForbiddenError:
      log.warning(
          'Your account does not have permission to add roles to the '
          'default compute engine service account. If import fails, '
          'ensure "{0}" has the roles "{1}" and "{2}" before retrying.'.format(
              compute_account, 'roles/compute.storageAdmin',
              'roles/storage.objectViewer'))
Ejemplo n.º 6
0
def _IsExistingProject(project_id):
    project_ref = projects_command_util.ParseProject(project_id)
    try:
        project = projects_api.Get(project_ref)
        return projects_util.IsActive(project)
    except Exception:  # pylint: disable=broad-except
        # Yeah, this isn't great, but there isn't a perfect exception super class
        # that covers both API related errors and network errors.
        return False
Ejemplo n.º 7
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)
    # 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)
def GetAnthosSupportUser(project_id):
    """Get P4SA account name for Anthos Support when user not specified."""
    project_number = projects_api.Get(
        projects_util.ParseProject(project_id)).projectNumber
    endpoint_overrides = properties.VALUES.api_endpoint_overrides.AllValues()
    hub_endpoint_override = endpoint_overrides.get('gkehub', '')
    if not hub_endpoint_override:
        return ANTHOS_SUPPORT_USER.format(project_number=project_number,
                                          instance_name='')
    elif 'autopush-gkehub' in hub_endpoint_override:
        return ANTHOS_SUPPORT_USER.format(project_number=project_number,
                                          instance_name='autopush-')
    else:
        raise memberships_errors.UnknownApiEndpointOverrideError('gkehub')
Ejemplo n.º 9
0
def Describe(project_id: str = None) -> Project:
    """
  Return the protobuf message describing the project.

  project_id: the string ID of the project. If omitted, the current
              configured project is used.

  A helper function ap_to_dict is provided, which also handles a case
  of a missing collection (and returns an empty dict in this case):

     ap_to_dict(proj.labels) -> dict
  """
    if not project_id:
        project_id = GetCurrent()
    # Use the SimpleNamespace ducky instead of the "official" ProjectReference
    # instance, because 'projectId' is all the API wants.
    return _projapi.Get(_Ducky(projectId=project_id))
Ejemplo n.º 10
0
def _WarnIfSettingProjectWithNoAccess(scope, project):
    """Warn if setting 'core/project' config to inaccessible project."""

    # Only display a warning if the following conditions are true:
    #
    # * The current scope is USER (not occurring in the context of installation).
    # * The 'core/account' value is set (a user has authed).
    #
    # If the above conditions are met, check that the project being set exists
    # and is accessible to the current user, otherwise show a warning.
    if (scope == properties.Scope.USER
            and properties.VALUES.core.account.Get()):
        project_ref = command_lib_util.ParseProject(project)
        base.DisableUserProjectQuota()
        try:
            projects_api.Get(project_ref)
        except (apitools_exceptions.HttpError,
                c_store.NoCredentialsForAccountException):
            log.warning('You do not appear to have access to project [{}] or'
                        ' it does not exist.'.format(project))
        finally:
            base.EnableUserProjectQuota()
Ejemplo n.º 11
0
 def _GetProjectNumber(self, project_id):
     """Converts a project id to a project number."""
     project_ref = projects_util.ParseProject(project_id)
     project = projects_api.Get(project_ref)
     return project.projectNumber
Ejemplo n.º 12
0
 def Run(self, args):
     project_ref = command_lib_util.ParseProject(args.id)
     return projects_api.Get(project_ref)
Ejemplo n.º 13
0
def _GetOrganizationId():
    """Gets id of current organization."""
    proj = projects_api.Get(projects_util.ParseProject(_GetProjectName()))
    return (proj.parent.id if proj.parent
            and proj.parent.type == 'organization' else _ORG_ID_PLACE_HOLDER)
Ejemplo n.º 14
0
def GetProjectNumber(project):
    project_id = project or properties.VALUES.core.project.Get(required=True)
    return projects_api.Get(
        projects_util.ParseProject(project_id)).projectNumber
Ejemplo n.º 15
0
def GetProjectNumber(project_id):
  return projects_api.Get(ParseProject(project_id)).projectNumber
Ejemplo n.º 16
0
def _GetProjectNumber(project_id):
    return projects_api.Get(
        projects_util.ParseProject(project_id)).projectNumber
Ejemplo n.º 17
0
def _CheckIamPermissions(project_id, cloudbuild_service_account_roles,
                         compute_service_account_roles,
                         custom_compute_service_account=''):
  """Check for needed IAM permissions and prompt to add if missing.

  Args:
    project_id: A string with the id of the project.
    cloudbuild_service_account_roles: A set of roles required for cloudbuild
      service account.
    compute_service_account_roles: A set of roles required for compute service
      account.
    custom_compute_service_account: Custom compute service account
  """
  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 Cloud Logging if they haven't yet.
  expected_services = ['cloudbuild.googleapis.com', 'logging.googleapis.com',
                       'compute.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)
      enable_service = console_io.PromptContinue(
          prompt_message,
          'Would you like to enable this service?',
          throw_if_unattended=True)
      if enable_service:
        services_api.EnableService(project.projectId, service_name)
      else:
        log.warning(
            'If import fails, manually enable {0} before retrying. For '
            'instructions on enabling services, see '
            'https://cloud.google.com/service-usage/docs/enable-disable.'
            .format(service_name))

  build_account = 'serviceAccount:{0}@cloudbuild.gserviceaccount.com'.format(
      project.projectNumber)
  # https://cloud.google.com/compute/docs/access/service-accounts#default_service_account
  compute_account = (
      'serviceAccount:{0}[email protected]'.format(
          project.projectNumber))
  if custom_compute_service_account:
    compute_account = 'serviceAccount:{0}'.format(
        custom_compute_service_account)

  # Now that we're sure the service account exists, actually check permissions.
  try:
    policy = projects_api.GetIamPolicy(project_id)
  except apitools_exceptions.HttpForbiddenError:
    log.warning(
        'Your account does not have permission to check roles for the '
        'service account {0}. If import fails, '
        'ensure "{0}" has the roles "{1}" and "{2}" has the roles "{3}" before '
        'retrying.'.format(build_account, cloudbuild_service_account_roles,
                           compute_account, compute_service_account_roles))
    return

  _VerifyRolesAndPromptIfMissing(project_id, build_account,
                                 _CurrentRolesForAccount(policy, build_account),
                                 frozenset(cloudbuild_service_account_roles))

  current_compute_account_roles = _CurrentRolesForAccount(
      policy, compute_account)

  # By default, the Compute Engine service account has the role `roles/editor`
  # applied to it, which is sufficient for import and export. If that's not
  # present, then request the minimal number of permissions.
  if ROLE_EDITOR not in current_compute_account_roles:
    _VerifyRolesAndPromptIfMissing(
        project_id, compute_account, current_compute_account_roles,
        compute_service_account_roles)