Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Vault namespaces #84

Merged
merged 7 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ build-in-docker: clean
make build

image: build-in-docker
docker build --build-arg VERSION=$(IMAGE_VERSION) -t $(IMAGE_TAG) .
docker build --no-cache --build-arg VERSION=$(IMAGE_VERSION) -t $(IMAGE_TAG) .

e2e-container:
REGISTRY_NAME="e2e" IMAGE_VERSION="latest" make image
Expand Down
8 changes: 3 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ go 1.12

require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/hashicorp/go-hclog v0.8.0
github.com/hashicorp/vault/api v1.0.4
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/pkg/errors v0.9.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
google.golang.org/grpc v1.29.1
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c // indirect
gotest.tools v2.2.0+incompatible
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c
k8s.io/api v0.20.0
k8s.io/apimachinery v0.20.0
k8s.io/client-go v0.20.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,9 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
Expand Down Expand Up @@ -459,7 +460,6 @@ github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down Expand Up @@ -716,8 +716,9 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down Expand Up @@ -885,7 +886,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
8 changes: 5 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package config

import (
"encoding/json"
"errors"
"os"
"strconv"

"github.com/hashicorp/go-hclog"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
"k8s.io/apimachinery/pkg/types"
)

Expand Down Expand Up @@ -39,6 +39,7 @@ type Parameters struct {
VaultAddress string
VaultRoleName string
VaultKubernetesMountPath string
VaultNamespace string
VaultTLSConfig TLSConfig
Secrets []Secret
PodInfo PodInfo
Expand Down Expand Up @@ -102,6 +103,7 @@ func parseParameters(logger hclog.Logger, parametersStr string) (Parameters, err
var parameters Parameters
parameters.VaultRoleName = params["roleName"]
parameters.VaultAddress = params["vaultAddress"]
parameters.VaultNamespace = params["vaultNamespace"]
parameters.VaultTLSConfig.CACertPath = params["vaultCACertPath"]
parameters.VaultTLSConfig.CADirectory = params["vaultCADirectory"]
parameters.VaultTLSConfig.TLSServerName = params["vaultTLSServerName"]
Expand Down Expand Up @@ -151,7 +153,7 @@ func (c *Config) validate() error {
return errors.New("missing target path field")
}
if c.Parameters.VaultRoleName == "" {
return errors.Errorf("missing 'roleName' in SecretProviderClass definition")
return errors.New("missing 'roleName' in SecretProviderClass definition")
}
if len(c.Parameters.Secrets) == 0 {
return errors.New("no secrets configured - the provider will not read any secret material")
Expand Down
15 changes: 9 additions & 6 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"encoding/json"
"io/ioutil"
"path/filepath"
"reflect"
"testing"

"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
"gotest.tools/assert"
"gopkg.in/yaml.v3"
)

const (
Expand Down Expand Up @@ -54,7 +54,7 @@ func TestParseParametersFromYaml(t *testing.T) {
params, err := parseParameters(hclog.NewNullLogger(), string(paramsBytes))
require.NoError(t, err)

assert.DeepEqual(t, Parameters{
require.True(t, reflect.DeepEqual(Parameters{
tomhjp marked this conversation as resolved.
Show resolved Hide resolved
VaultAddress: defaultVaultAddress,
VaultKubernetesMountPath: defaultVaultKubernetesMountPath,
Secrets: []Secret{
Expand All @@ -78,7 +78,7 @@ func TestParseParametersFromYaml(t *testing.T) {
Method: "PUT",
},
},
}, params)
}, params))
}

func TestParseParameters(t *testing.T) {
Expand All @@ -105,7 +105,7 @@ func TestParseParameters(t *testing.T) {
ServiceAccountName: "default",
},
}
assert.DeepEqual(t, expected, actual)
require.True(t, reflect.DeepEqual(expected, actual))
tomhjp marked this conversation as resolved.
Show resolved Hide resolved
}

func TestParseConfig(t *testing.T) {
Expand All @@ -114,6 +114,7 @@ func TestParseConfig(t *testing.T) {
defaultParams := Parameters{
VaultAddress: defaultVaultAddress,
VaultKubernetesMountPath: defaultVaultKubernetesMountPath,
VaultNamespace: "",
}
for _, tc := range []struct {
name string
Expand Down Expand Up @@ -150,6 +151,7 @@ func TestParseConfig(t *testing.T) {
"roleName": "example-role",
"vaultSkipTLSVerify": "true",
"vaultAddress": "my-vault-address",
"vaultNamespace": "my-vault-namespace",
"vaultKubernetesMountPath": "my-mount-path",
"KubernetesServiceAccountPath": "my-account-path",
"objects": objects,
Expand All @@ -161,6 +163,7 @@ func TestParseConfig(t *testing.T) {
expected := defaultParams
expected.VaultRoleName = roleName
expected.VaultAddress = "my-vault-address"
expected.VaultNamespace = "my-vault-namespace"
expected.VaultKubernetesMountPath = "my-mount-path"
expected.VaultTLSConfig.SkipVerify = true
expected.Secrets = []Secret{
Expand All @@ -175,7 +178,7 @@ func TestParseConfig(t *testing.T) {
require.NoError(t, err)
cfg, err := Parse(hclog.NewNullLogger(), string(parametersStr), tc.targetPath, "420")
require.NoError(t, err, tc.name)
assert.DeepEqual(t, tc.expected, cfg)
require.True(t, reflect.DeepEqual(tc.expected, cfg))
tomhjp marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
6 changes: 6 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,12 @@ func (p *provider) MountSecretsStoreObjectContent(ctx context.Context, cfg confi
return nil, err
}

// Set Vault namespace if configured
if cfg.VaultNamespace != "" {
p.logger.Debug("setting Vault namespace", "namespace", cfg.VaultNamespace)
client.SetNamespace(cfg.VaultNamespace)
}

// Authenticate to vault using the jwt token
_, err = p.login(ctx, client, cfg.Parameters)
if err != nil {
Expand Down
9 changes: 4 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,16 @@ import (
"github.com/hashicorp/go-hclog"
providerserver "github.com/hashicorp/vault-csi-provider/internal/server"
"github.com/hashicorp/vault-csi-provider/internal/version"
"github.com/spf13/pflag"
"google.golang.org/grpc"
"google.golang.org/grpc/status"
pb "sigs.k8s.io/secrets-store-csi-driver/provider/v1alpha1"
)

var (
endpoint = pflag.String("endpoint", "/tmp/vault.sock", "path to socket on which to listen for driver gRPC calls")
debug = pflag.Bool("debug", false, "sets log to debug level")
endpoint = flag.String("endpoint", "/tmp/vault.sock", "path to socket on which to listen for driver gRPC calls")
debug = flag.Bool("debug", false, "sets log to debug level")
healthAddr = flag.String("health_addr", ":8080", "configure http listener for reporting health")
selfVersion = pflag.Bool("version", false, "prints the version information")
selfVersion = flag.Bool("version", false, "prints the version information")
)

func main() {
Expand All @@ -37,7 +36,7 @@ func main() {
}

func realMain(logger hclog.Logger) error {
pflag.Parse()
flag.Parse()

// set log level
logger.SetLevel(hclog.Info)
Expand Down
17 changes: 17 additions & 0 deletions test/bats/configs/vault-kv-namespace-secretproviderclass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
name: vault-kv-namespace
spec:
provider: vault
parameters:
roleName: "kv-namespace-role"
vaultAddress: https://vault:8200
vaultNamespace: "acceptance"
vaultCACertPath: /mnt/tls/ca.crt
vaultTLSClientCertPath: /mnt/tls/client.crt
vaultTLSClientKeyPath: /mnt/tls/client.key
objects: |
- objectName: "secret-1"
secretPath: "secret/data/kv1-namespace"
secretKey: "greeting"
3 changes: 3 additions & 0 deletions test/bats/configs/vault-policy-kv-namespace.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
path "secret/data/kv1-namespace" {
capabilities = ["read"]
}
9 changes: 8 additions & 1 deletion test/bats/configs/vault/vault.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ injector:

server:
image:
repository: docker.mirror.hashicorp.services/vault
repository: docker.mirror.hashicorp.services/hashicorp/vault-enterprise
tag: 1.7.0_ent
volumes:
- name: vault-server-tls
secret:
Expand Down Expand Up @@ -45,6 +46,12 @@ server:

csi:
enabled: true
debug: true

image:
repository: "e2e/vault-csi-provider"
tag: "latest"
pullPolicy: Never

volumes:
- name: vault-client-tls
Expand Down
27 changes: 27 additions & 0 deletions test/bats/provider.bats
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ CONFIGS=test/bats/configs
setup(){
{ # Braces used to redirect all setup logs.
# 1. Configure Vault.
kubectl --namespace=csi exec vault-0 -- vault namespace create acceptance

# 1. a) Vault policies
cat $CONFIGS/vault-policy-db.hcl | kubectl --namespace=csi exec -i vault-0 -- vault policy write db-policy -
cat $CONFIGS/vault-policy-kv.hcl | kubectl --namespace=csi exec -i vault-0 -- vault policy write kv-policy -
cat $CONFIGS/vault-policy-pki.hcl | kubectl --namespace=csi exec -i vault-0 -- vault policy write pki-policy -
cat $CONFIGS/vault-policy-kv-namespace.hcl | kubectl --namespace=csi exec -i vault-0 -- vault policy write -namespace=acceptance kv-namespace-policy -

# 1. b) Setup kubernetes auth engine.
kubectl --namespace=csi exec vault-0 -- vault auth enable kubernetes
Expand All @@ -30,6 +33,12 @@ setup(){
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
issuer="https://kubernetes.default.svc.cluster.local"'
kubectl --namespace=csi exec vault-0 -- vault auth enable -namespace=acceptance kubernetes
kubectl --namespace=csi exec vault-0 -- sh -c 'vault write -namespace=acceptance auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
issuer="https://kubernetes.default.svc.cluster.local"'
kubectl --namespace=csi exec vault-0 -- vault write auth/kubernetes/role/db-role \
bound_service_account_names=nginx-db \
bound_service_account_namespaces=test \
Expand All @@ -40,6 +49,11 @@ setup(){
bound_service_account_namespaces=test \
policies=kv-policy \
ttl=20m
kubectl --namespace=csi exec vault-0 -- vault write -namespace=acceptance auth/kubernetes/role/kv-namespace-role \
bound_service_account_names=nginx-kv-namespace \
bound_service_account_namespaces=test \
policies=kv-namespace-policy \
ttl=20m
kubectl --namespace=csi exec vault-0 -- vault write auth/kubernetes/role/pki-role \
bound_service_account_names=nginx-pki \
bound_service_account_namespaces=test \
Expand Down Expand Up @@ -67,11 +81,14 @@ setup(){
kubectl --namespace=csi exec vault-0 -- vault kv put secret/kv2 bar2=hello2
kubectl --namespace=csi exec vault-0 -- vault kv put secret/kv-sync1 bar1=hello-sync1
kubectl --namespace=csi exec vault-0 -- vault kv put secret/kv-sync2 bar2=hello-sync2
kubectl --namespace=csi exec vault-0 -- vault secrets enable -namespace=acceptance -path=secret -version=2 kv
kubectl --namespace=csi exec vault-0 -- vault kv put -namespace=acceptance secret/kv1-namespace greeting=hello-namespaces

# 2. Create shared k8s resources.
kubectl create namespace test
kubectl --namespace=test apply -f $CONFIGS/vault-all-secretproviderclass.yaml
kubectl --namespace=test apply -f $CONFIGS/vault-db-secretproviderclass.yaml
kubectl --namespace=test apply -f $CONFIGS/vault-kv-namespace-secretproviderclass.yaml
kubectl --namespace=test apply -f $CONFIGS/vault-kv-secretproviderclass.yaml
kubectl --namespace=test apply -f $CONFIGS/vault-kv-sync-secretproviderclass.yaml
kubectl --namespace=test apply -f $CONFIGS/vault-kv-sync-multiple-secretproviderclass.yaml
Expand All @@ -98,6 +115,7 @@ teardown(){
fi

# Teardown Vault configuration.
kubectl --namespace=csi exec vault-0 -- vault namespace delete acceptance
kubectl --namespace=csi exec vault-0 -- vault auth disable kubernetes
kubectl --namespace=csi exec vault-0 -- vault secrets disable secret
kubectl --namespace=csi exec vault-0 -- vault secrets disable pki
Expand Down Expand Up @@ -274,3 +292,12 @@ teardown(){
wait_for_success "kubectl --namespace=test describe pod nginx-kv | grep 'FailedMount.*failed to mount secrets store objects for pod test/nginx-kv'"
wait_for_success "kubectl --namespace=test describe pod nginx-kv | grep 'service account name not authorized'"
}

@test "9 Vault Enterprise namespace" {
helm --namespace=test install nginx $CONFIGS/nginx \
--set engine=kv-namespace --set sa=kv-namespace \
--wait --timeout=5m

result=$(kubectl --namespace=test exec nginx-kv-namespace -- cat /mnt/secrets-store/secret-1)
[[ "$result" == "hello-namespaces" ]]
}