def testComputeInstancesEnablement(self): service = 'compute.googleapis.com' self.assertFalse( services_enable_api.IsServiceEnabled(self.project_id, service)) self._Run('compute instances list') self.assertTrue( services_enable_api.IsServiceEnabled(self.project_id, service))
def testComputeInstancesEnablement(self): service = 'compute.googleapis.com' self.assertFalse( services_enable_api.IsServiceEnabled(self.project_id, service)) instance_name = next(self.name_generator) self._Run('compute instances create --zone=us-east1-d {}'.format( instance_name)) self._Run('compute instances list') self.AssertOutputContains(instance_name) self.assertTrue( services_enable_api.IsServiceEnabled(self.project_id, service))
def DisplayProposedConfigDeployments(project, configs): """Prints the details of the proposed config deployments. Args: project: The name of the current project. configs: [yaml_parsing.ConfigYamlInfo], The configurations being deployed. """ log.status.Print('Configurations to update:\n') for c in configs: log.status.Print(DEPLOY_CONFIG_MESSAGE_TEMPLATE.format( project=project, type=CONFIG_TYPES[c.config], descriptor=c.file)) if c.name == yaml_parsing.ConfigYamlInfo.QUEUE: # If useful, this logic can be broken out and moved to enable_api.py, # under IsServiceMaybeEnabled(...) or similar. try: api_maybe_enabled = enable_api.IsServiceEnabled( project, 'cloudtasks.googleapis.com') except s_exceptions.ListServicesPermissionDeniedException: api_maybe_enabled = True # We can't know, so presume it is enabled if api_maybe_enabled: # Display this warning with a false positive rate for when the Service # Manangement API is not enabled or accessible. log.warning(QUEUE_TASKS_WARNING)
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 _IsResourceSettingsEnabled(project): api_endpoint = apis.GetEffectiveApiEndpoint( resourcesettings_service.RESOURCE_SETTINGS_API_NAME, resourcesettings_service.RESOURCE_SETTINGS_API_VERSION) # removes initial https:// and trailing slash api_endpoint = re.sub(r'https://(.*)/', r'\1', api_endpoint) return enable_api.IsServiceEnabled(project, api_endpoint)
def testDoesntUseResourceQuota(self): mock_http_client = self.StartObjectPatch(http, 'Http') mock_http_client.return_value.request.return_value = \ (httplib2.Response({'status': 200}), b'') self.request_mock = mock_http_client.return_value.request properties.VALUES.core.project.Set('myproject') enable_api.IsServiceEnabled('myproj', 'service1.googleapis.com') self.assertNotIn(b'X-Goog-User-Project', self.request_mock.call_args[0][3])
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'))
def testIsServiceEnabled_OtherError(self): """Test IsServiceEnabled raises HttpError when expected.""" server_error = http_error.MakeDetailedHttpError( code=401, message='Something else.') self.ExpectGetService(None, error=server_error) with self.assertRaisesRegex(apitools_exceptions.HttpError, r'Something else.'): enable_api.IsServiceEnabled(self.PROJECT_NAME, self.DEFAULT_SERVICE_NAME)
def testIsServiceEnabled_PermissionsError(self): """Test IsServiceEnabled raises PermissionsError when expected.""" server_error = http_error.MakeDetailedHttpError(code=403, message='Something.') self.ExpectGetService(None, error=server_error) with self.assertRaisesRegex( exceptions.GetServicePermissionDeniedException, r'Something.'): enable_api.IsServiceEnabled(self.PROJECT_NAME, self.DEFAULT_SERVICE_NAME)
def testIsServiceEnabled_False(self): """Test IsServiceEnabled when result is False.""" service = self._NewServiceConfig(self.PROJECT_NAME, self.DEFAULT_SERVICE_NAME, enabled=False) self.ExpectGetService(service) self.assertFalse( enable_api.IsServiceEnabled(self.PROJECT_NAME, self.DEFAULT_SERVICE_NAME))
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 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))
def CheckForContainerFileSystemApiEnablementWithPrompt(project): """Checks if the Container File System API is enabled.""" service_name = 'containerfilesystem.googleapis.com' try: if not enable_api.IsServiceEnabled(project, service_name): log.warning( 'Container File System API (containerfilesystem.googleapis.com) has not been enabled on the project. ' 'Please enable it for image streaming to fully work. ' 'For additional details, please refer to https://cloud.google.com/kubernetes-engine/docs/how-to/image-streaming#requirements' ) except (exceptions.GetServicePermissionDeniedException, apitools_exceptions.HttpError): log.warning( 'Failed to check if Container File System API (containerfilesystem.googleapis.com) has been enabled. ' 'Please make sure to enable it for image streaming to work. ' 'For additional details, please refer to https://cloud.google.com/kubernetes-engine/docs/how-to/image-streaming#requirements' )
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)
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)