Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

Support ACL replication. #368

Merged
merged 1 commit into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
47 changes: 35 additions & 12 deletions templates/server-acl-init-job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,28 @@ spec:
spec:
restartPolicy: Never
serviceAccountName: {{ template "consul.fullname" . }}-server-acl-init
{{- if .Values.global.tls.enabled }}
{{- if (or .Values.global.tls.enabled (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey)) }}
volumes:
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- if .Values.global.tls.enabled }}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey) }}
- name: acl-replication-token
secret:
secretName: {{ .Values.global.acls.replicationToken.secretName }}
items:
- key: {{ .Values.global.acls.replicationToken.secretKey }}
path: acl-replication-token
{{- end }}
{{- end }}
containers:
- name: post-install-job
Expand All @@ -53,11 +63,18 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- if .Values.global.tls.enabled }}
{{- if (or .Values.global.tls.enabled (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey)) }}
volumeMounts:
{{- if .Values.global.tls.enabled }}
- name: consul-ca-cert
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
{{- if (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey) }}
- name: acl-replication-token
mountPath: /consul/acl/tokens
readOnly: true
{{- end }}
{{- end }}
command:
- "/bin/sh"
Expand Down Expand Up @@ -96,6 +113,12 @@ spec:
{{- if not (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
-create-client-token=false \
{{- end }}
{{- if .Values.global.acls.createReplicationToken }}
-create-acl-replication-token=true \
lkysow marked this conversation as resolved.
Show resolved Hide resolved
{{- end }}
{{- if (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey) }}
-acl-replication-token-file=/consul/acl/tokens/acl-replication-token \
{{- end }}
{{- if .Values.global.enableConsulNamespaces }}
-enable-namespaces=true \
{{- /* syncCatalog must be enabled to set sync flags */}}
Expand Down
3 changes: 3 additions & 0 deletions templates/server-config-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ data:
"enabled": true,
"default_policy": "deny",
"down_policy": "extend-cache",
{{- if (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey) }}
"enable_token_replication": true,
{{- end }}
"enable_token_persistence": true
}
}
Expand Down
10 changes: 10 additions & 0 deletions templates/server-statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ spec:
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
{{- if (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey) }}
- name: ACL_REPLICATION_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.global.acls.replicationToken.secretName | quote }}
key: {{ .Values.global.acls.replicationToken.secretKey | quote }}
{{- end }}
{{- include "consul.extraEnvironmentVars" .Values.server | nindent 12 }}
command:
- "/bin/sh"
Expand Down Expand Up @@ -154,6 +161,9 @@ spec:
{{- if .Values.global.federation.enabled }}
-hcl="connect { enable_mesh_gateway_wan_federation = true }" \
{{- end }}
{{- if (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey) }}
-hcl="acl { tokens { agent = \"${ACL_REPLICATION_TOKEN}\", replication = \"${ACL_REPLICATION_TOKEN}\" } }" \
{{- end }}
{{- if .Values.ui.enabled }}
-ui \
{{- end }}
Expand Down
123 changes: 123 additions & 0 deletions test/unit/server-acl-init-job.bats
Original file line number Diff line number Diff line change
Expand Up @@ -658,3 +658,126 @@ load _helpers
yq 'any(contains("inject-k8s-namespace-mirroring-prefix"))' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

#--------------------------------------------------------------------
# global.acls.createReplicationToken

@test "serverACLInit/Job: -create-acl-replication-token is not set by default" {
cd `chart_dir`
local actual=$(helm template \
-x templates/server-acl-init-job.yaml \
--set 'global.bootstrapACLs=true' \
. | tee /dev/stderr |
yq '.spec.template.spec.containers[0].command | any(contains("-create-acl-replication-token"))' | tee /dev/stderr)
[ "${actual}" = "false" ]
}

