feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The super-group for policy-intelligence CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.DefaultUniverseOnly
@base.Hidden
class PolicyIntelligenceAlpha(base.Group):
"""A platform to help better understand, use, and manage policies at scale."""
category = base.IDENTITY_AND_SECURITY_CATEGORY
def Filter(self, context, args):
"""Enables User-Project override for this surface."""
base.EnableUserProjectQuota()
# TODO(b/190538573): Determine if command group works with project number
base.RequireProjectID(args)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.DefaultUniverseOnly
class PolicyIntelligenceBeta(base.Group):
"""A platform to help better understand, use, and manage policies at scale."""
category = base.IDENTITY_AND_SECURITY_CATEGORY
def Filter(self, context, args):
"""Enables User-Project override for this surface."""
base.EnableUserProjectQuota()
# TODO(b/190538573): Determine if command group works with project number
base.RequireProjectID(args)
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class PolicyIntelligenceGA(base.Group):
"""A platform to help better understand, use, and manage policies at scale."""
category = base.IDENTITY_AND_SECURITY_CATEGORY
def Filter(self, context, args):
"""Enables User-Project override for this surface."""
base.EnableUserProjectQuota()
# TODO(b/190538573): Determine if command group works with project number
base.RequireProjectID(args)

View File

@@ -0,0 +1,239 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to query activities."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import sys
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.policy_intelligence import policy_analyzer
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
_DETAILED_HELP = {
'brief':
"""Query activities on cloud resource.
""",
'DESCRIPTION':
"""\
Query activities with certain types of specific container resource. For --activity-type, supported values are:
- serviceAccountLastAuthentication
- serviceAccountKeyLastAuthentication
""",
'EXAMPLES':
"""\
To query serviceAccountKeyLastAuthentication activities of a project, run:
$ {command} --activity-type=serviceAccountKeyLastAuthentication --project=project-id
To query serviceAccountLastAuthentication activities of a project with no limit, run:
$ {command} --activity-type=serviceAccountLastAuthentication --project=project-id --limit=unlimited
To query serviceAccountLastAuthentication with filtering on certain service account, run:
$ {command} --activity-type=serviceAccountLastAuthentication --project=project-id --query-filter='activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name@project-id.iam.gserviceaccount.com"'
To query serviceAccountLastAuthentication with filtering on multiple service accounts, run:
$ {command} --activity-type=serviceAccountLastAuthentication --project=project-id --query-filter='activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-1@project-id.iam.gserviceaccount.com" OR activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-2@project-id.iam.gserviceaccount.com" OR activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-3@project-id.iam.gserviceaccount.com"'
"""
}
_DETAILED_HELP_ALPHA = {
'brief':
"""Query activities on cloud resource.
""",
'DESCRIPTION':
"""\
Query activities with certain types of specific container resource. For --activity-type, supported values are:
- serviceAccountLastAuthentication
- serviceAccountKeyLastAuthentication
- dailyAuthorization
""",
'EXAMPLES':
"""\
To query serviceAccountKeyLastAuthentication activities of a project, run:
$ {command} --activity-type=serviceAccountKeyLastAuthentication --project=project-id
To query serviceAccountLastAuthentication activities of a project with no limit, run:
$ {command} --activity-type=serviceAccountLastAuthentication --project=project-id --limit=unlimited
To query serviceAccountLastAuthentication with filtering on certain service account, run:
$ {command} --activity-type=serviceAccountLastAuthentication --project=project-id --query-filter='activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name@project-id.iam.gserviceaccount.com"'
To query serviceAccountLastAuthentication with filtering on multiple service accounts, run:
$ {command} --activity-type=serviceAccountLastAuthentication --project=project-id --query-filter='activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-1@project-id.iam.gserviceaccount.com" OR activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-2@project-id.iam.gserviceaccount.com" OR activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-3@project-id.iam.gserviceaccount.com"'
To query dailyAuthorization activities of a project, run:
$ {command} --activity-type=dailyAuthorization --project=project-id
To query dailyAuthorization of a project with filtering on certain resource, permission, principal and date, run:
$ {command} --activity-type=dailyAuthorization --project=project-id --query-filter='activities.activity.full_resource_name="<full_resource_name>" AND activities.activity.permission="<permission_name>" AND activities.activity.principal="<principal_email>" AND activities.activity.date="<YYYY-MM-DD>"'
"""
}
def _Args(parser):
"""Parses arguments for the commands."""
parser.add_argument(
'--activity-type',
required=True,
type=str,
choices=[
'serviceAccountLastAuthentication',
'serviceAccountKeyLastAuthentication'
],
help="""Type of the activities.
""")
parser.add_mutually_exclusive_group(required=True).add_argument(
'--project',
type=str,
help="""The project ID or number to query the activities.
""")
parser.add_argument(
'--query-filter',
type=str,
default='',
help='Filter on activities, separated by "OR" if multiple filters are specified. At most 10 filter restrictions are supported in the query-filter. e.g. --query-filter=\'activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-1@project-id.iam.gserviceaccount.com" OR activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-2@project-id.iam.gserviceaccount.com"\''
)
parser.add_argument(
'--limit',
type=arg_parsers.BoundedInt(1, sys.maxsize, unlimited=True),
default=1000,
help='Max number of query result. Default to be 1000 and max to be unlimited, i.e., --limit=unlimited.'
)
parser.add_argument(
'--page-size',
type=arg_parsers.BoundedInt(1, 1000),
default=500,
help='Max page size for each http response. Default to be 500 and max to be 1000.'
)
def _ArgsAlpha(parser):
"""Parses arguments for the commands."""
parser.add_argument(
'--activity-type',
required=True,
type=str,
choices=[
'serviceAccountLastAuthentication',
'serviceAccountKeyLastAuthentication', 'dailyAuthorization'
],
help="""Type of the activities.
""")
parser.add_mutually_exclusive_group(required=True).add_argument(
'--project',
type=str,
help="""The project ID or number to query the activities.
""")
parser.add_argument(
'--query-filter',
type=str,
default='',
help="""Filter on activities. \n
For last authentication activities, this field is separated by "OR" if multiple filters are specified. At most 10 filter restrictions are supported in the query-filter. \n
e.g. --query-filter=\'activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-1@project-id.iam.gserviceaccount.com" OR activities.full_resource_name="//iam.googleapis.com/projects/project-id/serviceAccounts/service-account-name-2@project-id.iam.gserviceaccount.com"\'\n
For daily authorization activities, this field is separated by "OR" and "AND". At most 10 filter restrictions per layer and at most 2 layers are supported in the query-filter. \n
e.g. --query-filter=\'activities.activity.date="2022-01-01" AND activities.activity.permission="spanner.databases.list" AND (activities.activity.principal="principal_1@your-organization.com" OR activities.activity.principal="principal_2@your-organization.com")'"""
)
parser.add_argument(
'--limit',
type=arg_parsers.BoundedInt(1, sys.maxsize, unlimited=True),
default=1000,
help='Max number of query result. Default to be 1000 and max to be unlimited, i.e., --limit=unlimited.'
)
parser.add_argument(
'--page-size',
type=arg_parsers.BoundedInt(1, 1000),
default=500,
help='Max page size for each http response. Default to be 500 and max to be 1000.'
)
def _Run(args):
policy_analyzer_client, messages = policy_analyzer.GetClientAndMessages()
query_activity_parent = 'projects/{0}/locations/global/activityTypes/{1}'.format(
args.project, args.activity_type)
query_activity_request = messages.PolicyanalyzerProjectsLocationsActivityTypesActivitiesQueryRequest(
parent=query_activity_parent, filter=args.query_filter)
policy_analyzer_service = policy_analyzer_client.ProjectsLocationsActivityTypesActivitiesService(
policy_analyzer_client)
return list_pager.YieldFromList(
policy_analyzer_service,
query_activity_request,
method='Query',
batch_size=args.page_size,
field='activities',
limit=args.limit,
batch_size_attribute='pageSize')
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.Hidden
class QueryActivityAlpha(base.Command):
"""Query activities on cloud resource."""
detailed_help = _DETAILED_HELP_ALPHA
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_ArgsAlpha(parser)
def Run(self, args):
return _Run(args)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.Hidden
class QueryActivityBeta(base.Command):
"""Query activities on cloud resource."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_Args(parser)
def Run(self, args):
return _Run(args)
@base.ReleaseTracks(base.ReleaseTrack.GA)
class QueryActivityGA(base.Command):
"""Query activities on cloud resource."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_Args(parser)
def Run(self, args):
return _Run(args)

