Skip to content

Commit

Permalink
Merge pull request kelseyhightower#623 from stepanstipl/kubernetes-auth
Browse files Browse the repository at this point in the history
Add Kubernetes auth for Vault backend
  • Loading branch information
okushchenko authored Feb 23, 2018
2 parents 304efb5 + dc3e4e5 commit 94bf80e
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 19 deletions.
18 changes: 9 additions & 9 deletions backends/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ func New(config Config) (StoreClient, error) {
return file.NewFileClient(config.YAMLFile)
case "vault":
vaultConfig := map[string]string{
"app-id": config.AppID,
"user-id": config.UserID,
"role-id": config.RoleID,
"app-id": config.AppID,
"user-id": config.UserID,
"role-id": config.RoleID,
"secret-id": config.SecretID,
"username": config.Username,
"password": config.Password,
"token": config.AuthToken,
"cert": config.ClientCert,
"key": config.ClientKey,
"caCert": config.ClientCaKeys,
"username": config.Username,
"password": config.Password,
"token": config.AuthToken,
"cert": config.ClientCert,
"key": config.ClientKey,
"caCert": config.ClientCaKeys,
}
return vault.New(backendNodes[0], config.AuthType, vaultConfig)
case "dynamodb":
Expand Down
1 change: 1 addition & 0 deletions backends/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ type Config struct {
RoleID string
SecretID string
YAMLFile string
Role string
}
29 changes: 21 additions & 8 deletions backends/vault/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func authenticate(c *vaultapi.Client, authType string, params map[string]string)
switch authType {
case "app-role":
secret, err = c.Logical().Write("/auth/approle/login", map[string]interface{}{
"role_id": getParameter("role-id", params),
"role_id": getParameter("role-id", params),
"secret_id": getParameter("secret-id", params),
})
case "app-id":
Expand All @@ -74,6 +74,15 @@ func authenticate(c *vaultapi.Client, authType string, params map[string]string)
secret, err = c.Logical().Write(fmt.Sprintf("/auth/userpass/login/%s", username), map[string]interface{}{
"password": password,
})
case "kubernetes":
jwt, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
if err != nil {
return err
}
secret, err = c.Logical().Write("/auth/kubernetes/login", map[string]interface{}{
"jwt": string(jwt[:]),
"role": getParameter("role-id", params),
})
case "cert":
secret, err = c.Logical().Write("/auth/cert/login", map[string]interface{}{})
}
Expand All @@ -87,6 +96,10 @@ func authenticate(c *vaultapi.Client, authType string, params map[string]string)
return nil
}

if secret == nil || secret.Auth == nil {
return errors.New("Unable to authenticate")
}

log.Debug("client authenticated with auth backend: %s", authType)
// the default place for a token is in the auth section
// otherwise, the backend will set the token itself
Expand Down Expand Up @@ -214,9 +227,9 @@ func flatten(key string, value interface{}, vars map[string]string) {
}

