Esempio n. 1
0
def PromptToEnableApi(project,
                      service_token,
                      exception,
                      is_batch_request=False):
    """Prompts to enable the API and throws if the answer is no.

  Args:
    project (str): The project that the API is not enabled on.
    service_token (str): The service token of the API to prompt for.
    exception (api_Exceptions.HttpException): Exception to throw if the prompt
      is denied.
    is_batch_request: If the request is a batch request. This determines how to
      get apitools to retry the request.

  Raises:
    api_exceptions.HttpException: API not enabled error if the user chooses to
      not enable the API.
  """
    if console_io.PromptContinue(
            default=False,
            prompt_string=(
                'API [{}] not enabled on project [{}]. '
                'Would you like to enable and retry (this will take a '
                'few minutes)?').format(service_token, project)):
        enable_api.EnableService(project, service_token)
        # In the case of a batch request, as long as the error's retryable code
        # (in this case 403) was set, after this runs it should retry. This
        # error code should be consistent with apis.GetApiEnablementInfo
        if not is_batch_request:
            raise apitools_exceptions.RequestError('Retry')
    else:
        raise exception
Esempio n. 2
0
    def SetUp(self):
        self.name_generator = e2e_utils.GetResourceNameGenerator('sdk-e2e')
        project_name = next(self.name_generator)
        self.project_id = command_lib_util.IdFromName(project_name)
        self.project_ref = command_lib_util.ParseProject(self.project_id)
        create_op = projects_api.Create(
            self.project_ref,
            parent=projects_api.ParentNameToResourceId(
                CLOUD_SDK_TESTING_FOLDER_ID))
        log.CreatedResource(self.project_ref, is_async=True)
        operations.WaitForOperation(create_op)

        log.debug('Enabling cloudapis.googleapis.com')
        services_enable_api.EnableService(self.project_ref.Name(),
                                          'cloudapis.googleapis.com')

        self.Run('services enable cloudbilling')
        self.Run(('alpha billing accounts projects link {project} '
                  '--account-id={billing}').format(project=self.project_id,
                                                   billing=self.BillingId()))
        self.Run('projects add-iam-policy-binding {project} '
                 '--member="group:[email protected]" '
                 '--role="roles/owner"'.format(project=self.project_id))

        properties.VALUES.core.disable_prompts.Set(True)
        # This is set to false by sdk_test_base.SdkBase.
        properties.VALUES.core.should_prompt_to_enable_api.Set(True)
        # The api enablement check will prompt, and this will inject a yes into that
        self.StartPatch(
            'googlecloudsdk.core.console.console_io.PromptContinue',
            return_value=True)
Esempio n. 3
0
    def check_prerequisite(self):
        log.status.Print('---- Checking network connectivity ----')
        msg = (
            'The Network Management API is needed to check the VM\'s network '
            'connectivity.')
        prompt = 'Is it OK to enable it and check the VM\'s network connectivity?'
        cancel = (
            'Test skipped.\n'
            'To manually test network connectivity, try reaching another '
            'device on the same network.\n')
        try:
            prompt_continue = console_io.PromptContinue(message=msg,
                                                        prompt_string=prompt,
                                                        cancel_on_no=True,
                                                        cancel_string=cancel)
            self.skip_troubleshoot = not prompt_continue
        except OperationCancelledError:
            self.skip_troubleshoot = True

        if self.skip_troubleshoot:
            return

        # Enable API
        enable_api.EnableService(self.project.name, NETWORK_API)
        # Test IAM Permission
        missing_permissions = self._CheckNetworkManagementPermissions()

        if missing_permissions:
            log.status.Print(
                'Missing the IAM permissions {0} necessary to perform the network '
                'connectivity test. To manually test network connectivity, try '
                'reaching another device on the same network.\n'.format(
                    ' '.join(missing_permissions)))
            self.skip_troubleshoot = True
            return
Esempio n. 4
0
    def testEnableApiDoneCall_Success(self):
        """Test EnableService."""
        self.ExpectEnableApiCall(self.OPERATION_NAME, done=True)

        enable_api.EnableService(self.PROJECT_NAME, self.DEFAULT_SERVICE_NAME)
        self.AssertErrContains("""\
Enabling service [service-name.googleapis.com] on project [fake-project]...
""")
Esempio 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'))
Esempio n. 6
0
    def testEnableApiCall_Success(self):
        """Test EnableService."""
        self.ExpectEnableApiCall(self.OPERATION_NAME)
        self.ExpectOperation(self.OPERATION_NAME, 0)

        enable_api.EnableService(self.PROJECT_NAME, self.DEFAULT_SERVICE_NAME)
        self.AssertErrContains("""\
Enabling service [service-name.googleapis.com] on project [fake-project]...
Operation "operations/abc.0000000000" finished successfully.
""")
Esempio 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.
    # 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.
    service_account = 'serviceAccount:{0}@cloudbuild.gserviceaccount.com'.format(
        project.projectNumber)
    expected_permissions = {'roles/compute.admin': service_account}
    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)