@test "serverACLInit/Job: -create-acl-replication-token is true when acls.createReplicationToken is true" {
cd `chart_dir`
local actual=$(helm template \
-x templates/server-acl-init-job.yaml \
--set 'global.bootstrapACLs=true' \
--set 'global.acls.createReplicationToken=true' \
. | tee /dev/stderr |
yq '.spec.template.spec.containers[0].command | any(contains("-create-acl-replication-token"))' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

#--------------------------------------------------------------------
# global.acls.replicationToken

@test "serverACLInit/Job: -acl-replication-token-file is not set by default" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-acl-init-job.yaml \
--set 'global.bootstrapACLs=true' \
. | tee /dev/stderr)

# Test the flag is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("-acl-replication-token-file"))' | tee /dev/stderr)
[ "${actual}" = "false" ]

# Test the volume doesn't exist
local actual=$(echo "$object" |
yq '.spec.template.spec.volumes | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]

# Test the volume mount doesn't exist
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].volumeMounts | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

@test "serverACLInit/Job: -acl-replication-token-file is not set when acls.replicationToken.secretName is set but secretKey is not" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-acl-init-job.yaml \
--set 'global.bootstrapACLs=true' \
--set 'global.acls.replicationToken.secretName=name' \
. | tee /dev/stderr)

# Test the flag is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("-acl-replication-token-file"))' | tee /dev/stderr)
[ "${actual}" = "false" ]

# Test the volume doesn't exist
local actual=$(echo "$object" |
yq '.spec.template.spec.volumes | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]

# Test the volume mount doesn't exist
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].volumeMounts | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

@test "serverACLInit/Job: -acl-replication-token-file is not set when acls.replicationToken.secretKey is set but secretName is not" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-acl-init-job.yaml \
--set 'global.bootstrapACLs=true' \
--set 'global.acls.replicationToken.secretKey=key' \
. | tee /dev/stderr)

# Test the flag is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("-acl-replication-token-file"))' | tee /dev/stderr)
[ "${actual}" = "false" ]

# Test the volume doesn't exist
local actual=$(echo "$object" |
yq '.spec.template.spec.volumes | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]

# Test the volume mount doesn't exist
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].volumeMounts | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

@test "serverACLInit/Job: -acl-replication-token-file is set when acls.replicationToken.secretKey and secretName are set" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-acl-init-job.yaml \
--set 'global.bootstrapACLs=true' \
--set 'global.acls.replicationToken.secretName=name' \
--set 'global.acls.replicationToken.secretKey=key' \
. | tee /dev/stderr)

# Test the -acl-replication-token-file flag is set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("-acl-replication-token-file=/consul/acl/tokens/acl-replication-token"))' | tee /dev/stderr)
[ "${actual}" = "true" ]

# Test the volume exists
local actual=$(echo "$object" |
yq '.spec.template.spec.volumes | map(select(.name == "acl-replication-token")) | length == 1' | tee /dev/stderr)
[ "${actual}" = "true" ]

# Test the volume mount exists
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].volumeMounts | map(select(.name == "acl-replication-token")) | length == 1' | tee /dev/stderr)
[ "${actual}" = "true" ]
}
47 changes: 47 additions & 0 deletions test/unit/server-configmap.bats
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,50 @@ load _helpers
yq -r '.data["proxy-defaults-config.json"]' | yq -r '.config_entries.bootstrap[0].mesh_gateway.mode' | tee /dev/stderr)
[ "${actual}" = "remote" ]
}

#--------------------------------------------------------------------
# global.acls.replicationToken

@test "server/ConfigMap: enable_token_replication is not set by default" {
cd `chart_dir`
local actual=$(helm template \
-x templates/server-config-configmap.yaml \
--set 'global.bootstrapACLs=true' \
. | tee /dev/stderr |
yq -r '.data["acl-config.json"]' | yq -r '.acl.enable_token_replication' | tee /dev/stderr)
[ "${actual}" = "null" ]
}

@test "server/ConfigMap: enable_token_replication is not set when acls.replicationToken.secretName is set but secretKey is not" {
cd `chart_dir`
local actual=$(helm template \
-x templates/server-config-configmap.yaml \
--set 'global.bootstrapACLs=true' \
--set 'global.acls.replicationToken.secretName=name' \
. | tee /dev/stderr |
yq -r '.data["acl-config.json"]' | yq -r '.acl.enable_token_replication' | tee /dev/stderr)
[ "${actual}" = "null" ]
}

@test "server/ConfigMap: enable_token_replication is not set when acls.replicationToken.secretKey is set but secretName is not" {
cd `chart_dir`
local actual=$(helm template \
-x templates/server-config-configmap.yaml \
--set 'global.bootstrapACLs=true' \
--set 'global.acls.replicationToken.secretKey=key' \
. | tee /dev/stderr |
yq -r '.data["acl-config.json"]' | yq -r '.acl.enable_token_replication' | tee /dev/stderr)
[ "${actual}" = "null" ]
}