View File

@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command group for Policy Intelligence Simulate."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.DefaultUniverseOnly
class SimulateAlpha(base.Group):
"""Simulate changes to organization policies."""
detailed_help = {
'DESCRIPTION': """\
Simulate changes to organization policies.
"""
}
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.DefaultUniverseOnly
class SimulateBeta(base.Group):
"""Simulate changes to organization policies."""
detailed_help = {
'DESCRIPTION': """\
Simulate changes to organization policies.
"""
}
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class SimulateGA(base.Group):
"""Simulate changes to organization policies."""
detailed_help = {
'DESCRIPTION': """\
Simulate changes to organization policies.
"""
}

View File

@@ -0,0 +1,236 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to simulate orgpolicy."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import encoding_helper
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.orgpolicy import utils as orgpolicy_utils
from googlecloudsdk.api_lib.policy_intelligence import orgpolicy_simulator
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.policy_intelligence.simulator.orgpolicy import utils
from googlecloudsdk.core import log
_DETAILED_HELP = {
'brief':
"""\
Understand how changes to organization policies could affect your
resources.
""",
'DESCRIPTION':
"""\
Understand how changes to organization policies could affect your
resources.
""",
'EXAMPLES':
"""\
To simulate changes to custom constraints defined in
`./custom-constraint.json`, run:
$ {command}
--organization=ORGANIZATION_ID
--custom-constraints=custom-constraint.json
To simulate changes to organization policies defined in `./policy.json`,
run:
$ {command}
--organization=ORGANIZATION_ID
--policies=policy.json
To simulate changes to both custom constraints defined in
`./custom-constraint.json` and organization policies defined in
`./policy.json`, run:
$ {command}
--organization=ORGANIZATION_ID
--policies=policy.json
--custom-constraints=custom-constraint.json
See https://cloud.google.com/policy-intelligence/docs/test-organization-policies
for more information about Policy Simulator for Organization Policy.
"""
}
def _ArgsParse(parser):
"""Parses arguments for the commands."""
parser.add_argument(
'--organization',
metavar='ORGANIZATION_ID',
required=True,
help=('Organization ID.'))
parser.add_argument(
'--policies',
type=arg_parsers.ArgList(),
metavar='POLICIES',
action=arg_parsers.UpdateAction,
help="""Path to the JSON or YAML file that contains the organization
policy to simulate. Multiple policies can be simulated by providing
multiple, comma-separated paths. For example: `--policies=p1.json,p2.json`
""")
parser.add_argument(
'--custom-constraints',
type=arg_parsers.ArgList(),
metavar='CUSTOM_CONSTRAINTS',
action=arg_parsers.UpdateAction,
help="""Path to the JSON or YAML file that contains the custom constraints
to simulate. Multiple custom constraints can be simulated by providing
multiple, comma-separated paths. For example:
`--custom-constraints=constraint1.json,constraint2.json`
""")
def _Run(args, version):
"""Run the workflow for Policy Simulator for Organization Policy."""
if not args.policies and not args.custom_constraints:
raise exceptions.ConflictingArgumentsException(
'Must specify either `--policies`, `--custom-constraints`, or both.')
op_api = orgpolicy_simulator.OrgPolicySimulatorApi(
version)
# Parse files and get Policy Overlay
policies = []
if args.policies:
for policy_file in args.policies:
policy = utils.GetPolicyMessageFromFile(policy_file,
version)
if not policy.name:
raise exceptions.InvalidArgumentException(
'Policy name',
"'name' field not present in the organization policy.")
policy_parent = orgpolicy_utils.GetResourceFromPolicyName(
policy.name)
policy_overlay = op_api.GetOrgPolicyPolicyOverlay(
policy=policy,
policy_parent=policy_parent)
policies.append(policy_overlay)
# Parse files and get Custom Constraints Overlay
custom_constraints = []
if args.custom_constraints:
for custom_constraint_file in args.custom_constraints:
custom_constraint = utils.GetCustomConstraintMessageFromFile(
custom_constraint_file,
version)
if not custom_constraint.name:
raise exceptions.InvalidArgumentException(
'Custom constraint name',
"'name' field not present in the custom constraint.")
custom_constraint_parent = orgpolicy_utils.GetResourceFromPolicyName(
custom_constraint.name)
constraint_overlay = op_api.GetOrgPolicyCustomConstraintOverlay(
custom_constraint=custom_constraint,
custom_constraint_parent=custom_constraint_parent)
custom_constraints.append(constraint_overlay)
overlay = op_api.GetOrgPolicyOverlay(
policies=policies, custom_constraints=custom_constraints)
# Create Violations Preview and get long operation id
organization_resource = 'organizations/' + args.organization
parent = utils.GetParentFromOrganization(organization_resource)
violations = op_api.GetPolicysimulatorOrgPolicyViolationsPreview(
overlay=overlay)
request = op_api.CreateOrgPolicyViolationsPreviewRequest(
violations_preview=violations,
parent=parent)
op_service = op_api.client.OrganizationsLocationsOrgPolicyViolationsPreviewsService(
op_api.client)
violations_preview_operation = op_service.Create(
request=request)
# Poll Long Running Operation and get Violations Preview
operation_response_raw = op_api.WaitForOperation(
violations_preview_operation,
'Waiting for operation [{}] to complete'.format(
violations_preview_operation.name))
preview = encoding_helper.JsonToMessage(
op_api.GetOrgPolicyViolationsPreviewMessage(),
encoding_helper.MessageToJson(operation_response_raw))
if not preview.violationsCount or not preview.resourceCounts:
log.err.Print('No violations found in the violations preview.\n')
# List results of the Violations under Violations Preview.
list_violations_request = op_api.messages.PolicysimulatorOrganizationsLocationsOrgPolicyViolationsPreviewsOrgPolicyViolationsListRequest(
parent=preview.name)
pov_service = op_api.client.OrganizationsLocationsOrgPolicyViolationsPreviewsOrgPolicyViolationsService(
op_api.client)
return list_pager.YieldFromList(
pov_service,
list_violations_request,
batch_size=1000,
field='orgPolicyViolations',
batch_size_attribute='pageSize')
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.DefaultUniverseOnly
class SimulateAlpha(base.Command):
"""Simulate changes to organization policies."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_ArgsParse(parser)
def Run(self, args):
return _Run(args, self.ReleaseTrack())
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.DefaultUniverseOnly
class SimulateBeta(base.Command):
"""Simulate changes to organization policies."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_ArgsParse(parser)
def Run(self, args):
return _Run(args, self.ReleaseTrack())
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class SimulateGA(base.Command):
"""Simulate changes to organization policies."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_ArgsParse(parser)
def Run(self, args):
return _Run(args, self.ReleaseTrack())

View File

@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command group for Policy Intelligence Troubleshoot Policy."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.Hidden
class TroubleshootAlpha(base.Group):
"""Troubleshoot IAM policies."""
detailed_help = {'DESCRIPTION': """\
Troubleshoot IAM policies.
More information can be found here:
https://cloud.google.com/iam/docs/troubleshooting-access
"""}
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.Hidden
class TroubleshootBeta(base.Group):
"""Troubleshoot IAM policies."""
detailed_help = {'DESCRIPTION': """\
Troubleshoot IAM policies.
More information can be found here:
https://cloud.google.com/iam/docs/troubleshooting-access
"""}
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Troubleshoot(base.Group):
"""Troubleshoot IAM policies."""
detailed_help = {'DESCRIPTION': """\
Troubleshoot IAM policies.
More information can be found here:
https://cloud.google.com/iam/docs/troubleshooting-access
"""}

View File

@@ -0,0 +1,235 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to query activities."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.policy_intelligence import policy_troubleshooter
from googlecloudsdk.calliope import base
_DETAILED_HELP = {
'brief': """Troubleshoot the IAM Policy.
""",
'DESCRIPTION': """\
Performs a check on whether a principal is granted a
permission on a resource and how that access is determined according to
the resource's effective IAM policy interpretation.
""",
'EXAMPLES': """\
To troubleshoot a permission of a principal on a resource, run:
$ {command} //cloudresourcemanager.googleapis.com/projects/project-id \
--principal-email=my-iam-account@somedomain.com \
--permission=resourcemanager.projects.get
See https://cloud.google.com/iam/help/allow-policies/overview for more
information about IAM policies.
""",
}
_DETAILED_HELP = {
'brief': """Troubleshoot IAM allow and deny policies.
""",
'DESCRIPTION': """\
Uses a resource's effective IAM allow policy and IAM deny policy to
check whether a principal has a specific permission on the resource.
""",
'EXAMPLES': """\
The following command checks whether the principal ``my-user@example.com''
has the permission ``resourcemanager.projects.get'' on the project
``my-project'':
$ {command} //cloudresourcemanager.googleapis.com/projects/my-project
--principal-email=my-user@example.com
--permission=resourcemanager.projects.get
The following command checks whether the principal ``my-user@example.com''
has the ``compute.images.get'' permission on the project
``my-project''. The command also provides additional context that lets
Troubleshooter evaluate conditional role bindings:
$ {command} //cloudresourcemanager.googleapis.com/projects/my-project \
--principal-email=my-user@example.com \
--permission=compute.images.get \
--resource-name=//compute.googleapis.com/projects/my-project/zones/images/my-image'\
--resource-service='compute.googleapis.com' \
--resource-type='compute.googleapis.com/Image' \
--destination-ip='192.2.2.2'--destination-port=8080 --request-time='2023-01-01T00:00:00Z'
""",
}
def _Args(parser):
"""Parses arguments for the commands."""
parser.add_argument(
'resource',
metavar='RESOURCE',
type=str,
help="""Full resource name that access is checked against.
For a list of full resource name formats, see: https://cloud.google.com/iam/docs/resource-names.
""",
)
parser.add_argument(
'--principal-email',
required=True,
metavar='EMAIL',
type=str,
help="""Email address that identifies the principal to check. Only Google Accounts and
service accounts are supported.
""",
)
parser.add_argument(
'--permission',
required=True,
metavar='PERMISSION',
type=str,
help="""IAM permission to check. The permssion can be in the `v1` or `v2`
format. For example, `resourcemanager.projects.get` or
`cloudresourcemanager.googleapis.com/projects.get`.
For a list of permissions, see https://cloud.google.com/iam/docs/permissions-reference and https://cloud.google.com/iam/docs/deny-permissions-support
""",
)
parser.add_argument(
'--resource-service',
required=False,
type=str,
help="""The resource service value to use when checking conditional bindings.
For accepted values, see: https://cloud.google.com/iam/docs/conditions-resource-attributes#resource-service
""",
)
parser.add_argument(
'--resource-type',
required=False,
type=str,
help="""The resource type value to use when checking conditional bindings.
For accepted values, see: https://cloud.google.com/iam/docs/conditions-resource-attributes#resource-type
""",
)
parser.add_argument(
'--resource-name',
required=False,
type=str,
help="""The resource name value to use when checking conditional bindings.
For accepted values, see: https://cloud.google.com/iam/docs/conditions-resource-attributes#resource-name.
""",
)
parser.add_argument(
'--request-time',
required=False,
type=str,
help="""The request timestamp to use when checking conditional bindings. This string must adhere to UTC format
(RFC 3339). For example,2021-01-01T00:00:00Z. For more information, see:
https://tools.ietf.org/html/rfc3339
""",
)
parser.add_argument(
'--destination-ip',
required=False,
type=str,
help="""The request destination IP address to use when checking conditional bindings. For example, `198.1.1.1`.
""",
)
parser.add_argument(
'--destination-port',
required=False,
type=int,
help="""The request destination port to use when checking conditional bindings. For example, 8080.
""",
)
def _Run(policy_troubleshooter_api, args):
"""Troubleshoot the IAM Policies."""
destination_context = policy_troubleshooter_api.GetPolicyTroubleshooterPeer(
destination_ip=args.destination_ip,
destination_port=args.destination_port,
)
request_context = policy_troubleshooter_api.GetPolicyTroubleshooterRequest(
request_time=args.request_time
)
resource_context = policy_troubleshooter_api.GetPolicyTroubleshooterResource(
resource_name=args.resource_name,
resource_service=args.resource_service,
resource_type=args.resource_type,
)
condition_context = (
policy_troubleshooter_api.GetPolicyTroubleshooterConditionContext(
destination=destination_context,
request=request_context,
resource=resource_context,
)
)
access_tuple = policy_troubleshooter_api.GetPolicyTroubleshooterAccessTuple(
condition_context=condition_context,
full_resource_name=args.resource,
principal_email=args.principal_email,
permission=args.permission,
)
return policy_troubleshooter_api.TroubleshootIAMPolicies(access_tuple)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.Hidden
class TroubleshootAlpha(base.Command):
"""Troubleshoot the IAM Policies."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_Args(parser)
def Run(self, args):
return _Run(
policy_troubleshooter.PolicyTroubleshooterApi(self.ReleaseTrack()), args
)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.Hidden
class TroubleshootBeta(base.Command):
"""Troubleshoot IAM allow and deny policies."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_Args(parser)
def Run(self, args):
return _Run(
policy_troubleshooter.PolicyTroubleshooterApi(self.ReleaseTrack()), args
)
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Troubleshoot(base.Command):
"""Troubleshoot IAM allow and deny policies."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
"""Parses arguments for the commands."""
_Args(parser)
def Run(self, args):
return _Run(
policy_troubleshooter.PolicyTroubleshooterApi(self.ReleaseTrack()), args
)