Ejemplo n.º 1
0
    def testParseReusableConfigInlineValues(self):
        concept_parsers.ConceptParser.ForResource(
            '--reusable-config',
            resource_args.CreateReusableConfigResourceSpec(),
            'Reusable config for this CA.',
            prefixes=True).AddToParser(self.parser)
        flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
        args = self.parser.parse_args([
            '--key-usages', 'cert_sign,crl_sign', '--extended-key-usages',
            'server_auth,client_auth', '--max-chain-length', '2'
        ])
        reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                            'us-west1',
                                                            is_ca=True)
        self.assertIsNone(reusable_config_wrapper.reusableConfig)
        values = reusable_config_wrapper.reusableConfigValues
        self.assertTrue(values.keyUsage.baseKeyUsage.certSign)
        self.assertTrue(values.keyUsage.baseKeyUsage.crlSign)
        self.assertIsNone(values.keyUsage.baseKeyUsage.digitalSignature)
        self.assertIsNone(values.keyUsage.baseKeyUsage.contentCommitment)
        self.assertIsNone(values.keyUsage.baseKeyUsage.keyEncipherment)
        self.assertIsNone(values.keyUsage.baseKeyUsage.dataEncipherment)
        self.assertIsNone(values.keyUsage.baseKeyUsage.keyAgreement)
        self.assertIsNone(values.keyUsage.baseKeyUsage.encipherOnly)
        self.assertIsNone(values.keyUsage.baseKeyUsage.decipherOnly)

        self.assertTrue(values.keyUsage.extendedKeyUsage.serverAuth)
        self.assertTrue(values.keyUsage.extendedKeyUsage.clientAuth)
        self.assertIsNone(values.keyUsage.extendedKeyUsage.codeSigning)
        self.assertIsNone(values.keyUsage.extendedKeyUsage.emailProtection)
        self.assertIsNone(values.keyUsage.extendedKeyUsage.timeStamping)
        self.assertIsNone(values.keyUsage.extendedKeyUsage.ocspSigning)

        self.assertEqual(values.caOptions.maxIssuerPathLength, 2)
        self.assertTrue(values.caOptions.isCa)
Ejemplo n.º 2
0
 def testParseReusableConfigResourceAndInlineValues(self):
     concept_parsers.ConceptParser.ForResource(
         '--reusable-config',
         resource_args.CreateReusableConfigResourceSpec('CA'),
         'Reusable config for this CA.',
         prefixes=True).AddToParser(self.parser)
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     args = self.parser.parse_args([
         '--reusable-config',
         'projects/foo/locations/us/reusableConfigs/rc1', '--key-usages',
         'cert_sign,crl_sign'
     ])
     with self.AssertRaisesExceptionMatches(Exception, 'Invalid value'):
         flags.ParseReusableConfig(args, 'us-west1', is_ca=True)
Ejemplo n.º 3
0
    def testParseReusableConfigNoResourceAndNoInlineCertificateValues(self):
        concept_parsers.ConceptParser.ForResource(
            '--reusable-config',
            resource_args.CreateReusableConfigResourceSpec(),
            'Reusable config for this CA.',
            prefixes=True).AddToParser(self.parser)
        flags.AddInlineReusableConfigFlags(self.parser, is_ca=False)
        args = self.parser.parse_args([])
        reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                            'us-west',
                                                            is_ca=False)

        self.assertIsNone(reusable_config_wrapper.reusableConfig)
        self.assertEqual(
            reusable_config_wrapper.reusableConfigValues.caOptions.isCa, False)