Esempio n. 8
0
    def Run(self, args):
        """Default Run method implementation."""

        flags.CheckParentFlags(args, parent_required=False)
        project_id = args.id
        if not project_id and args.name:
            candidate = command_lib_util.IdFromName(args.name)
            if candidate and console_io.PromptContinue(
                    'No project id provided.',
                    'Use [{}] as project id'.format(candidate),
                    throw_if_unattended=True):
                project_id = candidate
        if not project_id:
            raise exceptions.RequiredArgumentException(
                'PROJECT_ID', 'an id must be provided for the new project')
        project_ref = command_lib_util.ParseProject(project_id)
        labels = labels_util.ParseCreateArgs(
            args,
            projects_util.GetMessages().Project.LabelsValue)
        try:
            create_op = projects_api.Create(
                project_ref,
                display_name=args.name,
                parent=projects_api.ParentNameToResourceId(
                    flags.GetParentFromFlags(args)),
                labels=labels)
        except apitools_exceptions.HttpConflictError:
            msg = (
                'Project creation failed. The project ID you specified is '
                'already in use by another project. Please try an alternative '
                'ID.')
            core_exceptions.reraise(exceptions.HttpException(msg))
        log.CreatedResource(project_ref, is_async=True)
        create_op = operations.WaitForOperation(create_op)

        # Enable cloudapis.googleapis.com
        if args.enable_cloud_apis:
            log.debug('Enabling cloudapis.googleapis.com')
            enable_api.EnableService(project_ref.Name(),
                                     'cloudapis.googleapis.com')

        if args.set_as_default:
            project_property = properties.FromString('core/project')
            properties.PersistProperty(project_property, project_id)
            log.status.Print(
                'Updated property [core/project] to [{0}].'.format(project_id))

        return operations.ExtractOperationResponse(
            create_op,
            apis.GetMessagesModule('cloudresourcemanager', 'v1').Project)
Esempio n. 9
0
def CheckForAssetInventoryEnablementWithPrompt(project=None):
  """Checks if the cloudasset API is enabled, prompts to enable if not."""
  project = project or properties.VALUES.core.project.GetOrFail()
  service_name = 'cloudasset.googleapis.com'
  if not enable_api.IsServiceEnabled(project, service_name):
    if console_io.PromptContinue(
        default=False,
        prompt_string=(
            'API [{}] is required to continue, but is not enabled on project [{}]. '
            'Would you like to enable and retry (this will take a '
            'few minutes)?').format(service_name, project)):
      enable_api.EnableService(project, service_name)
    else:
      raise AssetInventoryNotEnabledException(
          'Aborted by user: API [{}] must be enabled on project [{}] to continue.'
          .format(service_name, project))
Esempio n. 10
0
  def AttemptToEnableService(self, service_name, is_async):
    """Attempt to enable a service. If lacking permission, log a warning.

    Args:
      service_name: The service to enable.
      is_async: If true, return immediately instead of waiting for the operation
          to finish.
    """
    project_id = properties.VALUES.core.project.Get(required=True)
    try:
      # Enable the produced service.
      enable_api.EnableService(project_id, service_name, is_async)
    except services_exceptions.EnableServicePermissionDeniedException:
      log.warning(('Attempted to enable service [{0}] on project [{1}], but '
                   'did not have required permissions. Please ensure this '
                   'service is enabled before using your Endpoints '
                   'service.').format(service_name, project_id))
Esempio n. 11
0
def PromptToEnableApi(project, service_token):
    """Prompts to enable the API.

  Args:
    project (str): The project that the API is not enabled on.
    service_token (str): The service token of the API to prompt for.

  Returns:
    bool, whether or not the API was attempted to be enabled
  """
    api_enable_attempted = console_io.PromptContinue(
        default=False,
        prompt_string=('API [{}] not enabled on project [{}]. '
                       'Would you like to enable and retry (this will take a '
                       'few minutes)?').format(service_token, project))
    if api_enable_attempted:
        enable_api.EnableService(project, service_token)
    return api_enable_attempted
Esempio n. 12
0
def PromptToEnableApi(service_name):
  """Prompts to enable the API and throws if the answer is no.

  Args:
    service_name: str, The service token of the API to prompt for.
  """
  if not properties.VALUES.core.should_prompt_to_enable_api.GetBool():
    return

  project = properties.VALUES.core.project.Get(required=True)
  # Don't prompt to enable an already enabled API
  if not enable_api.IsServiceEnabled(project, service_name):
    if console_io.PromptContinue(
        default=False,
        cancel_on_no=True,
        prompt_string=('API [{}] not enabled on project [{}]. '
                       'Would you like to enable and retry (this will take a '
                       'few minutes)?').format(service_name, project)):
      enable_api.EnableService(project, service_name)
Esempio n. 13
0
    def check_prerequisite(self):
        log.status.Print('---- Checking VM status ----')
        msg = 'The Monitoring API is needed to check the VM\'s Status.'
        prompt = 'Is it OK to enable it and check the VM\'s Status?'
        cancel = 'Test skipped.'
        try:
            prompt_continue = console_io.PromptContinue(message=msg,
                                                        prompt_string=prompt,
                                                        cancel_on_no=True,
                                                        cancel_string=cancel)
            self.skip_troubleshoot = not prompt_continue
        except OperationCancelledError:
            self.skip_troubleshoot = True

        if self.skip_troubleshoot:
            return

        # Enable API
        enable_api.EnableService(self.project.name, MONITORING_API)
Esempio n. 14
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)