Skip to content

Commit

Permalink
ci: simplifying e2e test for Vault with mTLS enforced
Browse files Browse the repository at this point in the history
Signed-off-by: Rodrigo Fior Kuntzer <rodrigo@miro.com>
  • Loading branch information
rodrigorfk committed Jan 17, 2024
1 parent bb0ba9a commit a2ebf4b
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 149 deletions.
14 changes: 8 additions & 6 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -6613,30 +6613,32 @@ when the Vault server requires mutual authentication.</p>
<tbody>
<tr>
<td>
<code>clientCert</code></br>
<code>certSecretRef</code></br>
<em>
<a href="https://pkg.go.dev/github.com/external-secrets/external-secrets/apis/meta/v1#SecretKeySelector">
External Secrets meta/v1.SecretKeySelector
</a>
</em>
</td>
<td>
<p>ClientCert is a certificate added to the transport layer
when communicating with the Vault server.</p>
<p>CertSecretRef is a certificate added to the transport layer
when communicating with the Vault server.
If no key for the Secret is specified, external-secret will default to &lsquo;tls.crt&rsquo;.</p>
</td>
</tr>
<tr>
<td>
<code>secretRef</code></br>
<code>keySecretRef</code></br>
<em>
<a href="https://pkg.go.dev/github.com/external-secrets/external-secrets/apis/meta/v1#SecretKeySelector">
External Secrets meta/v1.SecretKeySelector
</a>
</em>
</td>
<td>
<p>SecretRef to a key in a Secret resource containing client private key
added to the transport layer when communicating with the Vault server.</p>
<p>KeySecretRef to a key in a Secret resource containing client private key
added to the transport layer when communicating with the Vault server.
If no key for the Secret is specified, external-secret will default to &lsquo;tls.key&rsquo;.</p>
</td>
</tr>
</tbody>
Expand Down
49 changes: 25 additions & 24 deletions e2e/framework/addon/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"encoding/pem"
"fmt"
"k8s.io/apimachinery/pkg/types"
"math/big"
"net"
"net/http"
Expand All @@ -41,11 +41,12 @@ import (
)