// recursively walk the branches in the Vault, adding to branches map
func walkTree(c *Client, key string, branches map[string]bool) (error) {
func walkTree(c *Client, key string, branches map[string]bool) error {
log.Debug("listing %s from vault", key)

// strip trailing slash as long as it's not the only character
if last := len(key) - 1; last > 0 && key[last] == '/' {
key = key[:last]
Expand All @@ -238,11 +251,11 @@ func walkTree(c *Client, key string, branches map[string]bool) (error) {
}

switch resp.Data["keys"].(type) {
case []interface{}:
// expected
default:
log.Warning("key list type of '%s' is not supported (%T)", key, resp.Data["keys"])
return nil
case []interface{}:
// expected
default:
log.Warning("key list type of '%s' is not supported (%T)", key, resp.Data["keys"])
return nil
}

keyList := resp.Data["keys"].([]interface{})
Expand Down
2 changes: 1 addition & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func init() {
flag.StringVar(&authType, "auth-type", "", "Vault auth backend type to use (only used with -backend=vault)")
flag.StringVar(&appID, "app-id", "", "Vault app-id to use with the app-id backend (only used with -backend=vault and auth-type=app-id)")
flag.StringVar(&userID, "user-id", "", "Vault user-id to use with the app-id backend (only used with -backend=value and auth-type=app-id)")
flag.StringVar(&roleID, "role-id", "", "Vault role-id to use with the AppRole backend (only used with -backend=vault and auth-type=app-role)")
flag.StringVar(&roleID, "role-id", "", "Vault role-id to use with the AppRole, Kubernetes backends (only used with -backend=vault and either auth-type=app-role or auth-type=kubernetes)")
flag.StringVar(&secretID, "secret-id", "", "Vault secret-id to use with the AppRole backend (only used with -backend=vault and auth-type=app-role)")
flag.StringVar(&table, "table", "", "the name of the DynamoDB table (only used with -backend=dynamodb)")
flag.StringVar(&separator, "separator", "", "the separator to replace '/' with when looking up keys in the backend, prefixed '/' will also be removed (only used with -backend=redis)")
Expand Down
2 changes: 1 addition & 1 deletion docs/command-line-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Usage of confd:
-prefix string
key path prefix
-role-id string
Vault role-id to use with the AppRole backend (only used with -backend=vault and auth-type=app-role)
Vault role-id to use with the AppRole, Kubernetes backend (only used with -backend=vault and either auth-type=app-role or auth-type=kubernetes)
-scheme string
the backend URI scheme for nodes retrieved from DNS SRV records (http or https) (default "http")
-secret-id string
Expand Down
87 changes: 87 additions & 0 deletions docs/vault-kubernetes-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
These are steps to get vault with Kubernetes auth working on minikube.

*Do not use default service account in prod instead create dedicated acount for Vault auth.*

- Deploy Helm
```
# Install Helm - on macOS
brew install kubernetes-helm
# Deploy tiller into the cluster
helm init
- Install Vault in dev mode
```
# Add Vault chart
helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
# Install Vault
# Currently the chart has Vault 0.8.2 and we need 0.8.3 (but PR is pending)
helm install incubator/vault --name vault --set vault.dev=true --set image.tag="0.8.3"
```
- Enable Kubernetes backend
```
# Get Vault pod name
export POD_NAME=$(kubectl get pods --namespace default -l "app=vault" -o jsonpath="{.items[0].metadata.name}")
# Get inside pod
kubectl exec -i -t ${POD_NAME} sh
# Set env vars for Vault client
export VAULT_TOKEN=$(cat /root/.vault-token)
# Enable Kube auth backend
vault auth-enable kubernetes
# Configure Kube auth bacckend
vault write auth/kubernetes/config \
kubernetes_host=https://kubernetes \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Create Vault policy for testing
vault write sys/policy/test \
rules='path "secret/*" { capabilities = ["create", "read"] }'
# Cretate role for confd
vault write auth/kubernetes/role/confd \
bound_service_account_names=vault-auth \
bound_service_account_namespaces=default \
policies=test \
ttl=1h
# Write test secret
vault write secret/foo value=bar
```
- Create RBAC (if used) rule to allow acccess to TokenReview API
```
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: role-tokenreview-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-auth
namespace: default
```
- Start a pod with confd and get a secret
```
kubectl run test -i -t --image=quay.io/stepanstipl/test:confd-v7 \
--restart=Never -- sh
# Inside the pod
# Create confd config
mkdir -p /etc/confd/conf.d /etc/confd/templates
echo '[template]
src = "test.conf.tmpl"
dest = "/tmp/test.conf"
keys = [
"/secret/foo",
]' > /etc/confd/conf.d/test.toml
# And template
echo '{{getv "/secret/foo"}}' > /etc/confd/templates/test.conf.tmpl
# and finally run confd
confd -onetime -backend vault -auth-type kubernetes -role-id confd -node http://unrealistic-sabertooth-vault:8200 -log-level debug
```
- Check `/tmp/test.conf`, it should contain your secret
```
cat /tmp/test.conf
```

0 comments on commit 94bf80e

Please sign in to comment.