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,27 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 Cloud Security Command Center (SCC) RemediationIntent GCP resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class RemediationIntents(base.Group):
"""Manages Cloud Security Command Center (SCC) RemediationIntent resource."""
category = base.SECURITY_CATEGORY

View File

@@ -0,0 +1,255 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 for semi-automatic remediation of SCC findings."""
import copy
import uuid
from googlecloudsdk.api_lib.scc.remediation_intents import const
from googlecloudsdk.api_lib.scc.remediation_intents import converters
from googlecloudsdk.api_lib.scc.remediation_intents import extended_service
from googlecloudsdk.api_lib.scc.remediation_intents import git
from googlecloudsdk.api_lib.scc.remediation_intents import sps_api
from googlecloudsdk.api_lib.scc.remediation_intents import terraform
from googlecloudsdk.api_lib.scc.remediation_intents import validators
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.scc.remediation_intents import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
class AutoRemediate(base.SilentCommand, base.CacheCommand):
"""Command for semi-automatic remediation of SCC findings."""
detailed_help = {
"DESCRIPTION": """
Orchestrates the semi-automatic remediation process for SCC findings
by calling the Remediation Intent APIs.
""",
"EXAMPLES": """
Sample usage:
Remediate a SCC finding for the organization 1234567890, in the
terraform repository located at ./terraform-repo.
$ {{command}} scc remediation-intents auto-remediate \\
--org-id=1234567890 \\
--root-dir-path=./terraform-repo \\
--git-config-path=./git-config.yaml""",
}
@staticmethod
def Args(parser):
flags.ROOT_DIR_PATH_FLAG.AddToParser(parser)
flags.ROOT_DIR_PATH_FLAG.SetDefault(parser, ".")
flags.ORG_ID_FLAG.AddToParser(parser)
flags.GIT_CONFIG_FILE_PATH_FLAG.AddToParser(parser)
def Run(self, args) -> None:
"""The main function which is called when the user runs this command.
Args:
args: an argparse namespace. All the arguments that were provided to this
command invocation.
"""
# Set up the variables.
org_id = args.org_id
git_config_data = args.git_config_path
root_dir_path = args.root_dir_path
# The extended service client to interact with the SPS service.
client = extended_service.ExtendedSPSClient(org_id, base.ReleaseTrack.ALPHA)
# The converter instance to handle conversion between different data types.
converter = converters.RemediationIntentConverter(base.ReleaseTrack.ALPHA)
messages = sps_api.GetMessagesModule(base.ReleaseTrack.ALPHA)
# Validate the input arguments.
validators.validate_git_config(git_config_data)
validators.validate_relative_dir_path(root_dir_path)
# Create a SCC finding Remediation Intent.
# Fetch an enqueued remediation intent which needs to be remediated.
intent_data = client.fetch_enqueued_remediation_intent()
if ( # Create a new intent if no enqueued intent is found.
intent_data is None
):
client.create_semi_autonomous_remediation_intent()
intent_data = client.fetch_enqueued_remediation_intent()
if intent_data is None:
# Exit gracefully if still no intent is found.
log.Print("No remediation intent found to be remediated, exitting...")
return
intent_name = intent_data.name
tf_files = terraform.fetch_tf_files(root_dir_path)
if not tf_files: # Exit gracefully if no TF files are found.
log.Print("No TF files found, exitting...")
return
# Parse the TFState file for the given finding data.
tfstate_data = terraform.parse_tf_file(
root_dir_path, intent_data.findingData
)
log.Print("Remediation started....")
# Update the state to REMEDIATION_IN_PROGRESS and start the remediation.
intent_updated = copy.deepcopy(intent_data)
intent_updated.state = ( # Mark the state as REMEDIATION_IN_PROGRESS.
messages.RemediationIntent.StateValueValuesEnum.REMEDIATION_IN_PROGRESS
)
intent_updated.remediationInput = messages.RemediationInput(
tfData=messages.TfData(
fileData=converter.DictFilesToMessage(tf_files),
tfStateInfo=tfstate_data,
)
)
update_mask = "state,remediation_input"
intent_updated = client.update_remediation_intent( # Call the Update API.
intent_name, update_mask, intent_updated
)
if (
intent_updated.state
== messages.RemediationIntent.StateValueValuesEnum.REMEDIATION_FAILED
):
log.Print("Remediation failed, exitting...")
return
# Retry the remediation process for certain number of times.
is_remediated = False
retry_count = 0
while not is_remediated and retry_count < const.REMEDIATION_RETRY_COUNT:
log.Print("Remediation retry count: ", retry_count)
updated_tf_files = converter.MessageFilesToDict(
intent_updated.remediatedOutput.outputData[0].tfData.fileData
)
error_msg = terraform.validate_tf_files(updated_tf_files)
if error_msg is None: # Remediation is successful.
is_remediated = True
break
# Send the error details to the server and retry the remediation.
intent_updated.remediationInput.errorDetails = messages.ErrorDetails(
reason=error_msg
)
update_mask = "remediation_input.error_details"
intent_updated = client.update_remediation_intent(
intent_name, update_mask, intent_updated
)
if (
intent_updated.state
== messages.RemediationIntent.StateValueValuesEnum.REMEDIATION_FAILED
):
log.Print("Remediation failed, exitting...")
return
retry_count += 1 # Upate the retry count.
log.Print("Remediation failed, retrying...")
if not is_remediated: # Mark the state as REMEDIATION_FAILED and exit.
log.Print("Remediation failed: Max retry limit reached.")
intent_updated.state = (
messages.RemediationIntent.StateValueValuesEnum.REMEDIATION_FAILED
)
update_mask = "state"
_ = client.update_remediation_intent( # Call the Update API.
intent_name, update_mask, intent_updated
)
return
log.Print("Remediation completed successfully.")
intent_updated.state = ( # Mark the state as REMEDIATION_SUCCESS.
messages.RemediationIntent.StateValueValuesEnum.REMEDIATION_SUCCESS
)
intent_updated.remediationInput.errorDetails = None
update_mask = "state,remediation_input.error_details"
intent_updated = client.update_remediation_intent( # Call the Update API.
intent_name, update_mask, intent_updated
)
# Generate the PR for the remediated output.
log.Print("Starting PR generation process...")
updated_tf_files = converter.MessageFilesToDict(
intent_updated.remediatedOutput.outputData[0].tfData.fileData
)
git_config_data["branch-prefix"] += str(uuid.uuid4())
git.push_commit(
updated_tf_files,
const.COMMIT_MSG.format(
project_id=intent_updated.findingData.findingName.split("/")[1],
finding_id=intent_updated.findingData.findingName.split("/")[-1],
category=intent_updated.findingData.category,
),
git_config_data["remote"],
git_config_data["branch-prefix"],
)
log.Print("Commit pushed successfully.")
# Add the remediation explanation to the PR description.
pr_status, pr_msg = git.create_pr(
const.PR_TITLE.format(
project_id=intent_updated.findingData.findingName.split("/")[1],
finding_id=intent_updated.findingData.findingName.split("/")[-1],
category=intent_updated.findingData.category,
),
const.PR_DESC.format(
remediation_explanation=intent_updated.remediatedOutput.remediationExplanation.replace(
"`", r"\`"
),
file_modifiers="\n".join(
f"{fp}: {ea}"
for fp, ea in (git.get_file_modifiers(updated_tf_files)).items()
),
file_owners="\n".join(
f"{fp}: {ea}"
for fp, ea in (
git.get_file_modifiers(updated_tf_files, first=True)
).items()
),
),
git_config_data["remote"],
git_config_data["branch-prefix"],
git_config_data["main-branch-name"],
git_config_data["reviewers"],
)
# Update the state and error details if the PR creation fails, and exit.
if not pr_status:
log.Print("PR creation failed, exitting...")
intent_updated.state = (
messages.RemediationIntent.StateValueValuesEnum.PR_GENERATION_FAILED
)
intent_updated.errorDetails = messages.ErrorDetails(reason=pr_msg)
update_mask = "state,error_details"
_ = client.update_remediation_intent(
intent_name, update_mask, intent_updated
)
return
# Finally Update the state and PR details if the PR creation is successful.
log.Print("PR created successfully.")
intent_updated.state = (
messages.RemediationIntent.StateValueValuesEnum.PR_GENERATION_SUCCESS
)
intent_updated.remediationArtifacts = messages.RemediationArtifacts(
prData=messages.PullRequest(
url=pr_msg,
modifiedFileOwners=list(
(git.get_file_modifiers(updated_tf_files, first=True)).values()
),
modifiedFilePaths=list(
(git.get_file_modifiers(updated_tf_files, first=True)).keys()
),
)
)
update_mask = "state,remediation_artifacts"
_ = client.update_remediation_intent(
intent_name, update_mask, intent_updated
)

View File

@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 for creating a Cloud Security Command Center RemediationIntent resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from googlecloudsdk.api_lib.scc.remediation_intents import sps_api
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.scc.remediation_intents import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
class Create(base.CreateCommand):
"""Creates a remediation intent resource."""
detailed_help = {
"DESCRIPTION": """
Create a Cloud Security Command Center (SCC)
RemediationIntent resource.
Created resource is returned as the response of the command.""",
"EXAMPLES": """
Sample usage:
Create a manual workflow remediation intent resource:
$ {{command}} scc remediation-intents create --parent=organizations/123456789/locations/global --finding-name=projects/123456789/sources/123456789/locations/global/findings/123456789 --workflow-type=manual
Create a semi-autonomous workflow remediation intent resource:
$ {{command}} scc remediation-intents create --parent=organizations/123456789/locations/global --workflow-type=semi-autonomous
""",
}
@staticmethod
def Args(parser):
base.ASYNC_FLAG.AddToParser(parser)
base.ASYNC_FLAG.SetDefault(parser, False)
flags.PARENT_NAME_FLAG.AddToParser(parser)
flags.FINDING_NAME_FLAG.AddToParser(parser)
flags.WORKFLOW_TYPE_FLAG.AddToParser(parser)
parser.display_info.AddFormat("yaml")
def Run(self, args):
"""The main function which is called when the user runs this command.
Args:
args: an argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
Operation resource containing either resource or error.
"""
client = sps_api.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = sps_api.GetMessagesModule(base.ReleaseTrack.ALPHA)
# set workflow type based on the input argument value
if args.workflow_type == "semi-autonomous":
workflow_type = (
messages.CreateRemediationIntentRequest.WorkflowTypeValueValuesEnum.WORKFLOW_TYPE_SEMI_AUTONOMOUS
)
elif args.workflow_type == "manual":
workflow_type = (
messages.CreateRemediationIntentRequest.WorkflowTypeValueValuesEnum.WORKFLOW_TYPE_MANUAL
)
else:
workflow_type = ( # default value to be passed
messages.CreateRemediationIntentRequest.WorkflowTypeValueValuesEnum.WORKFLOW_TYPE_UNSPECIFIED
)
# create the request object
request = messages.SecuritypostureOrganizationsLocationsRemediationIntentsCreateRequest(
parent=args.parent,
createRemediationIntentRequest=messages.CreateRemediationIntentRequest(
findingName=args.finding_name,
workflowType=workflow_type,
),
)
# call the create remediation intent API
operation = client.organizations_locations_remediationIntents.Create(
request=request
)
operation_id = operation.name
if args.async_: # Return the in-progress operation if async is requested.
log.status.Print(
"Check for operation completion status using operation ID:",
operation_id,
)
return operation
else: # Poll the operation until it completes and return resource
return sps_api.WaitForOperation(
operation_ref=sps_api.GetOperationsRef(operation_id),
message="Waiting for remediation intent to be created",
has_result=True,
)

View File

@@ -0,0 +1,89 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 for deleting a Cloud Security Command Center RemediationIntent resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from googlecloudsdk.api_lib.scc.remediation_intents import sps_api
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.scc.remediation_intents import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
class Delete(base.DeleteCommand):
"""Deletes a remediation intent resource."""
detailed_help = {
"DESCRIPTION": """
Deletes a Cloud Security Command Center (SCC)
RemediationIntent resource.""",
"EXAMPLES": """
Sample usage:
Delete a remediation intent resource of name organizations/123456789/locations/global/remediationIntents/123:
$ {{command}} scc remediation-intents delete organizations/123456789/locations/global/remediationIntents/123
""",
}
@staticmethod
def Args(parser):
base.ASYNC_FLAG.AddToParser(parser)
base.ASYNC_FLAG.SetDefault(parser, False)
flags.ETAG_FLAG.AddToParser(parser)
flags.AddRemediationIntentResourceArg(parser)
def Run(self, args):
"""The main function which is called when the user runs this command.
Args:
args: An argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
Operation resource containing success or error.
"""
client = sps_api.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = sps_api.GetMessagesModule(base.ReleaseTrack.ALPHA)
# parse the remediation intent resource argument
ri_ref = args.CONCEPTS.remediationintent.Parse()
ri_name = ri_ref.RelativeName()
# create the request object
request = messages.SecuritypostureOrganizationsLocationsRemediationIntentsDeleteRequest(
name=ri_name,
etag=args.etag,
)
# call the create remediation intent API
operation = client.organizations_locations_remediationIntents.Delete(
request=request
)
operation_id = operation.name
if args.async_: # Return the in-progress operation if async is requested.
log.status.Print(
"Check for operation completion status using operation ID:",
operation_id,
)
return operation
else: # Poll the operation until it completes and return resource
return sps_api.WaitForOperation(
operation_ref=sps_api.GetOperationsRef(operation_id),
message="Waiting for remediation intent to be deleted",
has_result=False,
)

View File

@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 for describing a Cloud Security Command Center RemediationIntent resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from googlecloudsdk.api_lib.scc.remediation_intents import sps_api
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.scc.remediation_intents import flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
class Describe(base.DescribeCommand):
"""Describes a remediation intent resource."""
detailed_help = {
"DESCRIPTION": """
Describe a Cloud Security Command Center (SCC)
RemediationIntent resource.
The resource is returned as the response of the command.""",
"EXAMPLES": """
Sample usage:
Describe a remediation intent resource of id 1234 under organization 12345 and location global:
$ {{command}} scc remediation-intents describe organizations/12345/locations/global/remediationIntents/1234
""",
}
@staticmethod
def Args(parser):
flags.AddRemediationIntentResourceArg(parser)
def Run(self, args):
"""The main function which is called when the user runs this command.
Args:
args: An argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
RemediationIntent resource.
"""
client = sps_api.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = sps_api.GetMessagesModule(base.ReleaseTrack.ALPHA)
# parse the remediation intent resource argument
ri_ref = args.CONCEPTS.remediationintent.Parse()
ri_name = ri_ref.RelativeName()
# create the request object
request = messages.SecuritypostureOrganizationsLocationsRemediationIntentsGetRequest(
name=ri_name,
)
# call the get remediation intent API
response = client.organizations_locations_remediationIntents.Get(
request=request
)
return response

View File

@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 for listing a Cloud Security Command Center RemediationIntent resources."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.scc.remediation_intents import sps_api
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.scc.remediation_intents import flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
class List(base.ListCommand):
"""Lists the remediation intent resources."""
detailed_help = {
"DESCRIPTION": """
Lists the Cloud Security Command Center (SCC)
RemediationIntent resources.
List of resources is returned as the response of the command.""",
"EXAMPLES": """
Sample usage:
List all remediation intent resource under parent organizations/123456789/locations/global:
$ {{command}} scc remediation-intents list organizations/123456789/locations/global
""",
}
@staticmethod
def Args(parser):
flags.POSITIONAL_PARENT_NAME_FLAG.AddToParser(parser)
parser.display_info.AddFormat("table(name)")
def Run(self, args):
"""The main function which is called when the user runs this command.
Args:
args: an argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
List of remediation intent resources as per the request.
"""
client = sps_api.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = sps_api.GetMessagesModule(base.ReleaseTrack.ALPHA)
# create the request object
request = messages.SecuritypostureOrganizationsLocationsRemediationIntentsListRequest(
parent=args.parent,
filter=args.filter,
)
return list_pager.YieldFromList(
client.organizations_locations_remediationIntents,
request,
field="remediationIntents",
limit=args.limit,
batch_size_attribute="pageSize")

View File

@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 for updating a Cloud Security Command Center RemediationIntent resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from apitools.base.py import encoding
from googlecloudsdk.api_lib.scc.remediation_intents import sps_api
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.scc.remediation_intents import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
class Update(base.UpdateCommand):
"""Updates a remediation intent resource."""
detailed_help = {
"DESCRIPTION": """
Updates a Cloud Security Command Center (SCC)
RemediationIntent resource.\n
Fields specified in update-mask flag are updated. Updatable fields depends on the state transition.\n
Valid state transitions are:\n
a) ENQUEUED to IN_PROGRESS (mask: state,remediation_input)\n
b) REMEDIATION_SUCCESS to PR_GENERATION_SUCCESS (mask: state,remediation_artifacts)\n
c) REMEDIATION_SUCCESS to PR_GENERATION_FAILED (mask: state,error_details)\n
An empty or * as field mask will result in updating the relevant fields as per the transition.\n
Updated resource is returned as the response of the command.""",
"EXAMPLES": """
Sample usage:
Update the remediation intent resource's state from ENQUEUED to IN_PROGRESS:
$ {{command}} scc remediation-intents update organizations/123456789/locations/global/remediationIntents/123456789 --ri-from-file=/path/to/resource.yaml --update-mask=state,remediation_input
\n
Update the remediation intent resource's state from ENQUEUED to IN_PROGRESS (with empty update mask):
$ {{command}} scc remediation-intents update organizations/123456789/locations/global/remediationIntents/123456789 --ri-from-file=/path/to/resource.yaml
\n
Update the remediation intent resource's state from REMEDIATION_SUCCESS to PR_GENERATION_SUCCESS:
$ {{command}} scc remediation-intents update organizations/123456789/locations/global/remediationIntents/123456789 --ri-from-file=/path/to/resource.yaml --update-mask=state,remediation_artifacts
\n
Update the remediation intent resource's state from REMEDIATION_SUCCESS to PR_GENERATION_FAILED:
$ {{command}} scc remediation-intents update organizations/123456789/locations/global/remediationIntents/123456789 --ri-from-file=/path/to/resource.yaml --update-mask=state,error_details
""",
}
@staticmethod
def Args(parser):
base.ASYNC_FLAG.AddToParser(parser)
base.ASYNC_FLAG.SetDefault(parser, False)
flags.AddRemediationIntentResourceArg(parser)
flags.REMEDIATION_INTENT_FROM_FILE_FLAG.AddToParser(parser)
flags.UPDATE_MASK_FLAG.AddToParser(parser)
parser.display_info.AddFormat("yaml")
def Run(self, args):
"""The main function which is called when the user runs this command.
Args:
args: an argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
Operation resource containing either resource or error.
"""
client = sps_api.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = sps_api.GetMessagesModule(base.ReleaseTrack.ALPHA)
# Set mask based on the input argument value.
if args.update_mask is None:
update_mask = "*" # update all relevant fields
else:
update_mask = args.update_mask
# parse the remediation intent resource argument
ri_ref = args.CONCEPTS.remediationintent.Parse()
ri_name = ri_ref.RelativeName()
# create the request object
request = messages.SecuritypostureOrganizationsLocationsRemediationIntentsPatchRequest(
name=ri_name,
remediationIntent=encoding.DictToMessage(
args.ri_from_file, # dict object containing the resource
messages.RemediationIntent,
),
updateMask=update_mask,
)
# call the update remediation intent API
operation = client.organizations_locations_remediationIntents.Patch(
request=request
)
operation_id = operation.name
if args.async_: # Return the in-progress operation if async is requested.
log.status.Print(
"Check for operation completion status using operation ID:",
operation_id,
)
return operation
else: # Poll the operation until it completes and return resource
return sps_api.WaitForOperation(
operation_ref=sps_api.GetOperationsRef(operation_id),
message="Waiting for remediation intent to be updated",
has_result=True,
)