Ejemplo n.º 4
0
 def Args(parser):
     reusable_config_group = parser.add_group(
         mutex=True,
         required=False,
         help='The X.509 configuration used for the CA certificate.')
     concept_parsers.ConceptParser([
         presentation_specs.ResourcePresentationSpec(
             'CERTIFICATE_AUTHORITY',
             privateca_resource_args.CreateCertificateAuthorityResourceSpec(
                 'Certificate Authority'),
             'The name of the root CA to create.',
             required=True,
             # We'll get these from the KMS key resource.
             flag_name_overrides={
                 'location': '',
                 'project': '',
             }),
         presentation_specs.ResourcePresentationSpec(
             '--kms-key-version',
             kms_resource_args.GetKmsKeyVersionResourceSpec(),
             'The KMS key version backing this CA.',
             required=True),
         presentation_specs.ResourcePresentationSpec(
             '--reusable-config',
             privateca_resource_args.CreateReusableConfigResourceSpec(
                 location_fallthrough=deps.Fallthrough(
                     function=lambda: '',
                     hint=('location will default to the same location as '
                           'the CA'),
                     active=False,
                     plural=False)),
             'The Reusable Config containing X.509 values for this CA.',
             flag_name_overrides={
                 'location': '',
                 'project': '',
             },
             group=reusable_config_group)
     ]).AddToParser(parser)
     flags.AddSubjectFlags(parser, subject_required=True)
     flags.AddPublishCaCertFlag(parser, use_update_help_text=False)
     flags.AddPublishCrlFlag(parser, use_update_help_text=False)
     flags.AddInlineReusableConfigFlags(reusable_config_group, is_ca=True)
     flags.AddValidityFlag(parser,
                           resource_name='CA',
                           default_value='P10Y',
                           default_value_text='10 years')
     flags.AddCertificateAuthorityIssuancePolicyFlag(parser)
     labels_util.AddCreateLabelsFlags(parser)
Ejemplo n.º 5
0
 def testParseReusableConfigShortResourceArg(self):
     concept_parsers.ConceptParser.ForResource(
         '--reusable-config',
         resource_args.CreateReusableConfigResourceSpec('CA'),
         'Reusable config for this CA.',
         prefixes=True).AddToParser(self.parser)
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     args = self.parser.parse_args(['--reusable-config', 'rc1'])
     reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                         'us-central1',
                                                         is_ca=True)
     self.assertEqual(
         reusable_config_wrapper.reusableConfig,
         'projects/privateca-data/locations/us-central1/reusableConfigs/rc1'
     )
     self.assertEqual(reusable_config_wrapper.reusableConfigValues, None)
Ejemplo n.º 6
0
 def testParseReusableConfigInlineCertificateValues(self):
     concept_parsers.ConceptParser.ForResource(
         '--reusable-config',
         resource_args.CreateReusableConfigResourceSpec('certificate'),
         'Reusable config for this certificate.',
         prefixes=True).AddToParser(self.parser)
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=False)
     args = self.parser.parse_args([
         '--key-usages', 'cert_sign,crl_sign', '--extended-key-usages',
         'server_auth,client_auth', '--no-is-ca-cert'
     ])
     reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                         'us-west1',
                                                         is_ca=False)
     self.assertEqual(
         reusable_config_wrapper.reusableConfigValues.caOptions.isCa, False)
Ejemplo n.º 7
0
 def testParseReusableConfigMaxChainLengthIgnored(self):
     concept_parsers.ConceptParser.ForResource(
         '--reusable-config',
         resource_args.CreateReusableConfigResourceSpec(),
         'Reusable config for this CA.',
         prefixes=True).AddToParser(self.parser)
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=False)
     args = self.parser.parse_args(
         ['--no-is-ca-cert', '--max-chain-length', '1'])
     reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                         'us-west1',
                                                         is_ca=False)
     self.assertEqual(
         reusable_config_wrapper.reusableConfigValues.caOptions.isCa, False)
     self.assertIsNone(reusable_config_wrapper.reusableConfigValues.
                       caOptions.maxIssuerPathLength)
Ejemplo n.º 8
0
 def testParseReusableConfigIsCa(self):
     concept_parsers.ConceptParser.ForResource(
         '--reusable-config',
         resource_args.CreateReusableConfigResourceSpec(),
         'Reusable config for this CA.',
         prefixes=True).AddToParser(self.parser)
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     args = self.parser.parse_args([])
     reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                         'us-west1',
                                                         is_ca=True)
     self.assertTrue(
         reusable_config_wrapper.reusableConfigValues.caOptions.isCa)
     self.assertTrue(reusable_config_wrapper.reusableConfigValues.keyUsage.
                     baseKeyUsage.certSign)
     self.assertTrue(reusable_config_wrapper.reusableConfigValues.keyUsage.
                     baseKeyUsage.crlSign)
Ejemplo n.º 9
0
    def testParseReusableConfigFullyQualifiedResourceArg(self):
        reusable_config_id = 'projects/foo/locations/us-west1/reusableConfigs/rc1'
        concept_parsers.ConceptParser.ForResource(
            '--reusable-config',
            resource_args.CreateReusableConfigResourceSpec('CA'),
            'Reusable config for this CA.',
            prefixes=True).AddToParser(self.parser)
        flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
        args = self.parser.parse_args(
            ['--reusable-config', reusable_config_id])

        # We expect the parser to ignore the 'us-central1' hint here since the
        # resource name explicitly specifies 'us-west1'.
        reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                            'us-central1',
                                                            is_ca=True)
        self.assertEqual(reusable_config_wrapper.reusableConfig,
                         reusable_config_id)
        self.assertEqual(reusable_config_wrapper.reusableConfigValues, None)
