diff --git a/contrib/charts/vault/templates/vault-config.yaml b/contrib/charts/vault/templates/vault-config.yaml new file mode 100644 index 000000000..bda91bdc3 --- /dev/null +++ b/contrib/charts/vault/templates/vault-config.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: vault-config + labels: + app: vault +data: + config.json: | + {{ .Values.vault.config | toJson }} diff --git a/contrib/charts/vault/templates/vault-deployment.yaml b/contrib/charts/vault/templates/vault-deployment.yaml index a5ca34210..31533ba5b 100644 --- a/contrib/charts/vault/templates/vault-deployment.yaml +++ b/contrib/charts/vault/templates/vault-deployment.yaml @@ -17,6 +17,8 @@ spec: containers: - name: vault image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + command: ["vault", "server", "-dev", "-dev-listen-address=[::]:8202", "-config", "/vault/config/config.json"] + # command: ["/bin/sh", "-c", "sleep 9999"] ports: - containerPort: 8200 name: vaultport @@ -32,3 +34,16 @@ spec: httpGet: path: /v1/sys/health port: 8200 + scheme: HTTPS + volumeMounts: + - name: vault-config + mountPath: /vault/config + - name: vault-tls + mountPath: /vault/tls + volumes: + - name: vault-config + configMap: + name: vault-config + - name: vault-tls + secret: + secretName: vault-tls diff --git a/contrib/charts/vault/templates/vault-secret.yaml b/contrib/charts/vault/templates/vault-secret.yaml new file mode 100644 index 000000000..cb532b3a2 --- /dev/null +++ b/contrib/charts/vault/templates/vault-secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: vault-tls +type: Opaque +data: + server.crt: {{ .Values.vault.publicKey | b64enc }} + server.key: {{ .Values.vault.privateKey | b64enc }} diff --git a/contrib/charts/vault/values.yaml b/contrib/charts/vault/values.yaml index a5e966c06..4e7dcad17 100644 --- a/contrib/charts/vault/values.yaml +++ b/contrib/charts/vault/values.yaml @@ -1,4 +1,18 @@ image: repository: vault tag: "0.9.3" - pullPolicy: IfNotPresent + +vault: + publicKey: + privateKey: + + config: + listener: + tcp: + address: '[::]:8200' + cluster_address: '[::]:8201' + tls_disable: false + tls_prefer_server_cipher_suites: true + tls_cipher_suites: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA + tls_cert_file: /vault/tls/server.crt + tls_key_file: /vault/tls/server.key diff --git a/docs/generated/reference/openapi/openapi_generated.go b/docs/generated/reference/openapi/openapi_generated.go index 8e3cedd7e..b91c65b65 100644 --- a/docs/generated/reference/openapi/openapi_generated.go +++ b/docs/generated/reference/openapi/openapi_generated.go @@ -1641,6 +1641,13 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA Format: "", }, }, + "caBundle": { + SchemaProps: spec.SchemaProps{ + 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: "byte", + }, + }, }, Required: []string{"auth", "server", "path"}, }, diff --git a/docs/generated/reference/output/reference/api-docs/index.html b/docs/generated/reference/output/reference/api-docs/index.html index a3d275d9d..9e14791b1 100644 --- a/docs/generated/reference/output/reference/api-docs/index.html +++ b/docs/generated/reference/output/reference/api-docs/index.html @@ -1930,6 +1930,10 @@ Appears In: Vault authentication +caBundle
string +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 Vault URL path to the certificate role diff --git a/docs/tutorials/vault/creating-vault-issuers.rst b/docs/tutorials/vault/creating-vault-issuers.rst index 01e0b3db6..a88d874c3 100644 --- a/docs/tutorials/vault/creating-vault-issuers.rst +++ b/docs/tutorials/vault/creating-vault-issuers.rst @@ -54,6 +54,7 @@ We can now create a cluster issuer referencing this secret: vault: path: pki_int/sign/example-dot-com server: https://vault + caBundle: auth: appRole: path: approle @@ -72,6 +73,11 @@ 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 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. .. code-block:: yaml @@ -153,12 +159,18 @@ We can now create an issuer referencing this secret: key: token path: pki_int/sign/example-dot-com server: https://vault + 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 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. .. code-block:: yaml diff --git a/pkg/apis/certmanager/v1alpha1/types_issuer.go b/pkg/apis/certmanager/v1alpha1/types_issuer.go index 7c3b650cc..bccf1ba2d 100644 --- a/pkg/apis/certmanager/v1alpha1/types_issuer.go +++ b/pkg/apis/certmanager/v1alpha1/types_issuer.go @@ -91,6 +91,11 @@ type VaultIssuer struct { Server string `json:"server"` // Vault URL path to the certificate role Path string `json:"path"` + // 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,omitempty"` } // 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 04d9ff490..7af02e0c9 100644 --- a/pkg/apis/certmanager/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/certmanager/v1alpha1/zz_generated.deepcopy.go @@ -796,7 +796,7 @@ func (in *IssuerConfig) DeepCopyInto(out *IssuerConfig) { *out = nil } else { *out = new(VaultIssuer) - **out = **in + (*in).DeepCopyInto(*out) } } if in.SelfSigned != nil { @@ -1169,6 +1169,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/apis/certmanager/validation/issuer.go b/pkg/apis/certmanager/validation/issuer.go index 001ff362a..36accad53 100644 --- a/pkg/apis/certmanager/validation/issuer.go +++ b/pkg/apis/certmanager/validation/issuer.go @@ -17,6 +17,7 @@ limitations under the License. package validation import ( + "crypto/x509" "fmt" "strings" @@ -122,6 +123,17 @@ func ValidateVaultIssuerConfig(iss *v1alpha1.VaultIssuer, fldPath *field.Path) f if len(iss.Path) == 0 { el = append(el, field.Required(fldPath.Child("path"), "")) } + + // check if caBundle is valid + certs := iss.CABundle + if len(certs) > 0 { + caCertPool := x509.NewCertPool() + ok := caCertPool.AppendCertsFromPEM(certs) + if !ok { + el = append(el, field.Invalid(fldPath.Child("caBundle"), "", "Specified CA bundle is invalid")) + } + } + return el // TODO: add validation for Vault authentication types } diff --git a/pkg/apis/certmanager/validation/issuer_test.go b/pkg/apis/certmanager/validation/issuer_test.go index 13c4a38f1..c4d00249b 100644 --- a/pkg/apis/certmanager/validation/issuer_test.go +++ b/pkg/apis/certmanager/validation/issuer_test.go @@ -72,6 +72,16 @@ func TestValidateVaultIssuerConfig(t *testing.T) { field.Required(fldPath.Child("path"), ""), }, }, + "vault issuer with invalid fields": { + spec: &v1alpha1.VaultIssuer{ + Server: "something", + Path: "a/b/c", + CABundle: []byte("invalid"), + }, + errs: []*field.Error{ + field.Invalid(fldPath.Child("caBundle"), "", "Specified CA bundle is invalid"), + }, + }, } for n, s := range scenarios { t.Run(n, func(t *testing.T) { @@ -619,7 +629,7 @@ func TestValidateACMEIssuerDNS01Config(t *testing.T) { } func TestValidateSecretKeySelector(t *testing.T) { - validName := v1alpha1.LocalObjectReference{"name"} + validName := v1alpha1.LocalObjectReference{Name: "name"} validKey := "key" // invalidName := v1alpha1.LocalObjectReference{"-name-"} // invalidKey := "-key-" diff --git a/pkg/issuer/vault/issue.go b/pkg/issuer/vault/issue.go index 230c3c52c..9b5ccf41a 100644 --- a/pkg/issuer/vault/issue.go +++ b/pkg/issuer/vault/issue.go @@ -19,8 +19,10 @@ package vault import ( "bytes" "context" + "crypto/x509" "encoding/pem" "fmt" + "net/http" "path" "strings" "time" @@ -109,14 +111,36 @@ func (v *Vault) obtainCertificate(ctx context.Context, crt *v1alpha1.Certificate return keyBytes, crtBytes, caBytes, nil } +func (v *Vault) configureCertPool(cfg *vault.Config) error { + certs := v.issuer.GetSpec().Vault.CABundle + if len(certs) == 0 { + return nil + } + + caCertPool := x509.NewCertPool() + ok := caCertPool.AppendCertsFromPEM(certs) + if ok == false { + return fmt.Errorf("error loading Vault CA bundle") + } + + cfg.HttpClient.Transport.(*http.Transport).TLSClientConfig.RootCAs = caCertPool + + return nil +} + func (v *Vault) initVaultClient() (*vault.Client, error) { - client, err := vault.NewClient(nil) + vaultCfg := vault.DefaultConfig() + vaultCfg.Address = v.issuer.GetSpec().Vault.Server + err := v.configureCertPool(vaultCfg) + if err != nil { + return nil, err + } + + client, err := vault.NewClient(vaultCfg) if err != nil { return nil, fmt.Errorf("error initializing Vault client: %s", err.Error()) } - client.SetAddress(v.issuer.GetSpec().Vault.Server) - tokenRef := v.issuer.GetSpec().Vault.Auth.TokenSecretRef if tokenRef.Name != "" { token, err := v.vaultTokenRef(tokenRef.Name, tokenRef.Key) diff --git a/test/e2e/BUILD.bazel b/test/e2e/BUILD.bazel index 72a4f8b13..7c34f01d0 100644 --- a/test/e2e/BUILD.bazel +++ b/test/e2e/BUILD.bazel @@ -23,6 +23,7 @@ go_library( "//test/e2e/clusterissuer:go_default_library", "//test/e2e/framework:go_default_library", "//test/e2e/issuer:go_default_library", + "//test/util/vault:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/ginkgo/config:go_default_library", diff --git a/test/e2e/certificate/certificate_vault.go b/test/e2e/certificate/certificate_vault.go index 079ee54a4..524a986ec 100644 --- a/test/e2e/certificate/certificate_vault.go +++ b/test/e2e/certificate/certificate_vault.go @@ -69,14 +69,14 @@ var _ = framework.CertManagerDescribe("Vault Certificate (AppRole)", func() { vaultInit.Clean() }) - vaultURL := "http://vault.vault:8200" + vaultURL := "https://vault.vault:8200" It("should generate a new valid certificate", func() { By("Creating an Issuer") certClient := f.CertManagerClientSet.CertmanagerV1alpha1().Certificates(f.Namespace.Name) secretClient := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name) - _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath)) + _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath, vault.VaultCA)) Expect(err).NotTo(HaveOccurred()) By("Waiting for Issuer to become Ready") @@ -137,14 +137,14 @@ var _ = framework.CertManagerDescribe("Vault Certificate (AppRole with a custom vaultInit.Clean() }) - vaultURL := "http://vault.vault:8200" + vaultURL := "https://vault.vault:8200" It("should generate a new valid certificate", func() { By("Creating an Issuer") certClient := f.CertManagerClientSet.CertmanagerV1alpha1().Certificates(f.Namespace.Name) secretClient := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name) - _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath)) + _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath, vault.VaultCA)) Expect(err).NotTo(HaveOccurred()) By("Waiting for Issuer to become Ready") diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index 4d4206c43..7f3377817 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -35,6 +35,7 @@ import ( _ "github.com/jetstack/cert-manager/test/e2e/clusterissuer" "github.com/jetstack/cert-manager/test/e2e/framework" _ "github.com/jetstack/cert-manager/test/e2e/issuer" + "github.com/jetstack/cert-manager/test/util/vault" ) const certManagerDeploymentNamespace = "cert-manager" @@ -69,7 +70,8 @@ func RunE2ETests(t *testing.T) { } InstallHelmChart(t, "pebble", "./contrib/charts/pebble", "pebble", "./test/fixtures/pebble-values.yaml", extraArgs...) - InstallHelmChart(t, "vault", "./contrib/charts/vault", "vault", "./test/fixtures/vault-values.yaml") + vaultExtraArgs := []string{"--set", "vault.privateKey=" + string(vault.VaultCertPrivateKey), "--set", "vault.publicKey=" + string(vault.VaultCert)} + InstallHelmChart(t, "vault", "./contrib/charts/vault", "vault", "./test/fixtures/vault-values.yaml", vaultExtraArgs...) glog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunId, config.GinkgoConfig.ParallelNode) diff --git a/test/e2e/issuer/issuer_vault.go b/test/e2e/issuer/issuer_vault.go index 4f6d6665e..1aa5558a2 100644 --- a/test/e2e/issuer/issuer_vault.go +++ b/test/e2e/issuer/issuer_vault.go @@ -67,13 +67,13 @@ var _ = framework.CertManagerDescribe("Vault Issuer", func() { const vaultDefaultDuration = time.Hour * 24 * 90 - vaultURL := "http://vault.vault:8200" + vaultURL := "https://vault.vault:8200" It("should be ready with a valid AppRole", func() { _, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Create(vault.NewVaultAppRoleSecret(vaultSecretAppRoleName, secretId)) Expect(err).NotTo(HaveOccurred()) By("Creating an Issuer") - _, err = f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath)) + _, err = f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath, vault.VaultCA)) Expect(err).NotTo(HaveOccurred()) By("Waiting for Issuer to become Ready") @@ -88,7 +88,7 @@ var _ = framework.CertManagerDescribe("Vault Issuer", func() { It("should fail to init with missing Vault AppRole", func() { By("Creating an Issuer") - _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath)) + _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerAppRole(issuerName, vaultURL, vaultPath, roleId, vaultSecretAppRoleName, authPath, vault.VaultCA)) Expect(err).NotTo(HaveOccurred()) By("Waiting for Issuer to become Ready") @@ -103,7 +103,7 @@ var _ = framework.CertManagerDescribe("Vault Issuer", func() { It("should fail to init with missing Vault Token", func() { By("Creating an Issuer") - _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerToken(issuerName, vaultURL, vaultPath, vaultSecretTokenName)) + _, err := f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(util.NewCertManagerVaultIssuerToken(issuerName, vaultURL, vaultPath, vaultSecretTokenName, authPath, vault.VaultCA)) Expect(err).NotTo(HaveOccurred()) By("Waiting for Issuer to become Ready") diff --git a/test/util/util.go b/test/util/util.go index e05e3a98e..475ac6b7a 100644 --- a/test/util/util.go +++ b/test/util/util.go @@ -473,7 +473,7 @@ func NewCertManagerSelfSignedIssuer(name string) *v1alpha1.Issuer { } } -func NewCertManagerVaultIssuerToken(name, vaultURL, vaultPath, vaultSecretToken string) *v1alpha1.Issuer { +func NewCertManagerVaultIssuerToken(name, vaultURL, vaultPath, vaultSecretToken, authPath string, caBundle []byte) *v1alpha1.Issuer { return &v1alpha1.Issuer{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -481,8 +481,9 @@ func NewCertManagerVaultIssuerToken(name, vaultURL, vaultPath, vaultSecretToken Spec: v1alpha1.IssuerSpec{ IssuerConfig: v1alpha1.IssuerConfig{ Vault: &v1alpha1.VaultIssuer{ - Server: vaultURL, - Path: vaultPath, + Server: vaultURL, + Path: vaultPath, + CABundle: caBundle, Auth: v1alpha1.VaultAuth{ TokenSecretRef: v1alpha1.SecretKeySelector{ Key: "secretkey", @@ -497,7 +498,7 @@ func NewCertManagerVaultIssuerToken(name, vaultURL, vaultPath, vaultSecretToken } } -func NewCertManagerVaultIssuerAppRole(name, vaultURL, vaultPath, roleId, vaultSecretAppRole, authPath string) *v1alpha1.Issuer { +func NewCertManagerVaultIssuerAppRole(name, vaultURL, vaultPath, roleId, vaultSecretAppRole string, authPath string, caBundle []byte) *v1alpha1.Issuer { return &v1alpha1.Issuer{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -505,8 +506,9 @@ func NewCertManagerVaultIssuerAppRole(name, vaultURL, vaultPath, roleId, vaultSe Spec: v1alpha1.IssuerSpec{ IssuerConfig: v1alpha1.IssuerConfig{ Vault: &v1alpha1.VaultIssuer{ - Server: vaultURL, - Path: vaultPath, + Server: vaultURL, + Path: vaultPath, + CABundle: caBundle, Auth: v1alpha1.VaultAuth{ AppRole: v1alpha1.VaultAppRole{ Path: authPath, diff --git a/test/util/vault/util.go b/test/util/vault/util.go index 4ad00fd2e..f14ef08ef 100644 --- a/test/util/vault/util.go +++ b/test/util/vault/util.go @@ -17,7 +17,16 @@ limitations under the License. package vault import ( + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" "fmt" + "math/big" + "net" + "net/http" "os/exec" "path" "time" @@ -30,6 +39,18 @@ import ( const vaultToken = "vault-root-token" +var ( + VaultCA []byte + VaultCAPrivateKey []byte + VaultCert []byte + VaultCertPrivateKey []byte +) + +func init() { + generateCA() + generateCert() +} + func NewVaultTokenSecret(name string) *v1.Secret { return &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -72,7 +93,16 @@ func NewVaultInitializer(container, rootMount, intermediateMount, role, authPath time.Sleep(3 * time.Second) cfg := vault.DefaultConfig() - cfg.Address = "http://127.0.0.1:8200" + cfg.Address = "https://127.0.0.1:8200" + + caCertPool := x509.NewCertPool() + ok := caCertPool.AppendCertsFromPEM(VaultCA) + if ok == false { + glog.Fatal("error loading Vault CA bundle") + } + + cfg.HttpClient.Transport.(*http.Transport).TLSClientConfig.RootCAs = caCertPool + client, err := vault.NewClient(cfg) if err != nil { return nil, fmt.Errorf("Unable to initialize vault client: %s", err.Error()) @@ -284,8 +314,8 @@ func (v *VaultInitializer) importSignIntermediate(intermediateCa, rootCa, interm func (v *VaultInitializer) configureCert(mount string) error { params := map[string]string{ - "issuing_certificates": fmt.Sprintf("http://vault.vault:8200/v1/%s/ca", mount), - "crl_distribution_points": fmt.Sprintf("http://vault.vault:8200/v1/%s/crl", mount), + "issuing_certificates": fmt.Sprintf("https://vault.vault:8200/v1/%s/ca", mount), + "crl_distribution_points": fmt.Sprintf("https://vault.vault:8200/v1/%s/crl", mount), } url := path.Join("/v1", mount, "config", "urls") @@ -353,3 +383,78 @@ func (v *VaultInitializer) callVault(method, url, field string, params map[strin return fieldData, err } + +func generateCA() { + ca := &x509.Certificate{ + SerialNumber: big.NewInt(1653), + Subject: pkix.Name{ + Organization: []string{"cert-manager test"}, + }, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(10, 0, 0), + IsCA: true, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + BasicConstraintsValid: true, + } + + privateKey, _ := rsa.GenerateKey(rand.Reader, 2048) + pubKey := &privateKey.PublicKey + caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, pubKey, privateKey) + if err != nil { + glog.Fatalf("create ca failed: %s", err.Error()) + } + + VaultCA = encodePublicKey(caBytes) + VaultCAPrivateKey = encodePrivateKey(privateKey) +} + +func generateCert() { + catls, err := tls.X509KeyPair(VaultCA, VaultCAPrivateKey) + if err != nil { + glog.Fatalf("parsing ca key pair failed: %s", err.Error()) + } + ca, err := x509.ParseCertificate(catls.Certificate[0]) + if err != nil { + glog.Fatalf("parsing ca failed: %s", err.Error()) + } + + cert := &x509.Certificate{ + SerialNumber: big.NewInt(1658), + Subject: pkix.Name{ + CommonName: "vault.vault", + Organization: []string{"cert-manager vault server"}, + }, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(10, 0, 0), + SubjectKeyId: []byte{1, 2, 3, 4, 6}, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + KeyUsage: x509.KeyUsageDigitalSignature, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1)}, + DNSNames: []string{"vault.vault"}, + } + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + glog.Fatalf("private key generation failed: %s", err.Error()) + } + + publicKey := &privateKey.PublicKey + + certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, publicKey, catls.PrivateKey) + if err != nil { + glog.Fatal(err) + } + + VaultCert = encodePublicKey(certBytes) + VaultCertPrivateKey = encodePrivateKey(privateKey) +} + +func encodePublicKey(pub []byte) []byte { + return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: pub}) +} + +func encodePrivateKey(priv *rsa.PrivateKey) []byte { + block := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)} + + return pem.EncodeToMemory(block) +}