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)
def Run(self, args): kms_key_version_ref, ca_ref = self.ParseResourceArgs(args) kms_key_ref = kms_key_version_ref.Parent() project_ref = ca_ref.Parent().Parent() subject_config = flags.ParseSubjectFlags(args, is_ca=True) issuing_options = flags.ParseIssuingOptions(args) issuance_policy = flags.ParseIssuancePolicy(args) reusable_config_wrapper = flags.ParseReusableConfig(args, ca_ref.locationsId, is_ca=True) lifetime = flags.ParseValidityFlag(args) labels = labels_util.ParseCreateArgs( args, self.messages.CertificateAuthority.LabelsValue) iam.CheckCreateCertificateAuthorityPermissions(project_ref, kms_key_ref) p4sa_email = p4sa.GetOrCreate(project_ref) bucket_ref = storage.CreateBucketForCertificateAuthority(ca_ref) p4sa.AddResourceRoleBindings(p4sa_email, kms_key_ref, bucket_ref) new_ca = self.messages.CertificateAuthority( type=self.messages.CertificateAuthority.TypeValueValuesEnum. SELF_SIGNED, lifetime=lifetime, config=self.messages.CertificateConfig( reusableConfig=reusable_config_wrapper, subjectConfig=subject_config), cloudKmsKeyVersion=kms_key_version_ref.RelativeName(), certificatePolicy=issuance_policy, issuingOptions=issuing_options, gcsBucket=bucket_ref.bucket, labels=labels) operation = self.client.projects_locations_certificateAuthorities.Create( self.messages. PrivatecaProjectsLocationsCertificateAuthoritiesCreateRequest( certificateAuthority=new_ca, certificateAuthorityId=ca_ref.Name(), parent=ca_ref.Parent().RelativeName(), requestId=request_utils.GenerateRequestId())) ca_response = operations.Await(operation, 'Creating Certificate Authority.') ca = operations.GetMessageFromResponse( ca_response, self.messages.CertificateAuthority) log.status.Print('Creating the initial Certificate Revocation List.') self.client.projects_locations_certificateAuthorities.PublishCrl( self.messages. PrivatecaProjectsLocationsCertificateAuthoritiesPublishCrlRequest( name=ca.name, publishCertificateRevocationListRequest=self.messages. PublishCertificateRevocationListRequest())) log.status.Print('Created Certificate Authority [{}].'.format(ca.name))
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)
def _GenerateCertificateConfig(self, request, args, location): private_key, public_key = key_generation.RSAKeyGen(2048) key_generation.ExportPrivateKey(args.key_output_file, private_key) config = self.messages.CertificateConfig() config.publicKey = self.messages.PublicKey() config.publicKey.key = public_key config.publicKey.type = self.messages.PublicKey.TypeValueValuesEnum.PEM_RSA_KEY config.reusableConfig = flags.ParseReusableConfig( args, location, is_ca_command=args.is_ca_cert) config.subjectConfig = flags.ParseSubjectFlags(args, is_ca=args.is_ca_cert) return config
def _GenerateCertificateConfig(self, request, args): messages = privateca_base.GetMessagesModule() private_key, public_key = key_generation.RSAKeyGen(2048) key_generation.ExportPrivateKey(args.key_output_file, private_key) config = messages.CertificateConfig() config.publicKey = messages.PublicKey() config.publicKey.key = public_key config.publicKey.type = messages.PublicKey.TypeValueValuesEnum.PEM_RSA_KEY config.reusableConfig = flags.ParseReusableConfig(args) config.subjectConfig = flags.ParseSubjectFlags(args, is_ca=False) return config
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)
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)
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)
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)
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)
def Run(self, args): kms_key_version_ref, ca_ref = self.ParseResourceArgs(args) kms_key_ref = kms_key_version_ref.Parent() project_ref = ca_ref.Parent().Parent() common_name, subject = flags.ParseSubject(args.subject) subject_alt_names = flags.ParseSanFlags(args) issuing_options = flags.ParseIssuingOptions(args) issuance_policy = flags.ParseIssuancePolicy(args) reusable_config_wrapper = flags.ParseReusableConfig(args) lifetime = flags.ParseValidityFlag(args) labels = labels_util.ParseCreateArgs( args, self.messages.CertificateAuthority.LabelsValue) iam.CheckCreateCertificateAuthorityPermissions(project_ref, kms_key_ref) p4sa_email = p4sa.GetOrCreate(project_ref) bucket_ref = storage.CreateBucketForCertificateAuthority(ca_ref) p4sa.AddResourceRoleBindings(p4sa_email, kms_key_ref, bucket_ref) new_ca = self.messages.CertificateAuthority( type=self.messages.CertificateAuthority.TypeValueValuesEnum.SELF_SIGNED, lifetime=lifetime, config=self.messages.CertificateConfig( reusableConfig=reusable_config_wrapper, subjectConfig=self.messages.SubjectConfig( commonName=common_name, subject=subject, subjectAltName=subject_alt_names)), cloudKmsKeyVersion=kms_key_version_ref.RelativeName(), certificatePolicy=issuance_policy, issuingOptions=issuing_options, gcsBucket=bucket_ref.bucket, labels=labels) operation = self.client.projects_locations_certificateAuthorities.Create( self.messages .PrivatecaProjectsLocationsCertificateAuthoritiesCreateRequest( certificateAuthority=new_ca, certificateAuthorityId=ca_ref.Name(), parent=ca_ref.Parent().RelativeName(), requestId=request_utils.GenerateRequestId())) return operations.Await(operation, 'Creating Certificate Authority.')
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)
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)
def Run(self, args): kms_key_version_ref, ca_ref, issuer_ref = _ParseResourceArgs(args) kms_key_ref = kms_key_version_ref.Parent() project_ref = ca_ref.Parent().Parent() subject_config = flags.ParseSubjectFlags(args, is_ca=True) issuing_options = flags.ParseIssuingOptions(args) issuance_policy = flags.ParseIssuancePolicy(args) reusable_config_wrapper = flags.ParseReusableConfig(args, ca_ref.locationsId, is_ca=True) lifetime = flags.ParseValidityFlag(args) labels = labels_util.ParseCreateArgs( args, self.messages.CertificateAuthority.LabelsValue) iam.CheckCreateCertificateAuthorityPermissions(project_ref, kms_key_ref) if issuer_ref: iam.CheckCreateCertificatePermissions(issuer_ref) p4sa_email = p4sa.GetOrCreate(project_ref) bucket_ref = storage.CreateBucketForCertificateAuthority(ca_ref) p4sa.AddResourceRoleBindings(p4sa_email, kms_key_ref, bucket_ref) new_ca = self.messages.CertificateAuthority( type=self.messages.CertificateAuthority.TypeValueValuesEnum. SUBORDINATE, lifetime=lifetime, config=self.messages.CertificateConfig( reusableConfig=reusable_config_wrapper, subjectConfig=subject_config), cloudKmsKeyVersion=kms_key_version_ref.RelativeName(), certificatePolicy=issuance_policy, issuingOptions=issuing_options, gcsBucket=bucket_ref.bucket, labels=labels) operations.Await( self.client.projects_locations_certificateAuthorities.Create( self.messages. PrivatecaProjectsLocationsCertificateAuthoritiesCreateRequest( certificateAuthority=new_ca, certificateAuthorityId=ca_ref.Name(), parent=ca_ref.Parent().RelativeName(), requestId=request_utils.GenerateRequestId())), 'Creating Certificate Authority.') csr_response = self.client.projects_locations_certificateAuthorities.GetCsr( self.messages. PrivatecaProjectsLocationsCertificateAuthoritiesGetCsrRequest( name=ca_ref.RelativeName())) csr = csr_response.pemCsr if args.create_csr: files.WriteFileContents(args.csr_output_file, csr) log.status.Print( "Created Certificate Authority [{}] and saved CSR to '{}'.". format(ca_ref.RelativeName(), args.csr_output_file)) return if issuer_ref: ca_certificate = self._SignCsr(issuer_ref, csr, lifetime) self._ActivateCertificateAuthority(ca_ref, ca_certificate) log.status.Print('Created Certificate Authority [{}].'.format( ca_ref.RelativeName())) return # This should not happen because of the required arg group, but it protects # us in case of future additions. raise exceptions.OneOfArgumentsRequiredException([ '--issuer', '--create-csr' ], ('To create a subordinate CA, please provide either an issuer or the ' '--create-csr flag to output a CSR to be signed by another issuer.' ))
def CreateCAFromArgs(args, is_subordinate): """Creates a CA object from CA create flags. Args: args: The parser that contains the flag values. is_subordinate: If True, a subordinate CA is returned, otherwise a root CA. Returns: A tuple for the CA to create with (CA object, CA ref, issuer). """ client = privateca_base.GetClientInstance() messages = privateca_base.GetMessagesModule() ca_ref, source_ca_ref, issuer_ref = _ParseCAResourceArgs( args) source_ca = None if source_ca_ref: source_ca = client.projects_locations_certificateAuthorities.Get( messages.PrivatecaProjectsLocationsCertificateAuthoritiesGetRequest( name=source_ca_ref.RelativeName())) if not source_ca: raise exceptions.InvalidArgumentException( '--from-ca', 'The provided source CA could not be retrieved.') tier = flags.ParseTierFlag(args) keyspec = flags.ParseKeySpec(args) if tier == messages.CertificateAuthority.TierValueValuesEnum.DEVOPS and keyspec.cloudKmsKeyVersion: raise exceptions.InvalidArgumentException( '--kms-key-version', 'The DevOps tier does not support user-specified KMS keys.') subject_config = messages.SubjectConfig( subject=messages.Subject(), subjectAltName=messages.SubjectAltNames()) if args.IsSpecified('subject'): subject_config.commonName, subject_config.subject = flags.ParseSubject(args) elif source_ca: subject_config.commonName = source_ca.config.subjectConfig.commonName subject_config.subject = source_ca.config.subjectConfig.subject if flags.SanFlagsAreSpecified(args): subject_config.subjectAltName = flags.ParseSanFlags(args) elif source_ca: subject_config.subjectAltName = source_ca.config.subjectConfig.subjectAltName flags.ValidateSubjectConfig(subject_config, is_ca=True) issuing_options = flags.ParseIssuingOptions(args) if source_ca and not args.IsSpecified('publish_ca_cert'): issuing_options.includeCaCertUrl = source_ca.issuingOptions.includeCaCertUrl if source_ca and not args.IsSpecified('publish_crl'): issuing_options.includeCrlAccessUrl = source_ca.issuingOptions.includeCrlAccessUrl issuance_policy = flags.ParseIssuancePolicy(args) if source_ca and not issuance_policy: issuance_policy = source_ca.certificatePolicy reusable_config_wrapper = flags.ParseReusableConfig( args, ca_ref.locationsId, is_ca=True) if source_ca and not flags.ReusableConfigFlagsAreSpecified(args): reusable_config_wrapper = source_ca.config.reusableConfig lifetime = flags.ParseValidityFlag(args) if source_ca and not args.IsSpecified('validity'): lifetime = source_ca.lifetime labels = labels_util.ParseCreateArgs( args, messages.CertificateAuthority.LabelsValue) new_ca = messages.CertificateAuthority( tier=tier, type=messages.CertificateAuthority.TypeValueValuesEnum.SUBORDINATE if is_subordinate else messages.CertificateAuthority.TypeValueValuesEnum.SELF_SIGNED, lifetime=lifetime, config=messages.CertificateConfig( reusableConfig=reusable_config_wrapper, subjectConfig=subject_config), keySpec=keyspec, certificatePolicy=issuance_policy, issuingOptions=issuing_options, gcsBucket=None, labels=labels) return (new_ca, ca_ref, issuer_ref)