Ejemplo n.º 10
0
 def testParseReusableConfigMaxChainLength(self):
     concept_parsers.ConceptParser.ForResource(
         '--reusable-config',
         resource_args.CreateReusableConfigResourceSpec(),
         'Reusable config for this CA.',
         prefixes=True).AddToParser(self.parser)
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     args = self.parser.parse_args(['--max-chain-length', '1'])
     reusable_config_wrapper = flags.ParseReusableConfig(args,
                                                         'us-west1',
                                                         is_ca=True)
     self.assertTrue(
         reusable_config_wrapper.reusableConfigValues.caOptions.isCa)
     self.assertEqual(
         reusable_config_wrapper.reusableConfigValues.caOptions.
         maxIssuerPathLength, 1)
     self.assertTrue(reusable_config_wrapper.reusableConfigValues.keyUsage.
                     baseKeyUsage.certSign)
     self.assertTrue(reusable_config_wrapper.reusableConfigValues.keyUsage.
                     baseKeyUsage.crlSign)
Ejemplo n.º 11
0
 def testAddReusableConfigFlagsMaxChainLength(self):
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     args = self.parser.parse_args(['--max-chain-length', '1'])
     self.assertEqual(args.max_chain_length, '1')
Ejemplo n.º 12
0
 def testAddReusableConfigFlagsInvalidExtendedKeyUsages(self):
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     with self.AssertRaisesExceptionMatches(
             Exception, 'argument --extended-key-usages'):
         self.parser.parse_args(
             ['--extended-key-usages', 'not_server_auth'])
Ejemplo n.º 13
0
 def testAddReusableConfigFlagsExtendedKeyUsagesWithSpaces(self):
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     args = self.parser.parse_args(
         ['--extended-key-usages', 'server_auth, client_auth'])
     self.assertEqual(args.extended_key_usages,
                      ['server_auth', 'client_auth'])
Ejemplo n.º 14
0
 def testAddReusableConfigFlagsKeyUsagesWithSpaces(self):
     flags.AddInlineReusableConfigFlags(self.parser, is_ca=True)
     args = self.parser.parse_args(['--key-usages', 'cert_sign, crl_sign'])
     self.assertEqual(args.key_usages, ['cert_sign', 'crl_sign'])
Ejemplo n.º 15
0
    def Args(parser):
        base.Argument(
            '--cert-output-file',
            help=
            'The path where the resulting PEM-encoded certificate chain file should be written (ordered from leaf to root).',
            required=False).AddToParser(parser)
        flags.AddValidityFlag(parser, 'certificate', 'P30D', '30 days')
        labels_util.AddCreateLabelsFlags(parser)

        cert_generation_group = parser.add_group(
            mutex=True, required=True, help='Certificate generation method.')
        base.Argument(
            '--csr',
            help='A PEM-encoded certificate signing request file path.'
        ).AddToParser(cert_generation_group)

        key_generation_group = cert_generation_group.add_group(
            help='Alternatively, to generate a new key pair, use the following:'
        )
        base.Argument(
            '--generate-key',
            help=
            'Use this flag to have a new RSA-2048 private key securely generated on your machine.',
            action='store_const',
            const=True,
            default=False,
            required=True).AddToParser(key_generation_group)
        base.Argument('--key-output-file', help=KEY_OUTPUT_HELP,
                      required=True).AddToParser(key_generation_group)

        subject_group = key_generation_group.add_group(
            help='The subject names for the certificate.', required=True)
        flags.AddSubjectFlags(subject_group)
        reusable_config_group = key_generation_group.add_group(
            mutex=True,
            help='The x509 configuration used for this certificate.')
        flags.AddInlineReusableConfigFlags(reusable_config_group, is_ca=False)

        cert_arg = 'CERTIFICATE'
        id_fallthrough = deps.Fallthrough(
            function=certificate_utils.GenerateCertId,
            hint='certificate id will default to an automatically generated id',
            active=False,
            plural=False)
        concept_parsers.ConceptParser([
            presentation_specs.ResourcePresentationSpec(
                cert_arg,
                resource_args.CreateCertificateResourceSpec(
                    cert_arg, [id_fallthrough]),
                'The name of the certificate to issue. If the name is omitted, a '
                'random name will be generated according to the following format'
                ': {YYYYMMDD}-{3 random alphanumeric characters}-{3 random alph'
                'anumeric characters}.',
                required=True)
        ]).AddToParser(parser)

        concept_parsers.ConceptParser([
            presentation_specs.ResourcePresentationSpec(
                '--reusable-config',
                resource_args.CreateReusableConfigResourceSpec(
                    location_fallthrough=deps.Fallthrough(
                        function=lambda: '',
                        hint=(
                            'location will default to the same location as the '
                            'certificate'),
                        active=False,
                        plural=False)),
                'The Reusable Config containing X.509 values for this certificate.',
                flag_name_overrides={
                    'location': '',
                    'project': '',
                },
                group=reusable_config_group)
        ]).AddToParser(reusable_config_group)
