diff --git a/docs/generated/reference/openapi/openapi_generated.go b/docs/generated/reference/openapi/openapi_generated.go index 5b386d3bf..0a5997510 100644 --- a/docs/generated/reference/openapi/openapi_generated.go +++ b/docs/generated/reference/openapi/openapi_generated.go @@ -1356,9 +1356,9 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA }, "caBundle": { SchemaProps: spec.SchemaProps{ - Description: "CA bundle to validate Vault server certificate", + Description: "Base64 encoded CA bundle to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection.", Type: []string{"string"}, - Format: "", + Format: "byte", }, }, }, diff --git a/docs/generated/reference/output/reference/api-docs/index.html b/docs/generated/reference/output/reference/api-docs/index.html index 994cefccf..7d9136b68 100644 --- a/docs/generated/reference/output/reference/api-docs/index.html +++ b/docs/generated/reference/output/reference/api-docs/index.html @@ -2080,7 +2080,7 @@ Appears In: caBundle
string -CA bundle to validate Vault server certificate +Base64 encoded CA bundle to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. path
string diff --git a/docs/tutorials/vault/creating-vault-issuers.rst b/docs/tutorials/vault/creating-vault-issuers.rst index 5721c8364..a88d874c3 100644 --- a/docs/tutorials/vault/creating-vault-issuers.rst +++ b/docs/tutorials/vault/creating-vault-issuers.rst @@ -54,7 +54,7 @@ We can now create a cluster issuer referencing this secret: vault: path: pki_int/sign/example-dot-com server: https://vault - caBundle: ... + caBundle: auth: appRole: path: approle @@ -71,8 +71,12 @@ references the Kubernetes secret created previously. More specifically, the fiel *name* is the Kubernetes secret name and *key* is the name given as the key value that store the *secretId*. The optional attribute *path* specifies where the AppRole authentication is mounted in Vault. The attribute *path* default -value is *approle*. An optional *caBundle* in PEM format can be provided to validate -the TLS connection to the Vault Server. +value is *approle*. + +An optional base64 encoded *caBundle* in PEM format can be provided to validate +the TLS connection to the Vault Server. When *caBundle* is set it replaces the CA +bundle inside the container running cert-manager. This parameter as no effect if the +connection used is in plain HTTP. Once we have created the above Issuer we can use it to obtain a certificate. @@ -155,13 +159,17 @@ We can now create an issuer referencing this secret: key: token path: pki_int/sign/example-dot-com server: https://vault - caBundle: ... + caBundle: Where *path* is the Vault role path of the PKI backend and *server* is the Vault server base URL. The secret created previously is referenced in the issuer with its *name* and *key* corresponding to the name of the Kubernetes secret and the -property name containing the token value respectively. An optional *caBundle* in PEM -format can be provided to validate the TLS connection to the Vault Server. +property name containing the token value respectively. + +An optional base64 encoded *caBundle* in PEM format can be provided to validate +the TLS connection to the Vault Server. When *caBundle* is set it replaces the CA +bundle inside the container running cert-manager. This parameter as no effect if the +connection used is in plain HTTP. Once we have created the above Issuer we can use it to obtain a certificate. diff --git a/pkg/apis/certmanager/v1alpha1/types_issuer.go b/pkg/apis/certmanager/v1alpha1/types_issuer.go index a886be96f..87d4abdd5 100644 --- a/pkg/apis/certmanager/v1alpha1/types_issuer.go +++ b/pkg/apis/certmanager/v1alpha1/types_issuer.go @@ -91,8 +91,11 @@ type VaultIssuer struct { Server string `json:"server"` // Vault URL path to the certificate role Path string `json:"path"` - // CA bundle to validate Vault server certificate - CABundle string `json:"caBundle"` + // Base64 encoded CA bundle to validate Vault server certificate. Only used + // if the Server URL is using HTTPS protocol. This parameter is ignored for + // plain HTTP protocol connection. If not set the system root certificates + // are used to validate the TLS connection. + CABundle []byte `json:"caBundle"` } // Vault authentication can be configured: diff --git a/pkg/apis/certmanager/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/certmanager/v1alpha1/zz_generated.deepcopy.go index 46a6e7b31..58ab9f606 100644 --- a/pkg/apis/certmanager/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/certmanager/v1alpha1/zz_generated.deepcopy.go @@ -755,7 +755,7 @@ func (in *IssuerConfig) DeepCopyInto(out *IssuerConfig) { *out = nil } else { *out = new(VaultIssuer) - **out = **in + (*in).DeepCopyInto(*out) } } if in.SelfSigned != nil { @@ -999,6 +999,11 @@ func (in *VaultAuth) DeepCopy() *VaultAuth { func (in *VaultIssuer) DeepCopyInto(out *VaultIssuer) { *out = *in out.Auth = in.Auth + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/issuer/vault/issue.go b/pkg/issuer/vault/issue.go index a3e90243a..b4b4297fe 100644 --- a/pkg/issuer/vault/issue.go +++ b/pkg/issuer/vault/issue.go @@ -108,12 +108,12 @@ func (v *Vault) obtainCertificate(ctx context.Context, crt *v1alpha1.Certificate func (v *Vault) configureCertPool(cfg *vault.Config) error { certs := v.issuer.GetSpec().Vault.CABundle - if certs == "" { + if len(certs) == 0 { return nil } caCertPool := x509.NewCertPool() - ok := caCertPool.AppendCertsFromPEM([]byte(certs)) + ok := caCertPool.AppendCertsFromPEM(certs) if ok == false { return fmt.Errorf("error loading Vault CA bundle") } diff --git a/pkg/issuer/vault/setup.go b/pkg/issuer/vault/setup.go index 3248f82b9..5204eebdf 100644 --- a/pkg/issuer/vault/setup.go +++ b/pkg/issuer/vault/setup.go @@ -18,6 +18,7 @@ package vault import ( "context" + "crypto/x509" "fmt" "github.com/golang/glog" @@ -37,6 +38,7 @@ const ( messageServerAndPathRequired = "Vault server and path are required fields" messsageAuthFieldsRequired = "Vault tokenSecretRef or appRole is required" messageAuthFieldRequired = "Vault tokenSecretRef and appRole cannot be set on the same issuer" + messageVaultCABundleInvalid = "Specified CA bundle is invalid" ) func (v *Vault) Setup(ctx context.Context) error { @@ -81,6 +83,18 @@ func (v *Vault) Setup(ctx context.Context) error { return fmt.Errorf(messageAuthFieldRequired) } + // check if caBundle is valid + certs := v.issuer.GetSpec().Vault.CABundle + if len(certs) > 0 { + caCertPool := x509.NewCertPool() + ok := caCertPool.AppendCertsFromPEM(certs) + if !ok { + glog.V(4).Infof("%s: %s", v.issuer.GetObjectMeta().Name, messageVaultCABundleInvalid) + v.issuer.UpdateStatusCondition(v1alpha1.IssuerConditionReady, v1alpha1.ConditionFalse, errorVault, messageVaultCABundleInvalid) + return fmt.Errorf(messageVaultCABundleInvalid) + } + } + client, err := v.initVaultClient() if err != nil { s := messageVaultClientInitFailed + err.Error() diff --git a/test/util/util.go b/test/util/util.go index 0a7773da1..475ac6b7a 100644 --- a/test/util/util.go +++ b/test/util/util.go @@ -483,7 +483,7 @@ func NewCertManagerVaultIssuerToken(name, vaultURL, vaultPath, vaultSecretToken, Vault: &v1alpha1.VaultIssuer{ Server: vaultURL, Path: vaultPath, - CABundle: string(caBundle), + CABundle: caBundle, Auth: v1alpha1.VaultAuth{ TokenSecretRef: v1alpha1.SecretKeySelector{ Key: "secretkey", @@ -508,7 +508,7 @@ func NewCertManagerVaultIssuerAppRole(name, vaultURL, vaultPath, roleId, vaultSe Vault: &v1alpha1.VaultIssuer{ Server: vaultURL, Path: vaultPath, - CABundle: string(caBundle), + CABundle: caBundle, Auth: v1alpha1.VaultAuth{ AppRole: v1alpha1.VaultAppRole{ Path: authPath,