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

Commit

Permalink
Merge pull request #368 from hashicorp/wan-fed-acls
Browse files Browse the repository at this point in the history
Support ACL replication.
  • Loading branch information
lkysow committed Mar 16, 2020
2 parents 90cbb96 + 5fd93fc commit c24f5ff
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 12 deletions.
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 \
{{- 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

0 comments on commit c24f5ff

Please sign in to comment.