Ejemplo n.º 16
0
    def Args(parser):
        base.Argument(
            '--cert-output-file',
            help=
            'The path where the resulting PEM-encoded certificate chain file should be written (ordered from leaf to root).',
            required=False).AddToParser(parser)
        flags.AddValidityFlag(parser, 'certificate', 'P30D', '30 days')
        labels_util.AddCreateLabelsFlags(parser)

        cert_generation_group = parser.add_group(
            mutex=True, required=True, help='Certificate generation method.')
        base.Argument(
            '--csr',
            help='A PEM-encoded certificate signing request file path.'
        ).AddToParser(cert_generation_group)

        # This group is not useful in the beta command, but is here for consistency
        # in the flag hierarchy with the GA command.
        non_csr_group = cert_generation_group.add_group(
            help=
            'Alternatively, you may describe the certificate and key to use.')
        key_group = non_csr_group.add_group(
            mutex=True,
            required=True,
            help=
            'To describe the key that will be used for this certificate, use '
            'one of the following options.')
        key_generation_group = key_group.add_group(
            help='To generate a new key pair, use the following:')
        base.Argument(
            '--generate-key',
            help=
            'Use this flag to have a new RSA-2048 private key securely generated on your machine.',
            action='store_const',
            const=True,
            default=False,
            required=True).AddToParser(key_generation_group)
        base.Argument('--key-output-file',
                      help=_KEY_OUTPUT_HELP,
                      required=True).AddToParser(key_generation_group)

        subject_group = non_csr_group.add_group(
            help='The subject names for the certificate.', required=True)
        flags.AddSubjectFlags(subject_group)
        reusable_config_group = non_csr_group.add_group(
            mutex=True,
            help='The x509 configuration used for this certificate.')
        flags.AddInlineReusableConfigFlags(reusable_config_group,
                                           is_ca_command=False,
                                           default_max_chain_length=0)

        cert_arg = 'CERTIFICATE'
        concept_parsers.ConceptParser([
            presentation_specs.ResourcePresentationSpec(
                cert_arg,
                resource_args.CreateCertificateResourceSpec(
                    cert_arg,
                    [CreateBeta._GenerateCertificateIdFallthrough()]),
                'The name of the certificate to issue. If the certificate ID is '
                'omitted, a random identifier will be generated according to the '
                'following format: {YYYYMMDD}-{3 random alphanumeric characters}-'
                '{3 random alphanumeric characters}. The certificate ID is not '
                'required when the issuing CA is in the DevOps tier.',
                required=True)
        ]).AddToParser(parser)

        concept_parsers.ConceptParser([
            presentation_specs.ResourcePresentationSpec(
                '--reusable-config',
                resource_args.
                CreateReusableConfigResourceSpec(location_fallthroughs=[
                    deps.Fallthrough(
                        function=lambda: '',
                        hint=(
                            'location will default to the same location as the '
                            'certificate'),
                        active=False,
                        plural=False)
                ]),
                'The Reusable Config containing X.509 values for this certificate.',
                flag_name_overrides={
                    'location': '',
                    'project': '',
                },
                group=reusable_config_group)
        ]).AddToParser(reusable_config_group)
