diff --git a/Makefile b/Makefile index 46f9281..51956f7 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ GOMAXPROCS = 4 -PROJECT = "github.com/salrashid123/vault-plugin-secrets-gcpca" +PROJECT = "github.com/GoogleCloudPlatform/vault-plugin-secrets-gcppca" NAME = $(shell go run version/cmd/main.go name) VERSION = $(shell go run version/cmd/main.go version) COMMIT = $(shell git rev-parse --short HEAD) diff --git a/README.md b/README.md index c5b59ae..e830ee3 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,11 @@ To issue certificates, you need to first define a profile (config) for the mount 1. Define a config profile -A profile dictates the specifications of the CA a specific Vault mount will use. In the example used here, the mount path is `gcppca` with the CA of `prod-root` +A profile dictates the specifications of the CA a specific Vault mount will use. In the example used here, the mount path is `gcppca` with the CAPool of `my-pool` ```bash vault write gcppca/config \ - issuer="prod-root" \ + pool="my-pool" \ location="us-central1" \ project="your-project-id" ``` @@ -81,15 +81,24 @@ Under no circumstance does this plugin retain the private key for any certificat - The sub-path under `/issue-with-csr/` is intended for user-provided CSR -This plugin will create a certificate within GCP CA Service with a certificate `Name` using the final path parameter in the Vault resource path. For example, `gcppca/issue-with-genkey/my_tls_cert_rsa_1` will create a GCP CA Service Resource path `projects/your-project-id/locations/us-central1/certificateAuthorities/prod-root/certificates/my_tls_cert_rsa_1`. This is the actual CA Service unique name for the certificate and cannot be reused once created. +This plugin will create a certificate within GCP CA Service with a certificate `Name` using the final path parameter in the Vault resource path. For example, `gcppca/issue-with-genkey/my_tls_cert_rsa_1` will create a GCP CA Service Resource path `projects/your-project-id/locations/us-central1/caPools/my-pool/certificates/my_tls_cert_rsa_1`. This is the actual CA Service unique name for the certificate and cannot be reused once created. Deleting the key in Vault will revoke the certificate in CA Service which also means the same name cannot be reused. +The examples below uses a default certificate authority pool with a CA. That is, you should have a set pre-generated + +``` +```bash +$ gcloud privateca pools create my-pool-1 --location=us-central1 +$ gcloud privateca roots create ca-1 --location=us-central1 --pool my-pool-1 \ + --subject "C=US,ST=California,L=Mountain View,O=Google LLC,CN=google.com" +``` + ### Vault Generated To generate a certificate keypair on vault, first apply a configuration that allows Vault to reference which CA to sign against -The configuration below will generate a certificate called `my_tls_cert_rsa_1` within CA Service using a GCP CA `prod-root` that was defined earlier by specifying `gcppca/config`. +The configuration below will generate a certificate called `my_tls_cert_rsa_1` within CA Service using a GCP CA `prod-root` that was defined separately. Apply the config and acquire a `VAULT_TOKEN` based off of those policies. @@ -102,7 +111,6 @@ path "gcppca/issue-with-genkey/my_tls_cert_rsa_1" { "validity"= ["P30D"] "dns_san" = ["client.domain.com,client2.domain.com"] "subject" = ["C=US,ST=California,L=Mountain View,O=Google LLC,CN=google.com"] - "reusable_config" = ["leaf-server-tls"] } } EOF @@ -120,8 +128,7 @@ vault write gcppca/issue-with-genkey/my_tls_cert_rsa_1 \ key_type="rsa" \ validity="P30D" \ dns_san="client.domain.com,client2.domain.com" \ - subject="C=US,ST=California,L=Mountain View,O=Google LLC,CN=google.com" \ - reusable_config="leaf-server-tls" + subject="C=US,ST=California,L=Mountain View,O=Google LLC,CN=google.com" ``` The output will be Public Certificate and PrivateKey @@ -196,6 +203,7 @@ Plugin configuration supports various options that are common and mode-specific |:------------|-------------| | **`validity`** | `string` validity of the issued certificate (default: `P30d`) | | **`labels`** | `[]string` list of GCP labels to apply to the certificate (format `k1=v1,k2=v2`) | +| **`issuing_certificate_authority`** | `string` Optional. The resource ID of the CertificateAuthority that should issue the certificate. By default, the certificate will be issued from any of the active CAs in the CA Pool. | #### Generated (/issue-with-genkey/) Options @@ -204,7 +212,7 @@ Plugin configuration supports various options that are common and mode-specific | **`key_type`** | `string` what type of key to generate (default: `rsa`; either `rsa` or `ecdsa`; cannot be specified if `csr` is set) | | **`key_usage`** | `[]string` what are the `key_usage` settings (default: `[]`) | | **`extended_key_usage`** | `[]string` what are the `extended_key_usage` settings (default: `[]`) | -| **`reusable_config`** | `string` reusable_config to use (cannot be set if `key_usage`,`extended_key_usage` is set; default `[]`) | +| **`certificate_template`** | `string` certificate_template to use (cannot be set if `key_usage`,`extended_key_usage` is set; default `[]`) | | **`subject`** | `string` subject field value (must be in canonical format `C=,ST=,L=,O=,CN=`)| | **`dns_san`** | `[]string` list of `dns_san` to use | | **`email_san`** | `[]string` list of `email_san` to use | @@ -213,6 +221,8 @@ Plugin configuration supports various options that are common and mode-specific | **`is_ca_cert`** | `bool` whether this certificate is for a CA or not. | | **`max_chain_length`** | `int` Maximum depth of subordinate CAs allowed under this CA for a CA certificate.| +Note, if you use `certificate_template`, specify the fully qualified name: + `"certificate_template" = ["projects/your_project_id/locations/your_location/certificateTemplates/your_template"]` #### CSR (/issue-with-csr/) Options | Option | Description | @@ -221,9 +231,9 @@ Plugin configuration supports various options that are common and mode-specific Sample usage -The following policies describe usage of `reusable_config` and `key_usage` options. +The following policies describe usage of `certificate_template` and `key_usage` options. -`reusable_config` options: +`certificate_template` options: ```bash vault policy write genkey-reusable-policy -</config"), logical.ErrInvalidRequest + if pool == "" || projectID == "" || location == "" { + return logical.ErrorResponse("Configuration settings not found: Pool, ProjectID and Location must be set in /config"), logical.ErrInvalidRequest } pcaClient, closer, err := b.PCAClient(req.Storage) @@ -160,15 +171,15 @@ func (b *backend) pathCSRDelete(ctx context.Context, req *logical.Request, d *fr } defer closer() - b.Logger().Debug("Attempting to see if this cert exists %v", issuer, name) + b.Logger().Debug("Attempting to see if this cert exists %v", pool, name) - parent := fmt.Sprintf("projects/%s/locations/%s/certificateAuthorities/%s/certificates/%s", projectID, location, issuer, name) + parent := fmt.Sprintf("projects/%s/locations/%s/caPools/%s/certificates/%s", projectID, location, pool, name) getReq := &privatecapb.GetCertificateRequest{ Name: parent, } gcert, err := pcaClient.GetCertificate(ctx, getReq) if err != nil { - b.Logger().Debug("CertificateName doesn't exist..this maybe an anonymous cert exiting [", issuer, "] certspec: ", name) + b.Logger().Debug("CertificateName doesn't exist..this maybe an anonymous cert exiting [", pool, "] certspec: ", name) // not sure what to return here, err or nil //return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest return &logical.Response{}, nil diff --git a/path_generatekey.go b/path_generatekey.go index 667d61d..7e1d0bc 100644 --- a/path_generatekey.go +++ b/path_generatekey.go @@ -26,13 +26,12 @@ import ( "strings" "time" - privateca "cloud.google.com/go/security/privateca/apiv1beta1" + privateca "cloud.google.com/go/security/privateca/apiv1" "github.com/golang/protobuf/ptypes" - "github.com/golang/protobuf/ptypes/wrappers" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" "google.golang.org/api/iterator" - privatecapb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1beta1" + privatecapb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1" ) const ( @@ -67,7 +66,7 @@ var ( key_agreement, cert_sign, crl_sign, encipher_only, decipher_only} valid_extended_key_usages = []string{server_auth, client_auth, code_signing, email_protection, time_stamping, ocsp_signing} - valid_reusable_config = []string{} // derived from api + valid_certificate_templates = []string{} // derived ) func (b *backend) pathGenerateKey() *framework.Path { @@ -122,9 +121,13 @@ func (b *backend) pathGenerateKey() *framework.Path { Description: `One of: server_auth, client_auth, code_signing, email_protection, time_stamping, ocsp_signing`, }, - "reusable_config": &framework.FieldSchema{ + "certificate_template": &framework.FieldSchema{ Type: framework.TypeString, - Description: `Reusable Config Name`, + Description: `Certificate Template to use`, + }, + "issuing_certificate_authority": &framework.FieldSchema{ + Type: framework.TypeString, + Description: `Optional. The resource ID of the CertificateAuthority that should issue the certificate. `, }, "max_chain_length": &framework.FieldSchema{ Type: framework.TypeInt, @@ -160,10 +163,11 @@ func (b *backend) pathGenerateKeyWrite(ctx context.Context, req *logical.Request var uriSAN []string var key_usages []string var extended_key_usages []string - var reusable_config string + var certificate_template string var validity time.Duration var labels map[string]string var is_ca_cert bool + var issuingCertificateAuthority string name = d.Get("name").(string) @@ -175,12 +179,12 @@ func (b *backend) pathGenerateKeyWrite(ctx context.Context, req *logical.Request return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest } - issuer := cfg.Issuer + pool := cfg.Pool projectID := cfg.Project location := cfg.Location - if issuer == "" || projectID == "" || location == "" { - return logical.ErrorResponse("Configuration settings not found: Issuer, ProjectID and Location must be set in /config"), logical.ErrInvalidRequest + if pool == "" || projectID == "" || location == "" { + return logical.ErrorResponse("Configuration settings not found: CAPool, ProjectID and Location must be set in /config"), logical.ErrInvalidRequest } pcaClient, closer, err := b.PCAClient(req.Storage) @@ -242,16 +246,23 @@ func (b *backend) pathGenerateKeyWrite(ctx context.Context, req *logical.Request } } - valid_reusable_config, err := b.getReusableConfigs(ctx, pcaClient, location) + // certificate_templates can reside in any other project. For the sake of configuration simplicity, + // we can comment out the following and skip the check. If the referenced template does not exist, the + // error isn't particularly helpful: "rpc error: code = NotFound desc = Requested entity was not found." + valid_certificate_templates, err := b.getCertificateTemplates(ctx, pcaClient, projectID, location) if err != nil { - return logical.ErrorResponse("Could not recall reusable configs from CA Service "), logical.ErrInvalidRequest + return logical.ErrorResponse(fmt.Sprintf("Could not recall certificate Templates from project %s", projectID)), logical.ErrInvalidRequest } - if v, ok := d.GetOk("reusable_config"); ok { - if !contains(valid_reusable_config, v.(string)) { - return logical.ErrorResponse("Invalid reusable configs, must one of ", valid_reusable_config), logical.ErrInvalidRequest + if v, ok := d.GetOk("certificate_template"); ok { + if !contains(valid_certificate_templates, v.(string)) { + return logical.ErrorResponse("Invalid reusable configs, must one of %v", valid_certificate_templates), logical.ErrInvalidRequest } - reusable_config = v.(string) + certificate_template = v.(string) + } + + if v, ok := d.GetOk("issuing_certificate_authority"); ok { + issuingCertificateAuthority = v.(string) } if v, ok := d.GetOk("key_usages"); ok { @@ -265,15 +276,15 @@ func (b *backend) pathGenerateKeyWrite(ctx context.Context, req *logical.Request if v, ok := d.GetOk("extended_key_usages"); ok { for _, usage := range v.([]string) { - if !contains(valid_key_usages, usage) { + if !contains(valid_extended_key_usages, usage) { return logical.ErrorResponse("Invalid extended_key_usages, must one of ", valid_extended_key_usages), logical.ErrInvalidRequest } } extended_key_usages = v.([]string) } - if len(reusable_config) > 0 && (len(key_usages) > 0 || len(extended_key_usages) > 0) { - b.Logger().Error("Either reusable config or (key_usages|extended_key_usage) must be specified") + if len(certificate_template) > 0 && (len(key_usages) > 0 || len(extended_key_usages) > 0) { + b.Logger().Error("Either certificate_template or (key_usages|extended_key_usage) must be specified") return logical.ErrorResponse("Either reusable config or (key_usages|extended_key_usage) must be specified"), logical.ErrInvalidRequest } @@ -289,7 +300,7 @@ func (b *backend) pathGenerateKeyWrite(ctx context.Context, req *logical.Request } } - var pubkey *privatecapb.PublicKey + var pubPem []byte var publicKeyDer []byte var privPEM []byte @@ -311,10 +322,12 @@ func (b *backend) pathGenerateKeyWrite(ctx context.Context, req *logical.Request return logical.ErrorResponse(fmt.Sprintf("Unable to get marshall RSA publicKey %v", err)), logical.ErrInvalidRequest } - pubkey = &privatecapb.PublicKey{ - Type: privatecapb.PublicKey_PEM_RSA_KEY, - Key: publicKeyDer, - } + pubPem = pem.EncodeToMemory( + &pem.Block{ + Type: "PUBLIC KEY", + Bytes: publicKeyDer, + }, + ) } else { pubkeyCurve := elliptic.P256() @@ -339,105 +352,145 @@ func (b *backend) pathGenerateKeyWrite(ctx context.Context, req *logical.Request b.Logger().Error("Unable to get publicKey %v", err) return logical.ErrorResponse(fmt.Sprintf("Unable to get publicKey %v", err)), logical.ErrInvalidRequest } - pubkey = &privatecapb.PublicKey{ - Type: privatecapb.PublicKey_PEM_EC_KEY, - Key: publicKeyDer, - } + pubPem = pem.EncodeToMemory( + &pem.Block{ + Type: "PUBLIC KEY", + Bytes: publicKeyDer, + }, + ) } - pubPem := pem.EncodeToMemory( - &pem.Block{ - Type: "PUBLIC KEY", - Bytes: publicKeyDer, - }, - ) - pubkey.Key = pubPem + parent := fmt.Sprintf("projects/%s/locations/%s/caPools/%s", projectID, location, pool) + + var creq privatecapb.CreateCertificateRequest + + var rcfgw privatecapb.X509Parameters - var rcfgw privatecapb.ReusableConfigWrapper + if len(certificate_template) > 0 { - if len(reusable_config) > 0 { - reusableConfigProject := "privateca-data" - reusableConfigName := fmt.Sprintf("projects/%s/locations/%s/reusableConfigs/%s", reusableConfigProject, location, reusable_config) - rcfgw.ConfigValues = &privatecapb.ReusableConfigWrapper_ReusableConfig{ - ReusableConfig: reusableConfigName, + creq = privatecapb.CreateCertificateRequest{ + Parent: parent, + CertificateId: name, + IssuingCertificateAuthorityId: issuingCertificateAuthority, + Certificate: &privatecapb.Certificate{ + Lifetime: ptypes.DurationProto(validity), + Labels: labels, + CertificateTemplate: certificate_template, + CertificateConfig: &privatecapb.Certificate_Config{ + Config: &privatecapb.CertificateConfig{ + PublicKey: &privatecapb.PublicKey{ + Format: privatecapb.PublicKey_PEM, + Key: pubPem, + }, + X509Config: &privatecapb.X509Parameters{}, + SubjectConfig: &privatecapb.CertificateConfig_SubjectConfig{ + Subject: &privatecapb.Subject{ + Organization: subjectValues["organization"], + OrganizationalUnit: subjectValues["organizationunit"], + Locality: subjectValues["locality"], + Province: subjectValues["province"], + CountryCode: subjectValues["country"], + CommonName: subjectValues["cn"], + }, + SubjectAltName: &privatecapb.SubjectAltNames{ + DnsNames: dnsSAN, + Uris: uriSAN, + EmailAddresses: emailSAN, + IpAddresses: ipSAN, + }, + }, + }, + }, + }, } + } else { - caOptions := &privatecapb.ReusableConfigValues_CaOptions{} + caOptions := &privatecapb.X509Parameters_CaOptions{} if is_ca_cert { - caOptions.IsCa = &wrappers.BoolValue{ - Value: is_ca_cert, - } + caOptions.IsCa = &is_ca_cert // TODO: the path length attribute isn't shown in the cert thats issued... if v, ok := d.GetOk("max_chain_length"); ok { - caOptions.MaxIssuerPathLength = &wrappers.Int32Value{ - Value: int32(v.(int)), - } + caOptions.MaxIssuerPathLength = toInt32(v.(int)) } } // meh, ther's much more elegant way than iterating like this // dont be lazy, sal - rcfgw.ConfigValues = &privatecapb.ReusableConfigWrapper_ReusableConfigValues{ - ReusableConfigValues: &privatecapb.ReusableConfigValues{ - CaOptions: caOptions, - KeyUsage: &privatecapb.KeyUsage{ - BaseKeyUsage: &privatecapb.KeyUsage_KeyUsageOptions{ - DigitalSignature: contains(key_usages, digital_signature), - ContentCommitment: contains(key_usages, content_commitment), - KeyEncipherment: contains(key_usages, key_encipherment), - DataEncipherment: contains(key_usages, data_encipherment), - KeyAgreement: contains(key_usages, key_agreement), - CertSign: contains(key_usages, cert_sign), - CrlSign: contains(key_usages, cert_sign), - EncipherOnly: contains(key_usages, encipher_only), - DecipherOnly: contains(key_usages, decipher_only), - }, - ExtendedKeyUsage: &privatecapb.KeyUsage_ExtendedKeyUsageOptions{ - ServerAuth: contains(extended_key_usages, server_auth), - ClientAuth: contains(extended_key_usages, client_auth), - CodeSigning: contains(extended_key_usages, code_signing), - EmailProtection: contains(extended_key_usages, email_protection), - TimeStamping: contains(extended_key_usages, time_stamping), - OcspSigning: contains(extended_key_usages, ocsp_signing), - }, + rcfgw = privatecapb.X509Parameters{ + + KeyUsage: &privatecapb.KeyUsage{ + BaseKeyUsage: &privatecapb.KeyUsage_KeyUsageOptions{ + DigitalSignature: contains(key_usages, digital_signature), + ContentCommitment: contains(key_usages, content_commitment), + KeyEncipherment: contains(key_usages, key_encipherment), + DataEncipherment: contains(key_usages, data_encipherment), + KeyAgreement: contains(key_usages, key_agreement), + CertSign: contains(key_usages, cert_sign), + CrlSign: contains(key_usages, cert_sign), + EncipherOnly: contains(key_usages, encipher_only), + DecipherOnly: contains(key_usages, decipher_only), + }, + ExtendedKeyUsage: &privatecapb.KeyUsage_ExtendedKeyUsageOptions{ + ServerAuth: contains(extended_key_usages, server_auth), + ClientAuth: contains(extended_key_usages, client_auth), + CodeSigning: contains(extended_key_usages, code_signing), + EmailProtection: contains(extended_key_usages, email_protection), + TimeStamping: contains(extended_key_usages, time_stamping), + OcspSigning: contains(extended_key_usages, ocsp_signing), }, }, + CaOptions: &privatecapb.X509Parameters_CaOptions{ + IsCa: &is_ca_cert, + }, } - } - - parent := fmt.Sprintf("projects/%s/locations/%s/certificateAuthorities/%s", projectID, location, issuer) - creq := &privatecapb.CreateCertificateRequest{ - Parent: parent, - CertificateId: name, - Certificate: &privatecapb.Certificate{ - Lifetime: ptypes.DurationProto(validity), - Labels: labels, - CertificateConfig: &privatecapb.Certificate_Config{ - Config: &privatecapb.CertificateConfig{ - PublicKey: pubkey, - SubjectConfig: &privatecapb.CertificateConfig_SubjectConfig{ - Subject: &privatecapb.Subject{ - Organization: subjectValues["organization"], - OrganizationalUnit: subjectValues["organizationunit"], - Locality: subjectValues["locality"], - Province: subjectValues["province"], - CountryCode: subjectValues["country"], + creq = privatecapb.CreateCertificateRequest{ + Parent: parent, + CertificateId: name, + IssuingCertificateAuthorityId: issuingCertificateAuthority, + Certificate: &privatecapb.Certificate{ + Lifetime: ptypes.DurationProto(validity), + Labels: labels, + CertificateConfig: &privatecapb.Certificate_Config{ + Config: &privatecapb.CertificateConfig{ + PublicKey: &privatecapb.PublicKey{ + Format: privatecapb.PublicKey_PEM, + Key: pubPem, }, - CommonName: subjectValues["cn"], - SubjectAltName: &privatecapb.SubjectAltNames{ - DnsNames: dnsSAN, - Uris: uriSAN, - EmailAddresses: emailSAN, - IpAddresses: ipSAN, + SubjectConfig: &privatecapb.CertificateConfig_SubjectConfig{ + Subject: &privatecapb.Subject{ + Organization: subjectValues["organization"], + OrganizationalUnit: subjectValues["organizationunit"], + Locality: subjectValues["locality"], + Province: subjectValues["province"], + CountryCode: subjectValues["country"], + CommonName: subjectValues["cn"], + }, + SubjectAltName: &privatecapb.SubjectAltNames{ + DnsNames: dnsSAN, + Uris: uriSAN, + EmailAddresses: emailSAN, + IpAddresses: ipSAN, + // CustomSans is just a sample placeholder below because i do not + // know how best to map a vault config into a complex proto + // TODO: figure out how to specify customSans in vault config. + // maybe serialized b64 []*X509Extension serialized? + // CustomSans: []*privatecapb.X509Extension{{ + // ObjectId: &privatecapb.ObjectId{ + // ObjectIdPath: []int32{}, + // }, + // Critical: false, + // Value: []byte(""), + // }}, + }, }, + X509Config: &rcfgw, }, - ReusableConfig: &rcfgw, }, }, - }, + } } - cresp, err := pcaClient.CreateCertificate(ctx, creq) + cresp, err := pcaClient.CreateCertificate(ctx, &creq) if err != nil { return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest } @@ -458,7 +511,7 @@ func (b *backend) pathGenerateKeyDelete(ctx context.Context, req *logical.Reques return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest } - issuer := ccfg.Issuer + caPool := ccfg.Pool projectID := ccfg.Project location := ccfg.Location @@ -468,15 +521,15 @@ func (b *backend) pathGenerateKeyDelete(ctx context.Context, req *logical.Reques } defer closer() - b.Logger().Debug("Attempting to see if cert exists issuer:", issuer, "name:", name) + b.Logger().Debug("Attempting to see if cert exists issuer:", caPool, "name:", name) - parent := fmt.Sprintf("projects/%s/locations/%s/certificateAuthorities/%s/certificates/%s", projectID, location, issuer, name) + parent := fmt.Sprintf("projects/%s/locations/%s/caPools/%s/certificates/%s", projectID, location, caPool, name) getReq := &privatecapb.GetCertificateRequest{ Name: parent, } gcert, err := pcaClient.GetCertificate(ctx, getReq) if err != nil { - b.Logger().Debug("CertificateName doesn't exist..this maybe an anonymous cert, exiting certspec:", issuer, "name[", name, "]") + b.Logger().Debug("CertificateName doesn't exist..this maybe an anonymous cert, exiting certspec:", caPool, "name[", name, "]") // not sure what to return here, err or nil //return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest return &logical.Response{}, nil @@ -504,15 +557,15 @@ func (b *backend) pathGenerateKeyDelete(ctx context.Context, req *logical.Reques return &logical.Response{}, nil } -func (b *backend) getReusableConfigs(ctx context.Context, pcaClient *privateca.CertificateAuthorityClient, location string) (values []string, err error) { +func (b *backend) getCertificateTemplates(ctx context.Context, pcaClient *privateca.CertificateAuthorityClient, projectID string, location string) (values []string, err error) { - var valid_reusable_config []string - parent := fmt.Sprintf("projects/%s/locations/%s/reusableConfigs", "privateca-data", location) + var valid_certificate_templates []string + parent := fmt.Sprintf("projects/%s/locations/%s/certificateTemplates", projectID, location) - rcreq := &privatecapb.ListReusableConfigsRequest{ + rcreq := &privatecapb.ListCertificateTemplatesRequest{ Parent: parent, } - it := pcaClient.ListReusableConfigs(ctx, rcreq) + it := pcaClient.ListCertificateTemplates(ctx, rcreq) for { cfg, err := it.Next() if err == iterator.Done { @@ -521,10 +574,7 @@ func (b *backend) getReusableConfigs(ctx context.Context, pcaClient *privateca.C if err != nil { return []string{}, err } - n := cfg.Name - ss := strings.Split(n, "/") - s := ss[len(ss)-1] - valid_reusable_config = append(valid_reusable_config, s) + valid_certificate_templates = append(valid_certificate_templates, cfg.Name) } - return valid_reusable_config, nil + return valid_certificate_templates, nil } diff --git a/version/version.go b/version/version.go index 23e2e73..5f9c8b3 100644 --- a/version/version.go +++ b/version/version.go @@ -21,7 +21,7 @@ const ( Name = "vault-plugin-secrets-gcppca" // Version is the version of the release. - Version = "0.0.1" + Version = "1.0.3" ) var (