884 lines
24 KiB
Python
884 lines
24 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2024 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.
|
|
"""Helpers for parsing flags and arguments."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
from googlecloudsdk.api_lib.cloudkms import base as cloudkms_base
|
|
from googlecloudsdk.calliope import actions
|
|
from googlecloudsdk.calliope import arg_parsers
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.command_lib.kms import maps
|
|
from googlecloudsdk.command_lib.kms import resource_args
|
|
from googlecloudsdk.command_lib.util import completers
|
|
from googlecloudsdk.command_lib.util import parameter_info_lib
|
|
from googlecloudsdk.core import properties
|
|
from googlecloudsdk.core import resources
|
|
from googlecloudsdk.core.util import times
|
|
|
|
EKM_CONNECTION_COLLECTION = 'cloudkms.projects.locations.ekmConnections'
|
|
KEY_RING_COLLECTION = 'cloudkms.projects.locations.keyRings'
|
|
KEY_HANDLE_COLLECTION = 'cloudkms.projects.locations.keyHandles'
|
|
LOCATION_COLLECTION = 'cloudkms.projects.locations'
|
|
|
|
# Collection names.
|
|
CRYPTO_KEY_COLLECTION = 'cloudkms.projects.locations.keyRings.cryptoKeys'
|
|
CRYPTO_KEY_VERSION_COLLECTION = '%s.cryptoKeyVersions' % CRYPTO_KEY_COLLECTION
|
|
IMPORT_JOB_COLLECTION = 'cloudkms.projects.locations.keyRings.importJobs'
|
|
SINGLE_TENANT_HSM_INSTANCE_COLLECTION = (
|
|
'cloudkms.projects.locations.singleTenantHsmInstances'
|
|
)
|
|
# list command aggregators
|
|
|
|
|
|
class ListCommandParameterInfo(parameter_info_lib.ParameterInfoByConvention):
|
|
|
|
def GetFlag(
|
|
self,
|
|
parameter_name,
|
|
parameter_value=None,
|
|
check_properties=True,
|
|
for_update=False,
|
|
):
|
|
return super(ListCommandParameterInfo, self).GetFlag(
|
|
parameter_name,
|
|
parameter_value=parameter_value,
|
|
check_properties=check_properties,
|
|
for_update=for_update,
|
|
)
|
|
|
|
|
|
class ListCommandCompleter(completers.ListCommandCompleter):
|
|
|
|
def ParameterInfo(self, parsed_args, argument):
|
|
return ListCommandParameterInfo(
|
|
parsed_args,
|
|
argument,
|
|
self.collection,
|
|
updaters=COMPLETERS_BY_CONVENTION,
|
|
)
|
|
|
|
|
|
# kms completers
|
|
|
|
|
|
class LocationCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(LocationCompleter, self).__init__(
|
|
collection=LOCATION_COLLECTION,
|
|
list_command='kms locations list --uri',
|
|
**kwargs
|
|
)
|
|
|
|
|
|
class SingleTenantHsmInstanceCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(SingleTenantHsmInstanceCompleter, self).__init__(
|
|
collection=SINGLE_TENANT_HSM_INSTANCE_COLLECTION,
|
|
list_command='kms single-tenant-hsm-instances list --uri',
|
|
**kwargs
|
|
)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
|
|
class EkmConnectionCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(EkmConnectionCompleter, self).__init__(
|
|
collection=EKM_CONNECTION_COLLECTION,
|
|
list_command='kms ekm-connections list --uri',
|
|
flags=['location'],
|
|
**kwargs
|
|
)
|
|
|
|
|
|
class KeyRingCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(KeyRingCompleter, self).__init__(
|
|
collection=KEY_RING_COLLECTION,
|
|
list_command='kms keyrings list --uri',
|
|
flags=['location'],
|
|
**kwargs
|
|
)
|
|
|
|
|
|
class KeyCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(KeyCompleter, self).__init__(
|
|
collection=CRYPTO_KEY_COLLECTION,
|
|
list_command='kms keys list --uri',
|
|
flags=['location', 'keyring'],
|
|
**kwargs
|
|
)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
|
|
class KeyHandleCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(KeyHandleCompleter, self).__init__(
|
|
collection=KEY_HANDLE_COLLECTION,
|
|
list_command='kms key-handles list --uri',
|
|
flags=['location'],
|
|
**kwargs
|
|
)
|
|
|
|
|
|
class KeyVersionCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(KeyVersionCompleter, self).__init__(
|
|
collection=CRYPTO_KEY_VERSION_COLLECTION,
|
|
list_command='kms keys versions list --uri',
|
|
flags=['location', 'key', 'keyring'],
|
|
**kwargs
|
|
)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
|
|
class ImportJobCompleter(ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(ImportJobCompleter, self).__init__(
|
|
collection=IMPORT_JOB_COLLECTION,
|
|
list_command='beta kms import-jobs list --uri',
|
|
flags=['location', 'keyring'],
|
|
**kwargs
|
|
)
|
|
|
|
|
|
# completers by parameter name convention
|
|
|
|
COMPLETERS_BY_CONVENTION = {
|
|
'location': (LocationCompleter, False),
|
|
'keyring': (KeyRingCompleter, False),
|
|
'key-handle': (KeyHandleCompleter, False),
|
|
'key': (KeyCompleter, False),
|
|
'import-jobs': (ImportJobCompleter, False),
|
|
}
|
|
|
|
|
|
# Flags.
|
|
def AddLocationFlag(parser, resource='resource'):
|
|
parser.add_argument(
|
|
'--location',
|
|
completer=LocationCompleter,
|
|
help='Location of the {0}.'.format(resource),
|
|
)
|
|
|
|
|
|
def AddSingleTenantInstance(parser, resource='resource'):
|
|
parser.add_argument(
|
|
'--single-tenant-hsm-instance',
|
|
completer=SingleTenantHsmInstanceCompleter,
|
|
help='Single tenant HSM instance of the {0}.'.format(resource),
|
|
)
|
|
|
|
|
|
def AddKeyRingFlag(parser, resource='resource'):
|
|
parser.add_argument(
|
|
'--keyring',
|
|
completer=KeyRingCompleter,
|
|
help='Key ring of the {0}.'.format(resource),
|
|
)
|
|
|
|
|
|
def AddCryptoKeyFlag(parser, help_text=None):
|
|
parser.add_argument(
|
|
'--key', completer=KeyCompleter, help=help_text or 'The containing key.'
|
|
)
|
|
|
|
|
|
def AddKeyResourceFlags(parser, help_text=None):
|
|
AddLocationFlag(parser, 'keyring')
|
|
AddKeyRingFlag(parser, 'key')
|
|
AddCryptoKeyFlag(parser, help_text)
|
|
|
|
|
|
def AddSingleTenantHsmInstanceFlag(parser):
|
|
parser.add_argument(
|
|
'--single-tenant-hsm-instance',
|
|
completer=SingleTenantHsmInstanceCompleter,
|
|
help='The single tenant HSM instance to use for the import job.',
|
|
)
|
|
|
|
|
|
def AddCryptoKeyVersionFlag(parser, help_action, required=False):
|
|
parser.add_argument(
|
|
'--version',
|
|
required=required,
|
|
completer=KeyVersionCompleter,
|
|
help='Version {0}.'.format(help_action),
|
|
)
|
|
|
|
|
|
def AddCryptoKeyPrimaryVersionFlag(parser, help_action, required=False):
|
|
parser.add_argument(
|
|
'--primary-version',
|
|
required=required,
|
|
completer=KeyVersionCompleter,
|
|
help='Primary version {0}.'.format(help_action),
|
|
)
|
|
|
|
|
|
def AddRotationPeriodFlag(parser):
|
|
parser.add_argument(
|
|
'--rotation-period',
|
|
type=arg_parsers.Duration(lower_bound='1d'),
|
|
help=(
|
|
'Automatic rotation period of the key. See '
|
|
'$ gcloud topic datetimes for information on duration formats.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddNextRotationTimeFlag(parser):
|
|
parser.add_argument(
|
|
'--next-rotation-time',
|
|
type=arg_parsers.Datetime.Parse,
|
|
help=(
|
|
'Next automatic rotation time of the key. See '
|
|
'$ gcloud topic datetimes for information on time formats.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddRemoveRotationScheduleFlag(parser):
|
|
parser.add_argument(
|
|
'--remove-rotation-schedule',
|
|
action='store_true',
|
|
help='Remove any existing rotation schedule on the key.',
|
|
)
|
|
|
|
|
|
def AddSkipInitialVersionCreationFlag(parser):
|
|
parser.add_argument(
|
|
'--skip-initial-version-creation',
|
|
default=None,
|
|
action='store_true',
|
|
dest='skip_initial_version_creation',
|
|
help=(
|
|
'Skip creating the first version in a key and setting it as '
|
|
'primary during creation.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddPlaintextFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--plaintext-file',
|
|
help='File path of the plaintext file {0}.'.format(help_action),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddSharedSecretFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--shared-secret-file',
|
|
help='File path of the shared secret file {0}.'.format(help_action),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddCiphertextFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--ciphertext-file',
|
|
help='File path of the ciphertext file {0}.'.format(help_action),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddSignatureFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--signature-file',
|
|
help='Path to the signature file {}.'.format(help_action),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddInputFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--input-file',
|
|
help='Path to the input file {}.'.format(help_action),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddRsaAesWrappedKeyFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--rsa-aes-wrapped-key-file',
|
|
help='Path to the wrapped RSA AES key file {}.'.format(help_action),
|
|
hidden=True,
|
|
action=actions.DeprecationAction(
|
|
'--rsa-aes-wrapped-key-file',
|
|
warn=(
|
|
'The {flag_name} flag is deprecated but will continue to be '
|
|
'supported. Prefer to use the --wrapped-key-file flag instead.'
|
|
),
|
|
),
|
|
)
|
|
|
|
|
|
def AddWrappedKeyFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--wrapped-key-file',
|
|
help='Path to the RSA/RSA+AES wrapped key file {}.'.format(help_action),
|
|
)
|
|
|
|
|
|
def AddOutputFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--output-file', help='Path to the output file {}.'.format(help_action)
|
|
)
|
|
|
|
|
|
def AddAadFileFlag(parser):
|
|
parser.add_argument(
|
|
'--additional-authenticated-data-file',
|
|
help=(
|
|
'File path to the optional file containing the additional '
|
|
'authenticated data.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddIvFileFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--initialization-vector-file',
|
|
help=(
|
|
'File path to the optional file containing the initialization '
|
|
'vector {}.'.format(help_action)
|
|
),
|
|
)
|
|
|
|
|
|
def AddProtectionLevelFlag(parser):
|
|
parser.add_argument(
|
|
'--protection-level',
|
|
choices=[
|
|
'software',
|
|
'hsm',
|
|
'hsm-single-tenant',
|
|
'external',
|
|
'external-vpc',
|
|
],
|
|
default='software',
|
|
help='Protection level of the key.',
|
|
)
|
|
|
|
|
|
def AddRequiredProtectionLevelFlag(parser):
|
|
parser.add_argument(
|
|
'--protection-level',
|
|
choices=['software', 'hsm', 'hsm-single-tenant'],
|
|
help='Protection level of the import job.',
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddAttestationFileFlag(parser):
|
|
parser.add_argument(
|
|
'--attestation-file', help='Path to the output attestation file.'
|
|
)
|
|
|
|
|
|
def AddDefaultAlgorithmFlag(parser):
|
|
parser.add_argument(
|
|
'--default-algorithm',
|
|
choices=sorted(maps.ALL_ALGORITHMS),
|
|
help=(
|
|
'The default algorithm for the crypto key. For more information '
|
|
'about choosing an algorithm, see '
|
|
'https://cloud.google.com/kms/docs/algorithms.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddRequiredImportMethodFlag(parser):
|
|
parser.add_argument(
|
|
'--import-method',
|
|
choices=sorted(maps.IMPORT_METHOD_MAPPER.choices)[1:],
|
|
help=(
|
|
'The wrapping method to be used for incoming key material. For more '
|
|
'information about choosing an import method, see '
|
|
'https://cloud.google.com/kms/docs/key-wrapping.'
|
|
),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddPublicKeyFileFlag(parser):
|
|
parser.add_argument(
|
|
'--public-key-file',
|
|
help=(
|
|
'Path to the public key of the ImportJob, used to wrap the key for '
|
|
'import. If missing, the public key will be fetched on your behalf.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddTargetKeyFileFlag(parser):
|
|
parser.add_argument(
|
|
'--target-key-file',
|
|
help=(
|
|
'Path to the unwrapped target key to import into a Cloud KMS key'
|
|
' version. If specified, the key will be securely wrapped before'
|
|
' transmission to Google.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddDigestAlgorithmFlag(parser, help_action):
|
|
parser.add_argument(
|
|
'--digest-algorithm', choices=sorted(maps.DIGESTS), help=help_action
|
|
)
|
|
|
|
|
|
def AddImportedVersionAlgorithmFlag(parser):
|
|
parser.add_argument(
|
|
'--algorithm',
|
|
choices=sorted(maps.ALGORITHMS_FOR_IMPORT),
|
|
help=(
|
|
'The algorithm to assign to the new key version. For more '
|
|
'information about supported algorithms, see '
|
|
'https://cloud.google.com/kms/docs/algorithms.'
|
|
),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddExternalKeyUriFlag(parser):
|
|
parser.add_argument(
|
|
'--external-key-uri',
|
|
suggestion_aliases=['--key-uri'],
|
|
help=(
|
|
'The URI of the external key for keys with protection level'
|
|
' "external".'
|
|
),
|
|
)
|
|
|
|
|
|
def AddEkmConnectionKeyPathFlag(parser):
|
|
parser.add_argument(
|
|
'--ekm-connection-key-path',
|
|
help=(
|
|
'The path to the external key material on the EKM for keys with '
|
|
'protection level "external-vpc".'
|
|
),
|
|
)
|
|
|
|
|
|
def AddStateFlag(parser):
|
|
parser.add_argument('--state', dest='state', help='State of the key version.')
|
|
|
|
|
|
def AddSkipIntegrityVerification(parser):
|
|
parser.add_argument(
|
|
'--skip-integrity-verification',
|
|
default=None,
|
|
action='store_true',
|
|
dest='skip_integrity_verification',
|
|
help='Skip integrity verification on request and response API fields.',
|
|
)
|
|
|
|
|
|
def AddDestroyScheduledDurationFlag(parser):
|
|
parser.add_argument(
|
|
'--destroy-scheduled-duration',
|
|
type=arg_parsers.Duration(upper_bound='120d'),
|
|
help=(
|
|
'The amount of time that versions of the key should spend in the '
|
|
'DESTROY_SCHEDULED state before transitioning to DESTROYED. See '
|
|
'$ gcloud topic datetimes for information on duration formats.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddCryptoKeyBackendFlag(parser):
|
|
parser.add_argument(
|
|
'--crypto-key-backend',
|
|
help=(
|
|
'The resource name of the backend environment where the key material'
|
|
' for all CryptoKeyVersions associated with this CryptoKey reside and'
|
|
' where all related cryptographic operations are performed. Currently'
|
|
' only applicable for EXTERNAL_VPC and EkmConnection resource names.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddImportOnlyFlag(parser):
|
|
parser.add_argument(
|
|
'--import-only',
|
|
default=None,
|
|
action='store_true',
|
|
dest='import_only',
|
|
help='Restrict this key to imported versions only.',
|
|
)
|
|
|
|
|
|
def AddAllowedAccessReasonsFlag(parser):
|
|
parser.add_argument(
|
|
'--allowed-access-reasons',
|
|
type=arg_parsers.ArgList(
|
|
choices=maps.ACCESS_REASON_MAPPER.choices,
|
|
max_length=len(maps.ACCESS_REASON_MAPPER.choices),
|
|
),
|
|
metavar='ALLOWED_ACCESS_REASONS',
|
|
help=(
|
|
'The list of allowed Key Access Justifications access reasons on '
|
|
'the key. The key must be enrolled in Key Access Justifications to '
|
|
'configure this field. By default, this field is absent, and all '
|
|
'justification codes are allowed. For more information about '
|
|
'justification codes, see '
|
|
'https://cloud.google.com/assured-workloads/key-access-justifications/docs/justification-codes.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddRemoveKeyAccessJustificationsPolicyFlag(parser):
|
|
parser.add_argument(
|
|
'--remove-key-access-justifications-policy',
|
|
default=None,
|
|
action='store_true',
|
|
help=(
|
|
'Removes the Key Access Justifications policy on the key, making '
|
|
'all justification codes allowed.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddPublicKeyFormatFlag(parser):
|
|
parser.add_argument(
|
|
'--public-key-format',
|
|
default=None,
|
|
help='The format in which the public key will be returned.',
|
|
)
|
|
|
|
|
|
# Arguments
|
|
def AddKeyRingArgument(parser, help_action):
|
|
parser.add_argument(
|
|
'keyring',
|
|
completer=KeyRingCompleter,
|
|
help='Name of the key ring {0}.'.format(help_action),
|
|
)
|
|
|
|
|
|
def AddCryptoKeyArgument(parser, help_action):
|
|
parser.add_argument(
|
|
'key',
|
|
completer=KeyCompleter,
|
|
help='Name of the key {0}.'.format(help_action),
|
|
)
|
|
|
|
|
|
def AddKeyResourceArgument(parser, help_action):
|
|
AddLocationFlag(parser, 'key')
|
|
AddKeyRingFlag(parser, 'key')
|
|
AddCryptoKeyArgument(parser, help_action)
|
|
|
|
|
|
def AddCryptoKeyVersionArgument(parser, help_action):
|
|
parser.add_argument(
|
|
'version',
|
|
completer=KeyVersionCompleter,
|
|
help='Name of the version {0}.'.format(help_action),
|
|
)
|
|
|
|
|
|
def AddKeyVersionResourceArgument(parser, help_action):
|
|
AddKeyResourceFlags(parser)
|
|
AddCryptoKeyVersionArgument(parser, help_action)
|
|
|
|
|
|
def AddPositionalImportJobArgument(parser, help_action):
|
|
parser.add_argument(
|
|
'import_job',
|
|
completer=ImportJobCompleter,
|
|
help='Name of the import job {0}.'.format(help_action),
|
|
)
|
|
|
|
|
|
def AddRequiredImportJobArgument(parser, help_action):
|
|
parser.add_argument(
|
|
'--import-job',
|
|
completer=ImportJobCompleter,
|
|
help='Name of the import job {0}.'.format(help_action),
|
|
required=True,
|
|
)
|
|
|
|
|
|
def AddCertificateChainFlag(parser):
|
|
parser.add_argument(
|
|
'--certificate-chain-type',
|
|
default='all',
|
|
choices=['all', 'cavium', 'google-card', 'google-partition'],
|
|
help='Certificate chain to retrieve.',
|
|
)
|
|
|
|
|
|
def AddServiceDirectoryServiceFlag(parser, required=False):
|
|
parser.add_argument(
|
|
'--service-directory-service',
|
|
help=(
|
|
'The resource name of the Service Directory service pointing to '
|
|
'an EKM replica.'
|
|
),
|
|
required=required,
|
|
)
|
|
|
|
|
|
def AddEndpointFilterFlag(parser):
|
|
parser.add_argument(
|
|
'--endpoint-filter',
|
|
help=(
|
|
'The filter applied to the endpoints of the resolved service. '
|
|
'If no filter is specified, all endpoints will be considered.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddHostnameFlag(parser, required=False):
|
|
parser.add_argument(
|
|
'--hostname',
|
|
help='The hostname of the EKM replica used at TLS and HTTP layers.',
|
|
required=required,
|
|
)
|
|
|
|
|
|
def AddServerCertificatesFilesFlag(parser, required=False):
|
|
parser.add_argument(
|
|
'--server-certificates-files',
|
|
type=arg_parsers.ArgList(),
|
|
metavar='SERVER_CERTIFICATES',
|
|
help=(
|
|
'A list of filenames of leaf server certificates used to '
|
|
'authenticate HTTPS connections to the EKM replica in PEM format. If '
|
|
'files are not in PEM, the assumed format will be DER.'
|
|
),
|
|
required=required,
|
|
)
|
|
|
|
|
|
def AddKeyManagementModeFlags(parser):
|
|
"""Adds key-management-mode flags and related flags."""
|
|
|
|
group = parser.add_group(
|
|
help=(
|
|
'Specifies the key management mode for the EkmConnection and'
|
|
' associated fields.'
|
|
)
|
|
)
|
|
group.add_argument(
|
|
'--key-management-mode',
|
|
choices=['manual', 'cloud-kms'],
|
|
help=(
|
|
'Key management mode of the ekm connection. An EkmConnection in'
|
|
' `cloud-kms` mode means Cloud KMS will attempt to create and manage'
|
|
' the key material that resides on the EKM for crypto keys created'
|
|
' with this EkmConnection. An EkmConnection in `manual` mode means'
|
|
' the external key material will not be managed by Cloud KMS.'
|
|
' Omitting the flag defaults to `manual`.'
|
|
),
|
|
)
|
|
group.add_argument(
|
|
'--crypto-space-path',
|
|
help=(
|
|
'Crypto space path for the EkmConnection. Required during '
|
|
'EkmConnection creation if `--key-management-mode=cloud-kms`.'
|
|
),
|
|
)
|
|
|
|
|
|
def AddDefaultEkmConnectionFlag(parser, required=False):
|
|
parser.add_argument(
|
|
'--default-ekm-connection',
|
|
help=(
|
|
'The resource name of the EkmConnection to be used as the default'
|
|
' EkmConnection for all `external-vpc` CryptoKeys in a project and'
|
|
' location. Can be an empty string to remove the default'
|
|
' EkmConnection.'
|
|
),
|
|
required=required,
|
|
)
|
|
|
|
|
|
def AddResourceTypeSelectorFlag(parser, required=False):
|
|
parser.add_argument(
|
|
'--resource-type',
|
|
help=(
|
|
'The resource type selector for KeyHandle resources of the form'
|
|
' {{SERVICE}}.{{UNIVERSE_DOMAIN}}/{{TYPE}}.'
|
|
),
|
|
required=required,
|
|
)
|
|
|
|
|
|
def AddCreateKeyHandleFlags(parser):
|
|
resource_args.AddKmsLocationResourceArgForKMS(parser, True, '--location')
|
|
AddResourceTypeSelectorFlag(parser, True)
|
|
group = parser.add_group(mutex=True, required=True)
|
|
group.add_argument(
|
|
'--key-handle-id',
|
|
help='The KeyHandle id for the new KeyHandle resource.',
|
|
)
|
|
group.add_argument(
|
|
'--generate-key-handle-id',
|
|
help='Generate a KeyHandle id for the new KeyHandle resource.',
|
|
action='store_true',
|
|
)
|
|
|
|
|
|
def AddFolderIdFlag(parser, required=False):
|
|
parser.add_argument(
|
|
'--folder',
|
|
help='The folder id in which the AutokeyConfig resource exists.',
|
|
required=required,
|
|
)
|
|
|
|
|
|
def AddAutokeyConfigFileFlag(parser):
|
|
parser.add_argument(
|
|
'CONFIG_FILE',
|
|
help='The file containing the AutokeyConfig resource.',
|
|
)
|
|
|
|
|
|
# Parsing.
|
|
def ParseLocationName(args):
|
|
return resources.REGISTRY.Parse(
|
|
args.location,
|
|
params={'projectsId': properties.VALUES.core.project.GetOrFail},
|
|
collection=LOCATION_COLLECTION,
|
|
)
|
|
|
|
|
|
def ParseEkmConnectionName(args):
|
|
return resources.REGISTRY.Parse(
|
|
args.ekm_connection,
|
|
params={
|
|
'projectsId': properties.VALUES.core.project.GetOrFail,
|
|
'locationsId': args.MakeGetOrRaise('--location'),
|
|
},
|
|
collection=EKM_CONNECTION_COLLECTION,
|
|
)
|
|
|
|
|
|
def ParseKeyRingName(args):
|
|
return resources.REGISTRY.Parse(
|
|
args.keyring,
|
|
params={
|
|
'projectsId': properties.VALUES.core.project.GetOrFail,
|
|
'locationsId': args.MakeGetOrRaise('--location'),
|
|
},
|
|
collection=KEY_RING_COLLECTION,
|
|
)
|
|
|
|
|
|
def ParseCryptoKeyName(args):
|
|
return resources.REGISTRY.Parse(
|
|
args.key,
|
|
params={
|
|
'keyRingsId': args.MakeGetOrRaise('--keyring'),
|
|
'locationsId': args.MakeGetOrRaise('--location'),
|
|
'projectsId': properties.VALUES.core.project.GetOrFail,
|
|
},
|
|
collection=CRYPTO_KEY_COLLECTION,
|
|
)
|
|
|
|
|
|
def ParseCryptoKeyVersionName(args):
|
|
return resources.REGISTRY.Parse(
|
|
args.version,
|
|
params={
|
|
'cryptoKeysId': args.MakeGetOrRaise('--key'),
|
|
'keyRingsId': args.MakeGetOrRaise('--keyring'),
|
|
'locationsId': args.MakeGetOrRaise('--location'),
|
|
'projectsId': properties.VALUES.core.project.GetOrFail,
|
|
},
|
|
collection=CRYPTO_KEY_VERSION_COLLECTION,
|
|
)
|
|
|
|
|
|
def ParseImportJobName(args):
|
|
return resources.REGISTRY.Parse(
|
|
args.import_job,
|
|
params={
|
|
'keyRingsId': args.MakeGetOrRaise('--keyring'),
|
|
'locationsId': args.MakeGetOrRaise('--location'),
|
|
'projectsId': properties.VALUES.core.project.GetOrFail,
|
|
},
|
|
collection=IMPORT_JOB_COLLECTION,
|
|
)
|
|
|
|
|
|
def ParseSingleTenantHsmInstanceName(args):
|
|
return resources.REGISTRY.Parse(
|
|
args.single_tenant_hsm_instance,
|
|
params={
|
|
'projectsId': properties.VALUES.core.project.GetOrFail,
|
|
'locationsId': args.MakeGetOrRaise('--location'),
|
|
},
|
|
collection=SINGLE_TENANT_HSM_INSTANCE_COLLECTION,
|
|
)
|
|
|
|
|
|
# Get parent type Resource from output of Parse functions above.
|
|
def ParseParentFromResource(resource_ref):
|
|
collection_list = resource_ref.Collection().split('.')
|
|
parent_collection = '.'.join(collection_list[:-1])
|
|
params = resource_ref.AsDict()
|
|
del params[collection_list[-1] + 'Id']
|
|
return resources.REGISTRY.Create(parent_collection, **params)
|
|
|
|
|
|
# Set proto fields from flags.
|
|
def SetRotationPeriod(args, crypto_key):
|
|
if args.rotation_period is not None:
|
|
crypto_key.rotationPeriod = '{0}s'.format(args.rotation_period)
|
|
|
|
|
|
def SetNextRotationTime(args, crypto_key):
|
|
if args.next_rotation_time is not None:
|
|
crypto_key.nextRotationTime = times.FormatDateTime(args.next_rotation_time)
|
|
|
|
|
|
def SetDestroyScheduledDuration(args, crypto_key):
|
|
if args.destroy_scheduled_duration is not None:
|
|
crypto_key.destroyScheduledDuration = '{0}s'.format(
|
|
args.destroy_scheduled_duration
|
|
)
|
|
|
|
|
|
def SetKeyAccessJustificationsPolicy(args, crypto_key):
|
|
messages = cloudkms_base.GetMessagesModule()
|
|
if args.allowed_access_reasons is not None:
|
|
allowed_access_reasons = []
|
|
for access_reason in args.allowed_access_reasons:
|
|
reason_string = maps.ACCESS_REASON_MAPPER.GetEnumForChoice(access_reason)
|
|
if reason_string not in allowed_access_reasons:
|
|
allowed_access_reasons.append(reason_string)
|
|
crypto_key.keyAccessJustificationsPolicy = (
|
|
messages.KeyAccessJustificationsPolicy(
|
|
allowedAccessReasons=allowed_access_reasons
|
|
)
|
|
)
|