Ejemplo n.º 17
0
    def Args(parser):
        reusable_config_group = parser.add_group(
            mutex=True,
            required=False,
            help='The X.509 configuration used for the CA certificate.')
        issuer_configuration_group = parser.add_group(
            mutex=True,
            required=True,
            help='The issuer configuration used for this CA certificate.')

        concept_parsers.ConceptParser([
            presentation_specs.ResourcePresentationSpec(
                'CERTIFICATE_AUTHORITY',
                privateca_resource_args.CreateCertificateAuthorityResourceSpec(
                    'Certificate Authority'),
                'The name of the subordinate CA to create.',
                required=True,
                # We'll get these from the KMS key resource.
                flag_name_overrides={
                    'location': '',
                    'project': '',
                }),
            presentation_specs.ResourcePresentationSpec(
                '--issuer',
                privateca_resource_args.CreateCertificateAuthorityResourceSpec(
                    'Issuer'),
                'The issuing certificate authority to use, if it is on Private CA.',
                prefixes=True,
                group=issuer_configuration_group),
            presentation_specs.ResourcePresentationSpec(
                '--kms-key-version',
                kms_resource_args.GetKmsKeyVersionResourceSpec(),
                'The KMS key version backing this CA.',
                required=True),
            presentation_specs.ResourcePresentationSpec(
                '--reusable-config',
                privateca_resource_args.CreateReusableConfigResourceSpec(
                    location_fallthrough=deps.Fallthrough(
                        function=lambda: '',
                        hint=(
                            'location will default to the same location as the '
                            'CA'),
                        active=False,
                        plural=False)),
                'The Reusable Config containing X.509 values for this CA.',
                flag_name_overrides={
                    'location': '',
                    'project': '',
                },
                group=reusable_config_group)
        ]).AddToParser(parser)
        flags.AddSubjectFlags(parser, subject_required=True)
        flags.AddPublishCaCertFlag(parser, use_update_help_text=False)
        flags.AddPublishCrlFlag(parser, use_update_help_text=False)
        flags.AddInlineReusableConfigFlags(reusable_config_group, is_ca=True)
        flags.AddValidityFlag(parser,
                              resource_name='CA',
                              default_value='P10Y',
                              default_value_text='10 years')
        flags.AddCertificateAuthorityIssuancePolicyFlag(parser)
        labels_util.AddCreateLabelsFlags(parser)

        offline_issuer_group = issuer_configuration_group.add_group(help=(
            'If the issuing CA is not hosted on Private CA, you must provide '
            'these settings:'))
        base.Argument(
            '--create-csr',
            help=
            ('Indicates that a CSR should be generated which can be signed by '
             'the issuing CA. This must be set if --issuer is not provided.'),
            action='store_const',
            const=True,
            default=False,
            required=True).AddToParser(offline_issuer_group)
        base.Argument(
            '--csr-output-file',
            help=(
                'The path where the resulting PEM-encoded CSR file should be '
                'written.'),
            required=True).AddToParser(offline_issuer_group)
