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,