@test "server/ConfigMap: enable_token_replication is set when acls.replicationToken.secretKey and secretName are set" {
cd `chart_dir`
local actual=$(helm template \
-x templates/server-config-configmap.yaml \
--set 'global.bootstrapACLs=true' \
--set 'global.acls.replicationToken.secretName=name' \
--set 'global.acls.replicationToken.secretKey=key' \
. | tee /dev/stderr |
yq -r '.data["acl-config.json"]' | yq -r '.acl.enable_token_replication' | tee /dev/stderr)
[ "${actual}" = "true" ]
}
75 changes: 75 additions & 0 deletions test/unit/server-statefulset.bats
Original file line number Diff line number Diff line change
Expand Up @@ -685,3 +685,78 @@ load _helpers
yq '.spec.template.spec.containers[0].command | join(" ") | contains("connect { enable_mesh_gateway_wan_federation = true }")' | tee /dev/stderr)
[ "${actual}" = "false" ]
}

#--------------------------------------------------------------------
# global.acls.replicationToken

@test "server/StatefulSet: acl replication token config is not set by default" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-statefulset.yaml \
. | tee /dev/stderr)

# Test the flag is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("ACL_REPLICATION_TOKEN"))' | tee /dev/stderr)
[ "${actual}" = "false" ]

# Test the ACL_REPLICATION_TOKEN environment variable is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].env | map(select(.name == "ACL_REPLICATION_TOKEN")) | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

@test "server/StatefulSet: acl replication token config is not set when acls.replicationToken.secretName is set but secretKey is not" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-statefulset.yaml \
--set 'global.acls.replicationToken.secretName=name' \
. | tee /dev/stderr)

# Test the flag is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("ACL_REPLICATION_TOKEN"))' | tee /dev/stderr)
[ "${actual}" = "false" ]

# Test the ACL_REPLICATION_TOKEN environment variable is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].env | map(select(.name == "ACL_REPLICATION_TOKEN")) | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

@test "server/StatefulSet: acl replication token config is not set when acls.replicationToken.secretKey is set but secretName is not" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-statefulset.yaml \
--set 'global.acls.replicationToken.secretKey=key' \
. | tee /dev/stderr)

# Test the flag is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("ACL_REPLICATION_TOKEN"))' | tee /dev/stderr)
[ "${actual}" = "false" ]

# Test the ACL_REPLICATION_TOKEN environment variable is not set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].env | map(select(.name == "ACL_REPLICATION_TOKEN")) | length == 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}

@test "server/StatefulSet: acl replication token config is set when acls.replicationToken.secretKey and secretName are set" {
cd `chart_dir`
local object=$(helm template \
-x templates/server-statefulset.yaml \
--set 'global.acls.replicationToken.secretName=name' \
--set 'global.acls.replicationToken.secretKey=key' \
. | tee /dev/stderr)

# Test the flag is set.
local actual=$(echo "$object" |
yq '.spec.template.spec.containers[0].command | any(contains("-hcl=\"acl { tokens { agent = \\\"${ACL_REPLICATION_TOKEN}\\\", replication = \\\"${ACL_REPLICATION_TOKEN}\\\" } }\""))' | tee /dev/stderr)
[ "${actual}" = "true" ]

# Test the ACL_REPLICATION_TOKEN environment variable is set.
local actual=$(echo "$object" |
yq -r -c '.spec.template.spec.containers[0].env | map(select(.name == "ACL_REPLICATION_TOKEN"))' | tee /dev/stderr)
[ "${actual}" = '[{"name":"ACL_REPLICATION_TOKEN","valueFrom":{"secretKeyRef":{"name":"name","key":"key"}}}]' ]
}
17 changes: 17 additions & 0 deletions values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,23 @@ global:
# This setting must be true in both primary and secondary datacenters.
enabled: false

# Configure ACLs.
acls:
# If true, an ACL token will be created that can be used in secondary
# datacenters for replication. This should only be set to true in the
# primary datacenter since the replication token must be created from that
# datacenter.
# In secondary datacenters, the secret will be imported from the primary
# datacenter and referenced via global.acls.replicationToken.
createReplicationToken: false

# replicationToken references a secret containing the replication ACL token.
# This token will be used by secondary datacenters to perform ACL replication
# and create ACL tokens and policies
replicationToken:
secretName: null
secretKey: null

# Server, when enabled, configures a server cluster to run. This should
# be disabled if you plan on connecting to a Consul cluster external to
# the Kube cluster.
Expand Down