Ejemplo n.º 18
0
    def Args(parser):
        key_spec_group = parser.add_group(
            mutex=True,
            help=
            'The key configuration used for the CA certificate. Defaults to a '
            'managed key if not specified.')
        reusable_config_group = parser.add_group(
            mutex=True,
            required=False,
            help='The X.509 configuration used for the CA certificate.')
        issuer_configuration_group = parser.add_group(
            mutex=True,
            required=True,
            help='The issuer configuration used for this CA certificate.')

        concept_parsers.ConceptParser([
            presentation_specs.ResourcePresentationSpec(
                'CERTIFICATE_AUTHORITY',
                resource_args.CreateCertificateAuthorityResourceSpec(
                    'Certificate Authority'),
                'The name of the subordinate CA to create.',
                required=True),
            presentation_specs.ResourcePresentationSpec(
                '--issuer',
                resource_args.CreateCertificateAuthorityResourceSpec('Issuer'),
                'The issuing certificate authority to use, if it is on Private CA.',
                prefixes=True,
                group=issuer_configuration_group),
            presentation_specs.ResourcePresentationSpec(
                '--kms-key-version',
                resource_args.CreateKmsKeyVersionResourceSpec(),
                'The KMS key version backing this CA.',
                group=key_spec_group),
            presentation_specs.ResourcePresentationSpec(
                '--reusable-config',
                resource_args.
                CreateReusableConfigResourceSpec(location_fallthroughs=[
                    deps.Fallthrough(
                        function=lambda: '',
                        hint=(
                            'location will default to the same location as the '
                            'CA'),
                        active=False,
                        plural=False)
                ]),
                'The Reusable Config containing X.509 values for this CA.',
                flag_name_overrides={
                    'location': '',
                    'project': '',
                },
                group=reusable_config_group),
            presentation_specs.ResourcePresentationSpec(
                '--from-ca',
                resource_args.CreateCertificateAuthorityResourceSpec(
                    'source CA'),
                'An existing CA from which to copy configuration values for the '
                'new CA. You can still override any of those values by explicitly '
                'providing the appropriate flags.',
                flag_name_overrides={'project': '--from-ca-project'},
                prefixes=True)
        ]).AddToParser(parser)
        flags.AddTierFlag(parser)
        flags.AddSubjectFlags(parser, subject_required=False)
        flags.AddPublishCaCertFlag(parser, use_update_help_text=False)
        flags.AddPublishCrlFlag(parser, use_update_help_text=False)
        flags.AddKeyAlgorithmFlag(key_spec_group,
                                  default='rsa-pkcs1-2048-sha256')
        flags.AddInlineReusableConfigFlags(reusable_config_group, is_ca=True)
        flags.AddValidityFlag(parser,
                              resource_name='CA',
                              default_value='P3Y',
                              default_value_text='3 years')
        flags.AddCertificateAuthorityIssuancePolicyFlag(parser)
        labels_util.AddCreateLabelsFlags(parser)
        flags.AddBucketFlag(parser)

        offline_issuer_group = issuer_configuration_group.add_group(help=(
            'If the issuing CA is not hosted on Private CA, you must provide '
            'these settings:'))
        base.Argument(
            '--create-csr',
            help=
            ('Indicates that a CSR should be generated which can be signed by '
             'the issuing CA. This must be set if --issuer is not provided.'),
            action='store_const',
            const=True,
            default=False,
            required=True).AddToParser(offline_issuer_group)
        base.Argument(
            '--csr-output-file',
            help=(
                'The path where the resulting PEM-encoded CSR file should be '
                'written.'),
            required=True).AddToParser(offline_issuer_group)
  def Args(parser):
    key_spec_group = parser.add_group(
        mutex=True,
        help='The key configuration used for the CA certificate. Defaults to a '
        'managed key if not specified.')
    reusable_config_group = parser.add_group(
        mutex=True,
        required=False,
        help='The X.509 configuration used for the CA certificate.')

    concept_parsers.ConceptParser([
        presentation_specs.ResourcePresentationSpec(
            'CERTIFICATE_AUTHORITY',
            resource_args.CreateCertificateAuthorityResourceSpec(
                'Certificate Authority'),
            'The name of the root CA to create.',
            required=True),
        presentation_specs.ResourcePresentationSpec(
            '--kms-key-version',
            resource_args.CreateKmsKeyVersionResourceSpec(),
            'An existing KMS key version to back this CA.',
            group=key_spec_group),
        presentation_specs.ResourcePresentationSpec(
            '--reusable-config',
            resource_args.CreateReusableConfigResourceSpec(
                location_fallthroughs=[
                    deps.Fallthrough(
                        function=lambda: '',
                        hint=('location will default to the same location as '
                              'the CA'),
                        active=False,
                        plural=False)
                ]),
            'The Reusable Config containing X.509 values for this CA.',
            flag_name_overrides={
                'location': '',
                'project': '',
            },
            group=reusable_config_group),
        presentation_specs.ResourcePresentationSpec(
            '--from-ca',
            resource_args.CreateCertificateAuthorityResourceSpec('source CA'),
            'An existing CA from which to copy configuration values for the new CA. '
            'You can still override any of those values by explicitly providing '
            'the appropriate flags.',
            flag_name_overrides={'project': '--from-ca-project'},
            prefixes=True)
    ]).AddToParser(parser)
    flags.AddSubjectFlags(parser, subject_required=False)
    flags.AddKeyAlgorithmFlag(key_spec_group, default='rsa-pkcs1-4096-sha256')
    flags.AddValidityFlag(
        parser,
        resource_name='CA',
        default_value='P10Y',
        default_value_text='10 years')
    labels_util.AddCreateLabelsFlags(parser)
    flags.AddBucketFlag(parser)
    flags.AddTierFlag(parser)
    flags.AddPublishCaCertFlag(parser, use_update_help_text=False)
    flags.AddPublishCrlFlag(parser, use_update_help_text=False)
    flags.AddCertificateAuthorityIssuancePolicyFlag(parser)
    flags.AddInlineReusableConfigFlags(
        reusable_config_group,
        is_ca_command=True,
        default_max_chain_length=None)