type Vault struct {
chart *HelmChart
Namespace string
PodName string
VaultClient *vault.Client
VaultURL string
chart *HelmChart
Namespace string
PodName string
VaultClient *vault.Client
VaultURL string
VaultMtlsURL string

RootToken string
VaultServerCA []byte
Expand All @@ -66,17 +67,12 @@ type Vault struct {
AppRoleSecret string
AppRoleID string
AppRolePath string
EnforceMTLS bool
}

const privatePemType = "RSA PRIVATE KEY"

func NewVault(namespace string, enforceMTLS bool) *Vault {
func NewVault(namespace string) *Vault {
repo := "hashicorp-" + namespace
values := []string{"/k8s/vault.values.yaml"}
if enforceMTLS {
values = []string{"/k8s/vault-mtls.values.yaml"}
}
return &Vault{
chart: &HelmChart{
Namespace: namespace,
Expand All @@ -87,10 +83,9 @@ func NewVault(namespace string, enforceMTLS bool) *Vault {
Name: repo,
URL: "https://helm.releases.hashicorp.com",
},
Values: values,
Values: []string{"/k8s/vault.values.yaml"},
},
Namespace: namespace,
EnforceMTLS: enforceMTLS,
Namespace: namespace,
}
}

Expand All @@ -106,6 +101,11 @@ func (l *Vault) Install() error {
return err
}

err = l.patchVaultService()
if err != nil {
return err
}

err = l.initVault()
if err != nil {
return err
Expand All @@ -119,6 +119,15 @@ func (l *Vault) Install() error {
return nil
}

func (l *Vault) patchVaultService() error {
serviceName := fmt.Sprintf("vault-%s", l.Namespace)
servicePatch := []byte(`[{"op": "add", "path": "/spec/ports/-", "value": { "name": "https-mtls", "port": 8210, "protocol": "TCP", "targetPort": 8210 }}]`)
clientSet := l.chart.config.KubeClientSet
_, err := clientSet.CoreV1().Services(l.Namespace).
Patch(context.Background(), serviceName, types.JSONPatchType, servicePatch, metav1.PatchOptions{})
return err
}

func (l *Vault) initVault() error {
sec := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -233,17 +242,9 @@ func (l *Vault) initVault() error {
}
cfg := vault.DefaultConfig()
l.VaultURL = fmt.Sprintf("https://vault-%s.%s.svc.cluster.local:8200", l.Namespace, l.Namespace)
l.VaultMtlsURL = fmt.Sprintf("https://vault-%s.%s.svc.cluster.local:8210", l.Namespace, l.Namespace)
cfg.Address = l.VaultURL
cfg.HttpClient.Transport.(*http.Transport).TLSClientConfig.RootCAs = caCertPool
if l.EnforceMTLS {
cert, err := tls.X509KeyPair(clientPem, clientKeyPem)
if err != nil {
return fmt.Errorf("error parsing the client certificates for the transport layer: %w", err)
}
if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
}
}
l.VaultClient, err = vault.NewClient(cfg)
if err != nil {
return fmt.Errorf("unable to create vault client: %w", err)
Expand Down
22 changes: 13 additions & 9 deletions e2e/framework/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func TableFunc(f *Framework, prov SecretStoreProvider) func(...func(*TestCase))
if tc.ExternalSecretV1Alpha1 != nil {
err = tc.Framework.CRClient.Create(context.Background(), tc.ExternalSecretV1Alpha1)
Expect(err).ToNot(HaveOccurred())
} else {
} else if tc.ExternalSecret != nil {
// create v1beta1 external secret otherwise
err = tc.Framework.CRClient.Create(context.Background(), tc.ExternalSecret)
Expect(err).ToNot(HaveOccurred())
Expand All @@ -89,19 +89,23 @@ func TableFunc(f *Framework, prov SecretStoreProvider) func(...func(*TestCase))
}
}
// in case target name is empty
if tc.ExternalSecret.Spec.Target.Name == "" {
if tc.ExternalSecret != nil && tc.ExternalSecret.Spec.Target.Name == "" {
TargetSecretName = tc.ExternalSecret.ObjectMeta.Name
}

// wait for Kind=Secret to have the expected data
secret, err := tc.Framework.WaitForSecretValue(tc.Framework.Namespace.Name, TargetSecretName, tc.ExpectedSecret)
if err != nil {
f.printESDebugLogs(tc.ExternalSecret.Name, tc.ExternalSecret.Namespace)
log.Logf("Did not match. Expected: %+v, Got: %+v", tc.ExpectedSecret, secret)
}
if tc.ExpectedSecret != nil {
secret, err := tc.Framework.WaitForSecretValue(tc.Framework.Namespace.Name, TargetSecretName, tc.ExpectedSecret)
if err != nil {
f.printESDebugLogs(tc.ExternalSecret.Name, tc.ExternalSecret.Namespace)
log.Logf("Did not match. Expected: %+v, Got: %+v", tc.ExpectedSecret, secret)
}

Expect(err).ToNot(HaveOccurred())
tc.AfterSync(prov, secret)
Expect(err).ToNot(HaveOccurred())
tc.AfterSync(prov, secret)
} else {
tc.AfterSync(prov, nil)
}
}
}

Expand Down
30 changes: 0 additions & 30 deletions e2e/k8s/vault-mtls.values.yaml

This file was deleted.

8 changes: 8 additions & 0 deletions e2e/k8s/vault.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ server:
tls_key_file = "/etc/vault-config/server-cert-key.pem"
tls_client_ca_file = "/etc/vault-config/vault-client-ca.pem"
}
listener "tcp" {
address = "[::]:8210"
cluster_address = "[::]:8211"
tls_cert_file = "/etc/vault-config/server-cert.pem"
tls_key_file = "/etc/vault-config/server-cert-key.pem"
tls_client_ca_file = "/etc/vault-config/vault-client-ca.pem"
tls_require_and_verify_client_cert = true
}
storage "file" {
path = "/vault/data"
}

0 comments on commit a2ebf4b

Please sign in to comment.