diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f5c9bbee..53c292183 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ -## 0.1.0 +## 0.1.1 (August 7th, 2019) + +Features: + +* Added `authDelegator` Cluster Role Binding to Vault service account for + bootstrapping Kube auth method + +Improvements: + +* Added `server.service.clusterIP` to `values.yml` so users can toggle + the Vault service to headless by using the value `None`. +* Upgraded Vault to 1.2.1 + +## 0.1.0 (August 6th, 2019) Initial release diff --git a/Chart.yaml b/Chart.yaml index 44626b83f..f920f080a 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v1 name: vault -version: 0.1.0 +version: 0.1.1 description: Install and configure Vault on Kubernetes. home: https://www.vaultproject.io icon: https://github.com/hashicorp/vault/raw/f22d202cde2018f9455dec755118a9b84586e082/Vault_PrimaryLogo_Black.png diff --git a/templates/server-clusterrolebinding.yaml b/templates/server-clusterrolebinding.yaml new file mode 100644 index 000000000..43e8073b9 --- /dev/null +++ b/templates/server-clusterrolebinding.yaml @@ -0,0 +1,22 @@ +{{ template "vault.mode" . }} +{{- if and (ne .mode "") (and (eq (.Values.global.enabled | toString) "true") (eq (.Values.server.authDelegator.enabled | toString) "true")) }} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: {{ template "vault.fullname" . }}-server-binding + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.Version | quote }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: {{ template "vault.fullname" . }} + namespace: {{ .Release.Namespace }} +{{ end }} diff --git a/templates/server-service.yaml b/templates/server-service.yaml index 7ee7dce57..a70ab4e27 100644 --- a/templates/server-service.yaml +++ b/templates/server-service.yaml @@ -1,8 +1,4 @@ -# Headless service for Vault server DNS entries. This service should only -# point to Vault servers. For access to an agent, one should assume that -# the agent is installed locally on the node and the NODE_IP should be used. -# If the node can't run a Vault agent, then this service can be used to -# communicate directly to a server agent. +# Service for Vault cluster {{- if and (eq (.Values.server.service.enabled | toString) "true" ) (eq (.Values.global.enabled | toString) "true") }} apiVersion: v1 kind: Service @@ -20,7 +16,7 @@ metadata: # https://github.com/kubernetes/kubernetes/issues/58662 service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" spec: - clusterIP: None + clusterIP: {{ .Values.server.service.clusterIP }} # We want the servers to become available even if they're not ready # since this DNS is also used for join operations. publishNotReadyAddresses: true @@ -32,7 +28,7 @@ spec: port: 8201 targetPort: 8201 selector: - app: {{ template "vault.name" . }} - release: "{{ .Release.Name }}" + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} component: server {{- end }} diff --git a/test/acceptance/server-dev.bats b/test/acceptance/server-dev.bats index 4f104dd2c..eb6784899 100644 --- a/test/acceptance/server-dev.bats +++ b/test/acceptance/server-dev.bats @@ -20,7 +20,7 @@ load _helpers # Service local service=$(kubectl get service "$(name_prefix)" --output json | jq -r '.spec.clusterIP') - [ "${service}" == "None" ] + [ "${service}" != "None" ] local service=$(kubectl get service "$(name_prefix)" --output json | jq -r '.spec.type') diff --git a/test/acceptance/server-ha.bats b/test/acceptance/server-ha.bats index 30c4e50af..bb0fa3f00 100644 --- a/test/acceptance/server-ha.bats +++ b/test/acceptance/server-ha.bats @@ -44,7 +44,7 @@ load _helpers # Service local service=$(kubectl get service "$(name_prefix)" --output json | jq -r '.spec.clusterIP') - [ "${service}" == "None" ] + [ "${service}" != "None" ] local service=$(kubectl get service "$(name_prefix)" --output json | jq -r '.spec.type') diff --git a/test/acceptance/server.bats b/test/acceptance/server.bats index 542bc72e7..77f3e199d 100644 --- a/test/acceptance/server.bats +++ b/test/acceptance/server.bats @@ -60,7 +60,7 @@ load _helpers # Service local service=$(kubectl get service "$(name_prefix)" --output json | jq -r '.spec.clusterIP') - [ "${service}" == "None" ] + [ "${service}" != "None" ] local service=$(kubectl get service "$(name_prefix)" --output json | jq -r '.spec.type') diff --git a/test/unit/server-clusterrolebinding.bats b/test/unit/server-clusterrolebinding.bats new file mode 100755 index 000000000..88a8d0114 --- /dev/null +++ b/test/unit/server-clusterrolebinding.bats @@ -0,0 +1,62 @@ +#!/usr/bin/env bats + +load _helpers + +@test "server/ClusterRoleBinding: disabled by default" { + cd `chart_dir` + local actual=$(helm template \ + -x templates/server-clusterrolebinding.yaml \ + --set 'server.dev.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "false" ] + + local actual=$(helm template \ + -x templates/server-clusterrolebinding.yaml \ + --set 'server.ha.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "false" ] + + local actual=$(helm template \ + -x templates/server-clusterrolebinding.yaml \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "false" ] +} + +@test "server/ClusterRoleBinding: disable with global.enabled" { + cd `chart_dir` + local actual=$(helm template \ + -x templates/server-clusterrolebinding.yaml \ + --set 'global.enabled=false' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "false" ] +} + +@test "server/ClusterRoleBinding: can enable with server.authDelegator" { + cd `chart_dir` + local actual=$(helm template \ + -x templates/server-clusterrolebinding.yaml \ + --set 'server.authDelegator.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(helm template \ + -x templates/server-clusterrolebinding.yaml \ + --set 'server.authDelegator.enabled=true' \ + --set 'server.ha.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(helm template \ + -x templates/server-clusterrolebinding.yaml \ + --set 'server.authDelegator.enabled=true' \ + --set 'server.dev.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} diff --git a/test/unit/server-service.bats b/test/unit/server-service.bats index 0acc6e3ac..175a8f719 100755 --- a/test/unit/server-service.bats +++ b/test/unit/server-service.bats @@ -163,3 +163,52 @@ load _helpers yq -r '.spec.publishNotReadyAddresses' | tee /dev/stderr) [ "${actual}" = "true" ] } + +@test "server/Service: clusterIP empty by default" { + cd `chart_dir` + local actual=$(helm template \ + -x templates/server-service.yaml \ + --set 'server.dev.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.clusterIP' | tee /dev/stderr) + [ "${actual}" = "null" ] + + local actual=$(helm template \ + -x templates/server-service.yaml \ + --set 'server.ha.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.clusterIP' | tee /dev/stderr) + [ "${actual}" = "null" ] + + local actual=$(helm template \ + -x templates/server-service.yaml \ + . | tee /dev/stderr | + yq -r '.spec.clusterIP' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "server/Service: clusterIP can set" { + cd `chart_dir` + local actual=$(helm template \ + -x templates/server-service.yaml \ + --set 'server.dev.enabled=true' \ + --set 'server.service.clusterIP=None' \ + . | tee /dev/stderr | + yq -r '.spec.clusterIP' | tee /dev/stderr) + [ "${actual}" = "None" ] + + local actual=$(helm template \ + -x templates/server-service.yaml \ + --set 'server.ha.enabled=true' \ + --set 'server.service.clusterIP=None' \ + . | tee /dev/stderr | + yq -r '.spec.clusterIP' | tee /dev/stderr) + [ "${actual}" = "None" ] + + local actual=$(helm template \ + -x templates/server-service.yaml \ + --set 'server.service.clusterIP=None' \ + . | tee /dev/stderr | + yq -r '.spec.clusterIP' | tee /dev/stderr) + [ "${actual}" = "None" ] +} diff --git a/values.yaml b/values.yaml index bb9cf7acb..e4772a8c1 100644 --- a/values.yaml +++ b/values.yaml @@ -6,7 +6,7 @@ global: enabled: true # Image is the name (and tag) of the Vault Docker image. - image: "vault:1.2.0" + image: "vault:1.2.1" server: # Resource requests, limits, etc. for the server cluster placement. This @@ -21,6 +21,12 @@ server: # memory: 256Mi # cpu: 250m + # authDelegator enables a cluster role binding to be attached to the service + # account. This cluster role binding can be used to setup Kubernetes auth + # method. https://www.vaultproject.io/docs/auth/kubernetes.html + authDelegator: + enabled: false + # extraEnvVars is a list of extra enviroment variables to set with the stateful set. These could be # used to include variables required for auto-unseal. extraEnvironmentVars: {} @@ -69,6 +75,13 @@ server: # Enables a headless service to be used by the Vault Statefulset service: enabled: true + # clusterIP controls whether a Cluster IP address is attached to the + # Vault service within Kubernetes. By default the Vault service will + # be given a Cluster IP address, set to None to disable. When disabled + # Kubernetes will create a "headless" service. Headless services can be + # used to communicate with pods directly through DNS instead of a round robin + # load balancer. + clusterIP: "" # This configures the Vault Statefulset to create a PVC for data # storage when using the file backend. @@ -119,10 +132,11 @@ server: # using a stateful set. This should be HCL. config: | ui = true - api_addr = "http://POD_IP:8200" + listener "tcp" { tls_disable = 1 - address = "0.0.0.0:8200" + address = "[::]:8200" + cluster_address = "[::]:8201" } storage "file" { path = "/vault/data" @@ -152,10 +166,10 @@ server: # This should be HCL. config: | ui = true - api_addr = "http://POD_IP:8200" listener "tcp" { tls_disable = 1 - address = "0.0.0.0:8200" + address = "[::]:8200" + cluster_address = "[::]:8201" } storage "consul" { path = "vault"