diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index cd5ad9ddd2..83558e9bd4 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -66,6 +66,10 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace + {{- if .Values.global.acls.manageSystemACLs }} + - name: CONSUL_HTTP_TOKEN_FILE + value: "/consul/login/acl-token" + {{- end }} {{- if .Values.global.tls.enabled }} - name: CONSUL_CACERT value: /consul/tls/ca/tls.crt @@ -80,12 +84,6 @@ spec: secretKeyRef: name: {{ .Values.connectInject.aclInjectToken.secretName }} key: {{ .Values.connectInject.aclInjectToken.secretKey }} - {{- else if .Values.global.acls.manageSystemACLs }} - - name: CONSUL_HTTP_TOKEN - valueFrom: - secretKeyRef: - name: "{{ template "consul.fullname" . }}-connect-inject-acl-token" - key: "token" {{- end }} - name: CONSUL_HTTP_ADDR {{- if .Values.global.tls.enabled }} @@ -216,6 +214,16 @@ spec: -default-consul-sidecar-cpu-request={{ $consulSidecarResources.requests.cpu }} \ {{- end }} {{- end }} + {{- if .Values.global.acls.manageSystemACLs }} + lifecycle: + preStop: + exec: + command: + - "/bin/sh" + - "-ec" + - | + consul-k8s-control-plane consul-logout + {{- end }} startupProbe: httpGet: path: /readyz/ready @@ -246,6 +254,9 @@ spec: - name: certs mountPath: /etc/connect-injector/certs readOnly: true + - mountPath: /consul/login + name: consul-data + readOnly: true {{- if .Values.global.tls.enabled }} {{- if .Values.global.tls.enableAutoEncrypt }} - name: consul-auto-encrypt-ca-cert @@ -264,6 +275,9 @@ spec: secret: defaultMode: 420 secretName: {{ template "consul.fullname" . }}-connect-inject-webhook-cert + - name: consul-data + emptyDir: + medium: "Memory" {{- if .Values.global.tls.enabled }} {{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }} - name: consul-ca-cert @@ -285,16 +299,57 @@ spec: {{- end }} {{- if or (and .Values.global.acls.manageSystemACLs) (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }} initContainers: + {{- if and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt }} + {{- include "consul.getAutoEncryptClientCA" . | nindent 6 }} + {{- end }} {{- if .Values.global.acls.manageSystemACLs }} - - name: injector-acl-init + - name: connect-injector-acl-init + env: + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- if .Values.global.tls.enabled }} + - name: CONSUL_CACERT + value: /consul/tls/ca/tls.crt + {{- end }} + - name: CONSUL_HTTP_ADDR + {{- if .Values.global.tls.enabled }} + value: https://$(HOST_IP):8501 + {{- else }} + value: http://$(HOST_IP):8500 + {{- end }} image: {{ .Values.global.imageK8S }} + volumeMounts: + - mountPath: /consul/login + name: consul-data + readOnly: false + {{- if .Values.global.tls.enabled }} + {{- if .Values.global.tls.enableAutoEncrypt }} + - name: consul-auto-encrypt-ca-cert + {{- else }} + - name: consul-ca-cert + {{- end }} + mountPath: /consul/tls/ca + readOnly: true + {{- end }} command: - "/bin/sh" - "-ec" - | consul-k8s-control-plane acl-init \ - -secret-name="{{ template "consul.fullname" . }}-connect-inject-acl-token" \ - -k8s-namespace={{ .Release.Namespace }} + -component-name=connect-injector \ + {{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter .Values.global.enableConsulNamespaces }} + -acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method-{{ .Values.global.datacenter }} \ + -primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \ + {{- else }} + -acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method \ + {{- end }} + {{- if .Values.global.adminPartitions.enabled }} + -partition={{ .Values.global.adminPartitions.name }} \ + {{- end }} + -log-level={{ default .Values.global.logLevel .Values.controller.logLevel }} \ + -log-json={{ .Values.global.logJSON }} resources: requests: memory: "25Mi" @@ -303,9 +358,6 @@ spec: memory: "25Mi" cpu: "50m" {{- end }} - {{- if (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }} - {{- include "consul.getAutoEncryptClientCA" . | nindent 6 }} - {{- end }} {{- end }} {{- if .Values.connectInject.priorityClassName }} priorityClassName: {{ .Values.connectInject.priorityClassName | quote }} diff --git a/charts/consul/templates/controller-deployment.yaml b/charts/consul/templates/controller-deployment.yaml index 5c6f65529b..29e5aa5bda 100644 --- a/charts/consul/templates/controller-deployment.yaml +++ b/charts/consul/templates/controller-deployment.yaml @@ -47,7 +47,7 @@ spec: spec: {{- if or .Values.global.acls.manageSystemACLs (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }} initContainers: - {{- if (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }} + {{- if and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt }} {{- include "consul.getAutoEncryptClientCA" . | nindent 6 }} {{- end }} {{- if .Values.global.acls.manageSystemACLs }} @@ -97,7 +97,7 @@ spec: -partition={{ .Values.global.adminPartitions.name }} \ {{- end }} -log-level={{ default .Values.global.logLevel .Values.controller.logLevel }} \ - -log-json={{ .Values.global.logJSON }} \ + -log-json={{ .Values.global.logJSON }} resources: requests: memory: "25Mi" diff --git a/charts/consul/templates/server-acl-init-job.yaml b/charts/consul/templates/server-acl-init-job.yaml index a6c26a0656..53514e959e 100644 --- a/charts/consul/templates/server-acl-init-job.yaml +++ b/charts/consul/templates/server-acl-init-job.yaml @@ -183,7 +183,7 @@ spec: {{- end }} {{- if (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled)) }} - -create-inject-token=true \ + -create-inject-policy=true \ {{- if and .Values.externalServers.enabled .Values.externalServers.k8sAuthMethodHost }} -auth-method-host={{ .Values.externalServers.k8sAuthMethodHost }} \ {{- end }} diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index a3da403005..4c6576bfbd 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -926,40 +926,188 @@ EOF #-------------------------------------------------------------------- # global.acls.manageSystemACLs -@test "connectInject/Deployment: CONSUL_HTTP_TOKEN env variable created when global.acls.manageSystemACLs=true" { +@test "connectInject/Deployment: consul-logout preStop hook is added when ACLs are enabled" { cd `chart_dir` local object=$(helm template \ -s templates/connect-inject-deployment.yaml \ --set 'connectInject.enabled=true' \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq '[.spec.template.spec.containers[0].env[].name] ' | tee /dev/stderr) + yq '[.spec.template.spec.containers[0].lifecycle.preStop.exec.command[2]] | any(contains("consul-k8s-control-plane consul-logout"))' | tee /dev/stderr) + + [ "${object}" = "true" ] +} + +@test "connectInject/Deployment: CONSUL_HTTP_TOKEN_FILE is not set when acls are disabled" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq '[.spec.template.spec.containers[0].env[0].name] | any(contains("CONSUL_HTTP_TOKEN_FILE"))' | tee /dev/stderr) + [ "${actual}" = "false" ] +} + +@test "connectInject/Deployment: CONSUL_HTTP_TOKEN_FILE is set when acls are enabled" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq '[.spec.template.spec.containers[0].env[1].name] | any(contains("CONSUL_HTTP_TOKEN_FILE"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: init container is created when global.acls.manageSystemACLs=true and has correct command and environment with tls disabled" { + cd `chart_dir` + local object=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.initContainers[0]' | tee /dev/stderr) local actual=$(echo $object | - yq 'any(contains("CONSUL_HTTP_TOKEN"))' | tee /dev/stderr) + yq -r '.name' | tee /dev/stderr) + [ "${actual}" = "connect-injector-acl-init" ] + + local actual=$(echo $object | + yq -r '.command | any(contains("consul-k8s-control-plane acl-init"))' | tee /dev/stderr) [ "${actual}" = "true" ] local actual=$(echo $object | - yq 'map(select(test("CONSUL_HTTP_TOKEN"))) | length' | tee /dev/stderr) - [ "${actual}" = "1" ] + yq '[.env[1].name] | any(contains("CONSUL_HTTP_ADDR"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[1].value] | any(contains("http://$(HOST_IP):8500"))' | tee /dev/stderr) + echo $actual + [ "${actual}" = "true" ] } -@test "connectInject/Deployment: init container is created when global.acls.manageSystemACLs=true" { +@test "connectInject/Deployment: init container is created when global.acls.manageSystemACLs=true and has correct command and environment with tls enabled" { cd `chart_dir` local object=$(helm template \ -s templates/connect-inject-deployment.yaml \ --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq '.spec.template.spec.initContainers[0]' | tee /dev/stderr) + yq '.spec.template.spec.initContainers[] | select(.name == "connect-injector-acl-init")' | tee /dev/stderr) local actual=$(echo $object | - yq -r '.name' | tee /dev/stderr) - [ "${actual}" = "injector-acl-init" ] + yq -r '.command | any(contains("consul-k8s-control-plane acl-init"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[1].name] | any(contains("CONSUL_CACERT"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[2].name] | any(contains("CONSUL_HTTP_ADDR"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[2].value] | any(contains("https://$(HOST_IP):8501"))' | tee /dev/stderr) + echo $actual + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '.volumeMounts[1] | any(contains("consul-ca-cert"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: init container is created when global.acls.manageSystemACLs=true and has correct command with Partitions enabled" { + cd `chart_dir` + local object=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.adminPartitions.name=default' \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.initContainers[] | select(.name == "connect-injector-acl-init")' | tee /dev/stderr) + + local actual=$(echo $object | + yq -r '.command | any(contains("consul-k8s-control-plane acl-init"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq -r '.command | any(contains("-acl-auth-method=RELEASE-NAME-consul-k8s-component-auth-method"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq -r '.command | any(contains("-partition=default"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[1].name] | any(contains("CONSUL_CACERT"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[2].name] | any(contains("CONSUL_HTTP_ADDR"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[2].value] | any(contains("https://$(HOST_IP):8501"))' | tee /dev/stderr) + echo $actual + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '.volumeMounts[1] | any(contains("consul-ca-cert"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: init container is created when global.acls.manageSystemACLs=true and has correct command and environment with tls enabled and autoencrypt enabled" { + cd `chart_dir` + local object=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.tls.enableAutoEncrypt=true' \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.initContainers[] | select(.name == "connect-injector-acl-init")' | tee /dev/stderr) local actual=$(echo $object | yq -r '.command | any(contains("consul-k8s-control-plane acl-init"))' | tee /dev/stderr) [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[1].name] | any(contains("CONSUL_CACERT"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[2].name] | any(contains("CONSUL_HTTP_ADDR"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '[.env[2].value] | any(contains("https://$(HOST_IP):8501"))' | tee /dev/stderr) + echo $actual + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq '.volumeMounts[1] | any(contains("consul-auto-encrypt-ca-cert"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: auto-encrypt init container is created and is the first init-container when global.acls.manageSystemACLs=true and has correct command and environment with tls enabled and autoencrypt enabled" { + cd `chart_dir` + local object=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.tls.enableAutoEncrypt=true' \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.initContainers[0]' | tee /dev/stderr) + + local actual=$(echo $object | + yq -r '.name' | tee /dev/stderr) + [ "${actual}" = "get-auto-encrypt-client-ca" ] } @test "connectInject/Deployment: cross namespace policy is not added when global.acls.manageSystemACLs=false" { diff --git a/charts/consul/test/unit/server-acl-init-job.bats b/charts/consul/test/unit/server-acl-init-job.bats index 73dd3f6432..43f2178ae1 100644 --- a/charts/consul/test/unit/server-acl-init-job.bats +++ b/charts/consul/test/unit/server-acl-init-job.bats @@ -961,7 +961,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "false" ] local actual=$(echo $object | @@ -1008,7 +1008,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "false" ] local actual=$(echo $object | @@ -1051,7 +1051,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "false" ] local actual=$(echo $object | @@ -1095,7 +1095,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "false" ] local actual=$(echo $object | @@ -1140,7 +1140,7 @@ load _helpers [ "${actual}" = "true" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "false" ] local actual=$(echo $object | @@ -1187,7 +1187,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "false" ] local actual=$(echo $object | @@ -1230,7 +1230,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "true" ] local actual=$(echo $object | @@ -1274,7 +1274,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "true" ] local actual=$(echo $object | @@ -1319,7 +1319,7 @@ load _helpers [ "${actual}" = "false" ] local actual=$(echo $object | - yq 'any(contains("create-inject-token"))' | tee /dev/stderr) + yq 'any(contains("create-inject-policy"))' | tee /dev/stderr) [ "${actual}" = "true" ] local actual=$(echo $object | diff --git a/control-plane/subcommand/server-acl-init/command.go b/control-plane/subcommand/server-acl-init/command.go index 6c5e0f3e4b..3b8ab8d95f 100644 --- a/control-plane/subcommand/server-acl-init/command.go +++ b/control-plane/subcommand/server-acl-init/command.go @@ -45,7 +45,7 @@ type Command struct { flagCreateSyncToken bool flagSyncConsulNodeName string - flagCreateInjectToken bool + flagCreateInjectPolicy bool flagAuthMethodHost string flagBindingRuleSelector string @@ -139,11 +139,10 @@ func (c *Command) init() { var unused bool c.flags.BoolVar(&unused, "create-inject-namespace-token", false, "Toggle for creating a connect injector token. Only required when namespaces are enabled. "+ - "Deprecated: set -enable-namespaces and -create-inject-token instead.") - - c.flags.BoolVar(&c.flagCreateInjectToken, "create-inject-auth-method", false, - "Toggle for creating a connect inject auth method. Deprecated: use -create-inject-token instead.") - c.flags.BoolVar(&c.flagCreateInjectToken, "create-inject-token", false, + "Deprecated: set -enable-namespaces and -create-inject-policy instead.") + c.flags.BoolVar(&c.flagCreateInjectPolicy, "create-inject-auth-method", false, + "Toggle for creating a connect inject auth method. Deprecated: use -create-inject-policy instead.") + c.flags.BoolVar(&c.flagCreateInjectPolicy, "create-inject-policy", false, "Toggle for creating a connect inject auth method and an ACL token.") c.flags.StringVar(&c.flagAuthMethodHost, "auth-method-host", "", "Kubernetes Host config parameter for the auth method."+ @@ -512,9 +511,9 @@ func (c *Command) Run(args []string) int { } } - if c.flagCreateInjectToken { - authMethodName := c.withPrefix("k8s-auth-method") - err := c.configureConnectInjectAuthMethod(consulClient, authMethodName) + if c.flagCreateInjectPolicy { + connectAuthMethodName := c.withPrefix("k8s-auth-method") + err := c.configureConnectInjectAuthMethod(consulClient, connectAuthMethodName) if err != nil { c.log.Error(err.Error()) return 1 @@ -527,14 +526,22 @@ func (c *Command) Run(args []string) int { return 1 } + serviceAccountName := c.withPrefix("connect-injector") + componentAuthMethodName := localComponentAuthMethodName + // If namespaces are enabled, the policy and token need to be global // to be allowed to create namespaces. if c.flagEnableNamespaces { - err = c.createGlobalACL("connect-inject", injectRules, consulDC, primary, consulClient) + // Create the controller ACL Policy, Role and BindingRule but do not issue any ACLTokens or create Kube Secrets. + // ConnectInjector token must be global when namespaces are enabled. This means secondary datacenters need + // a token that is known by the primary datacenters. + if !primary { + componentAuthMethodName = globalComponentAuthMethodName + } + err = c.createACLPolicyRoleAndBindingRule("connect-inject", injectRules, consulDC, primaryDC, globalToken, primary, componentAuthMethodName, serviceAccountName, consulClient) } else { - err = c.createLocalACL("connect-inject", injectRules, consulDC, primary, consulClient) + err = c.createACLPolicyRoleAndBindingRule("connect-inject", injectRules, consulDC, primaryDC, localToken, primary, componentAuthMethodName, serviceAccountName, consulClient) } - if err != nil { c.log.Error(err.Error()) return 1 @@ -905,7 +912,7 @@ func (c *Command) createAnonymousPolicy(isPrimary bool) bool { // on cross-dc API calls. The cross-dc API calls thus use the anonymous // token. Cross-dc API calls are needed by the Connect proxies to talk // cross-dc. - (c.flagCreateInjectToken && c.flagFederation)) + (c.flagCreateInjectPolicy && c.flagFederation)) } func (c *Command) validateFlags() error { @@ -947,11 +954,13 @@ func (c *Command) validateFlags() error { return nil } -const consulDefaultNamespace = "default" -const consulDefaultPartition = "default" -const globalToken = true -const synopsis = "Initialize ACLs on Consul servers and other components." -const help = ` +const ( + consulDefaultNamespace = "default" + consulDefaultPartition = "default" + globalToken = true + localToken = false + synopsis = "Initialize ACLs on Consul servers and other components." + help = ` Usage: consul-k8s-control-plane server-acl-init [options] Bootstraps servers with ACLs and creates policies and ACL tokens for other @@ -960,3 +969,4 @@ Usage: consul-k8s-control-plane server-acl-init [options] and safe to run multiple times. ` +) diff --git a/control-plane/subcommand/server-acl-init/command_ent_test.go b/control-plane/subcommand/server-acl-init/command_ent_test.go index 6247194c3d..22dc4877ba 100644 --- a/control-plane/subcommand/server-acl-init/command_ent_test.go +++ b/control-plane/subcommand/server-acl-init/command_ent_test.go @@ -43,7 +43,7 @@ func TestRun_ConnectInject_SingleDestinationNamespace(t *testing.T) { "-server-port=" + strings.Split(testAgent.HTTPAddr, ":")[1], "-resource-prefix=" + resourcePrefix, "-k8s-namespace=" + ns, - "-create-inject-token", + "-create-inject-policy", "-enable-partitions", "-partition=default", "-enable-namespaces", @@ -171,7 +171,7 @@ func TestRun_ConnectInject_NamespaceMirroring(t *testing.T) { "-server-port=" + strings.Split(testAgent.HTTPAddr, ":")[1], "-resource-prefix=" + resourcePrefix, "-k8s-namespace=" + ns, - "-create-inject-token", + "-create-inject-policy", "-enable-partitions", "-partition=default", "-enable-namespaces", @@ -287,7 +287,7 @@ func TestRun_ACLPolicyUpdates(t *testing.T) { "-allow-dns", "-create-mesh-gateway-token", "-create-sync-token", - "-create-inject-token", + "-create-inject-policy", "-create-snapshot-agent-token", "-create-enterprise-license-token", "-ingress-gateway-name=gw", @@ -332,7 +332,7 @@ func TestRun_ACLPolicyUpdates(t *testing.T) { "anothergw-ingress-gateway-token", "gw-terminating-gateway-token", "anothergw-terminating-gateway-token", - "connect-inject-token", + "connect-inject-policy", "controller-policy", } policies, _, err := consul.ACL().PolicyList(nil) @@ -376,7 +376,7 @@ func TestRun_ACLPolicyUpdates(t *testing.T) { "anonymous-token-policy", "client-token", "catalog-sync-token", - "connect-inject-token", + "connect-inject-policy", "mesh-gateway-token", "client-snapshot-agent-token", "enterprise-license-token", @@ -598,7 +598,7 @@ func TestRun_ConnectInject_Updates(t *testing.T) { "-k8s-namespace=" + ns, "-enable-partitions", "-partition=default", - "-create-inject-token", + "-create-inject-policy", } // First run. NOTE: we don't assert anything here since we've @@ -681,13 +681,6 @@ func TestRun_TokensWithNamespacesEnabled(t *testing.T) { SecretNames: []string{resourcePrefix + "-catalog-sync-acl-token"}, LocalToken: false, }, - "connect-inject-token": { - TokenFlags: []string{"-create-inject-token", "-enable-namespaces"}, - PolicyNames: []string{"connect-inject-token"}, - PolicyDCs: nil, - SecretNames: []string{resourcePrefix + "-connect-inject-acl-token"}, - LocalToken: false, - }, "enterprise-license token": { TokenFlags: []string{"-create-enterprise-license-token"}, PolicyNames: []string{"enterprise-license-token"}, @@ -742,20 +735,6 @@ func TestRun_TokensWithNamespacesEnabled(t *testing.T) { SecretNames: []string{resourcePrefix + "-acl-replication-acl-token"}, LocalToken: false, }, - "inject token with namespaces (deprecated)": { - TokenFlags: []string{"-create-inject-auth-method", "-enable-namespaces", "-create-inject-namespace-token"}, - PolicyNames: []string{"connect-inject-token"}, - PolicyDCs: nil, - SecretNames: []string{resourcePrefix + "-connect-inject-acl-token"}, - LocalToken: false, - }, - "inject token and namespaces": { - TokenFlags: []string{"-create-inject-token", "-enable-namespaces"}, - PolicyNames: []string{"connect-inject-token"}, - PolicyDCs: nil, - SecretNames: []string{resourcePrefix + "-connect-inject-acl-token"}, - LocalToken: false, - }, "partitions token": { TokenFlags: []string{"-enable-partitions", "-partition=default"}, PolicyNames: []string{"partitions-token"}, @@ -1100,6 +1079,13 @@ func TestRun_PrimaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEnab Roles: []string{resourcePrefix + "-controller-acl-role"}, Namespace: ns, }, + { + TestName: "Connect Inject", + TokenFlags: []string{"-create-inject-policy"}, + PolicyNames: []string{"connect-inject-policy"}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role"}, + Namespace: ns, + }, } for _, c := range cases { t.Run(c.TestName, func(t *testing.T) { @@ -1116,6 +1102,7 @@ func TestRun_PrimaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEnab cmdArgs := append([]string{ "-timeout=500ms", "-resource-prefix=" + resourcePrefix, + "-enable-namespaces", "-k8s-namespace=" + c.Namespace, "-enable-namespaces", "-consul-inject-destination-namespace", c.Namespace, @@ -1148,8 +1135,8 @@ func TestRun_PrimaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEnab // Check that the Role references the Policy. found := false - for x := range role.Policies { - if role.Policies[x].Name == policy.Name { + for j := range role.Policies { + if role.Policies[j].Name == policy.Name { found = true break } @@ -1161,8 +1148,8 @@ func TestRun_PrimaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEnab require.NoError(t, err) require.NotNil(t, rb) found = false - for x := range rb { - if rb[x].BindName == c.Roles[i] { + for j := range rb { + if rb[j].BindName == c.Roles[i] { found = true break } @@ -1199,6 +1186,13 @@ func TestRun_SecondaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEn Roles: []string{resourcePrefix + "-controller-acl-role-" + secondaryDatacenter}, Namespace: ns, }, + { + TestName: "Connect Inject", + TokenFlags: []string{"-create-inject-policy"}, + PolicyNames: []string{"connect-inject-policy-" + secondaryDatacenter}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role-" + secondaryDatacenter}, + Namespace: ns, + }, } for _, c := range cases { t.Run(c.TestName, func(t *testing.T) { @@ -1218,6 +1212,7 @@ func TestRun_SecondaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEn "-federation", "-timeout=1m", "-resource-prefix=" + resourcePrefix, + "-enable-namespaces", "-k8s-namespace=" + c.Namespace, "-enable-namespaces", "-consul-inject-destination-namespace", c.Namespace, @@ -1245,8 +1240,8 @@ func TestRun_SecondaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEn // Check that the Role references the Policy. found := false - for x := range role.Policies { - if role.Policies[x].Name == policy.Name { + for j := range role.Policies { + if role.Policies[j].Name == policy.Name { found = true break } @@ -1258,8 +1253,8 @@ func TestRun_SecondaryDatacenter_PoliciesAndBindingRulesForACLLogin_NamespacesEn require.NoError(t, err) require.NotNil(t, rb) found = false - for x := range rb { - if rb[x].BindName == c.Roles[i] { + for j := range rb { + if rb[j].BindName == c.Roles[i] { found = true break } @@ -1288,6 +1283,12 @@ func TestRun_NamespaceEnabled_ValidateLoginToken_PrimaryDatacenter(t *testing.T) Roles: []string{resourcePrefix + "-controller-acl-role"}, Namespace: ns, }, + { + ComponentName: "connect-injector", + TokenFlags: []string{"-create-inject-policy"}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role"}, + Namespace: ns, + }, } for _, c := range cases { t.Run(c.ComponentName, func(t *testing.T) { @@ -1319,6 +1320,7 @@ func TestRun_NamespaceEnabled_ValidateLoginToken_PrimaryDatacenter(t *testing.T) cmdArgs := append([]string{ "-timeout=500ms", "-resource-prefix=" + resourcePrefix, + "-enable-namespaces", "-k8s-namespace=" + c.Namespace, "-enable-namespaces", "-consul-inject-destination-namespace", c.Namespace, @@ -1368,6 +1370,12 @@ func TestRun_NamespaceEnabled_ValidateLoginToken_SecondaryDatacenter(t *testing. Roles: []string{resourcePrefix + "-controller-acl-role-dc2"}, Namespace: ns, }, + { + ComponentName: "connect-injector", + TokenFlags: []string{"-create-inject-policy"}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role-dc2"}, + Namespace: ns, + }, } for _, c := range cases { t.Run(c.ComponentName, func(t *testing.T) { @@ -1402,6 +1410,7 @@ func TestRun_NamespaceEnabled_ValidateLoginToken_SecondaryDatacenter(t *testing. "-federation", "-timeout=1m", "-resource-prefix=" + resourcePrefix, + "-enable-namespaces", "-k8s-namespace=" + c.Namespace, "-enable-namespaces", "-consul-inject-destination-namespace", c.Namespace, diff --git a/control-plane/subcommand/server-acl-init/command_test.go b/control-plane/subcommand/server-acl-init/command_test.go index 58969ba13f..6c86aa1ed1 100644 --- a/control-plane/subcommand/server-acl-init/command_test.go +++ b/control-plane/subcommand/server-acl-init/command_test.go @@ -248,14 +248,6 @@ func TestRun_TokensPrimaryDC(t *testing.T) { SecretNames: []string{resourcePrefix + "-acl-replication-acl-token"}, LocalToken: false, }, - { - TestName: "Endpoints Controller ACL token", - TokenFlags: []string{"-create-inject-token"}, - PolicyNames: []string{"connect-inject-token"}, - PolicyDCs: []string{"dc1"}, - SecretNames: []string{resourcePrefix + "-connect-inject-acl-token"}, - LocalToken: true, - }, } for _, c := range cases { t.Run(c.TestName, func(t *testing.T) { @@ -474,14 +466,6 @@ func TestRun_TokensReplicatedDC(t *testing.T) { resourcePrefix + "-another-gateway-terminating-gateway-acl-token"}, LocalToken: true, }, - { - TestName: "Endpoints controller ACL token", - TokenFlags: []string{"-create-inject-token"}, - PolicyNames: []string{"connect-inject-token-dc2"}, - PolicyDCs: []string{"dc2"}, - SecretNames: []string{resourcePrefix + "-connect-inject-acl-token"}, - LocalToken: true, - }, } for _, c := range cases { t.Run(c.TestName, func(t *testing.T) { @@ -552,12 +536,6 @@ func TestRun_TokensWithProvidedBootstrapToken(t *testing.T) { PolicyNames: []string{"client-token"}, SecretNames: []string{resourcePrefix + "-client-acl-token"}, }, - { - TestName: "Endpoints controller ACL token", - TokenFlags: []string{"-create-inject-token"}, - PolicyNames: []string{"connect-inject-token"}, - SecretNames: []string{resourcePrefix + "-connect-inject-acl-token"}, - }, { TestName: "Sync token", TokenFlags: []string{"-create-sync-token"}, @@ -715,12 +693,12 @@ func TestRun_AnonymousTokenPolicy(t *testing.T) { ExpAnonymousPolicy: false, }, "auth method, primary dc, no replication": { - Flags: []string{"-create-inject-token"}, + Flags: []string{"-create-inject-policy"}, SecondaryDC: false, ExpAnonymousPolicy: false, }, "auth method, secondary dc": { - Flags: []string{"-create-inject-token"}, + Flags: []string{"-create-inject-policy"}, SecondaryDC: true, ExpAnonymousPolicy: false, }, @@ -821,8 +799,8 @@ func TestRun_ConnectInjectAuthMethod(t *testing.T) { flags []string expectedHost string }{ - "-create-inject-token flag": { - flags: []string{"-create-inject-token"}, + "-create-inject-policy flag": { + flags: []string{"-create-inject-policy"}, expectedHost: "https://kubernetes.default.svc", }, "-create-inject-auth-method flag": { @@ -838,7 +816,7 @@ func TestRun_ConnectInjectAuthMethod(t *testing.T) { }, "-auth-method-host flag": { flags: []string{ - "-create-inject-token", + "-create-inject-policy", "-auth-method-host=https://my-kube.com", }, expectedHost: "https://my-kube.com", @@ -917,7 +895,7 @@ func TestRun_ConnectInjectAuthMethodUpdates(t *testing.T) { t.Parallel() // Test with deprecated -create-inject-auth-method flag. - cases := []string{"-create-inject-auth-method", "-create-inject-token"} + cases := []string{"-create-inject-auth-method", "-create-inject-policy"} for _, flag := range cases { t.Run(flag, func(t *testing.T) { @@ -1009,7 +987,7 @@ func TestRun_BindingRuleUpdates(tt *testing.T) { tt.Parallel() // Test with deprecated -create-inject-auth-method flag. - cases := []string{"-create-inject-auth-method", "-create-inject-token"} + cases := []string{"-create-inject-auth-method", "-create-inject-policy"} for _, flag := range cases { tt.Run(flag, func(t *testing.T) { k8s, testSvr := completeSetup(t) @@ -2241,6 +2219,12 @@ func TestRun_PoliciesAndBindingRulesForACLLogin_PrimaryDatacenter(t *testing.T) PolicyNames: []string{"controller-policy"}, Roles: []string{resourcePrefix + "-controller-acl-role"}, }, + { + TestName: "Connect Inject", + TokenFlags: []string{"-create-inject-policy"}, + PolicyNames: []string{"connect-inject-policy"}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role"}, + }, } for _, c := range cases { t.Run(c.TestName, func(t *testing.T) { @@ -2286,8 +2270,8 @@ func TestRun_PoliciesAndBindingRulesForACLLogin_PrimaryDatacenter(t *testing.T) // Check that the Role references the Policy. found := false - for x := range role.Policies { - if role.Policies[x].Name == policy.Name { + for j := range role.Policies { + if role.Policies[j].Name == policy.Name { found = true break } @@ -2299,8 +2283,8 @@ func TestRun_PoliciesAndBindingRulesForACLLogin_PrimaryDatacenter(t *testing.T) require.NoError(t, err) require.NotNil(t, rb) found = false - for x := range rb { - if rb[x].BindName == c.Roles[i] { + for j := range rb { + if rb[j].BindName == c.Roles[i] { found = true break } @@ -2325,16 +2309,25 @@ func TestRun_PoliciesAndBindingRulesACLLogin_SecondaryDatacenter(t *testing.T) { primaryDatacenter = "dc1" ) cases := []struct { - TestName string - TokenFlags []string - PolicyNames []string - Roles []string + TestName string + TokenFlags []string + PolicyNames []string + Roles []string + GlobalAuthMethod bool }{ { - TestName: "Controller", - TokenFlags: []string{"-create-controller-token"}, - PolicyNames: []string{"controller-policy-" + secondaryDatacenter}, - Roles: []string{resourcePrefix + "-controller-acl-role-" + secondaryDatacenter}, + TestName: "Controller", + TokenFlags: []string{"-create-controller-token"}, + PolicyNames: []string{"controller-policy-" + secondaryDatacenter}, + Roles: []string{resourcePrefix + "-controller-acl-role-" + secondaryDatacenter}, + GlobalAuthMethod: true, + }, + { + TestName: "Connect Inject", + TokenFlags: []string{"-create-inject-policy"}, + PolicyNames: []string{"connect-inject-policy-" + secondaryDatacenter}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role-" + secondaryDatacenter}, + GlobalAuthMethod: false, }, } for _, c := range cases { @@ -2365,23 +2358,28 @@ func TestRun_PoliciesAndBindingRulesACLLogin_SecondaryDatacenter(t *testing.T) { responseCode := cmd.Run(cmdArgs) require.Equal(t, 0, responseCode, ui.ErrorWriter.String()) + datacenter := "" + if c.GlobalAuthMethod { + datacenter = primaryDatacenter + } + // Check that the Role exists + has correct Policy and is associated with a BindingRule. for i := range c.Roles { // Check that the Policy exists. - policy, _, err := consul.ACL().PolicyReadByName(c.PolicyNames[i], &api.QueryOptions{Datacenter: primaryDatacenter}) + policy, _, err := consul.ACL().PolicyReadByName(c.PolicyNames[i], &api.QueryOptions{Datacenter: datacenter}) require.NoError(t, err) require.NotNil(t, policy) // Check that the Role exists. - role, _, err := consul.ACL().RoleReadByName(c.Roles[i], &api.QueryOptions{Datacenter: primaryDatacenter}) + role, _, err := consul.ACL().RoleReadByName(c.Roles[i], &api.QueryOptions{Datacenter: datacenter}) require.NoError(t, err) require.NotNil(t, role) // Check that the Role references the Policy. found := false - for x := range role.Policies { - if role.Policies[x].Name == policy.Name { + for j := range role.Policies { + if role.Policies[j].Name == policy.Name { found = true break } @@ -2389,12 +2387,16 @@ func TestRun_PoliciesAndBindingRulesACLLogin_SecondaryDatacenter(t *testing.T) { require.True(t, found) // Check that there exists a BindingRule that references this Role. - rb, _, err := consul.ACL().BindingRuleList(fmt.Sprintf("release-name-%s-%s", componentAuthMethod, secondaryDatacenter), &api.QueryOptions{Datacenter: primaryDatacenter}) + authMethodName := fmt.Sprintf("release-name-%s", componentAuthMethod) + if c.GlobalAuthMethod { + authMethodName = fmt.Sprintf("release-name-%s-%s", componentAuthMethod, secondaryDatacenter) + } + rb, _, err := consul.ACL().BindingRuleList(authMethodName, &api.QueryOptions{Datacenter: datacenter}) require.NoError(t, err) require.NotNil(t, rb) found = false - for x := range rb { - if rb[x].BindName == c.Roles[i] { + for j := range rb { + if rb[j].BindName == c.Roles[i] { found = true break } @@ -2421,6 +2423,11 @@ func TestRun_ValidateLoginToken_PrimaryDatacenter(t *testing.T) { TokenFlags: []string{"-create-controller-token"}, Roles: []string{resourcePrefix + "-controller-acl-role"}, }, + { + ComponentName: "connect-injector", + TokenFlags: []string{"-create-inject-policy"}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role"}, + }, } for _, c := range cases { t.Run(c.ComponentName, func(t *testing.T) { @@ -2488,21 +2495,32 @@ func TestRun_ValidateLoginToken_SecondaryDatacenter(t *testing.T) { t.Parallel() cases := []struct { - ComponentName string - TokenFlags []string - Roles []string + ComponentName string + TokenFlags []string + Roles []string + GlobalAuthMethod bool }{ { - ComponentName: "controller", - TokenFlags: []string{"-create-controller-token"}, - Roles: []string{resourcePrefix + "-controller-acl-role-dc2"}, + ComponentName: "controller", + TokenFlags: []string{"-create-controller-token"}, + Roles: []string{resourcePrefix + "-controller-acl-role-dc2"}, + GlobalAuthMethod: true, + }, + { + ComponentName: "connect-injector", + TokenFlags: []string{"-create-inject-policy"}, + Roles: []string{resourcePrefix + "-connect-injector-acl-role-dc2"}, + GlobalAuthMethod: false, }, } for _, c := range cases { t.Run(c.ComponentName, func(t *testing.T) { bootToken := "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" tokenFile := common.WriteTempFile(t, bootToken) - authMethodName := "release-name-" + componentAuthMethod + "-dc2" + authMethodName := "release-name-" + componentAuthMethod + if c.GlobalAuthMethod { + authMethodName = "release-name-" + componentAuthMethod + "-dc2" + } serviceAccountName := fmt.Sprintf("%s-%s", resourcePrefix, c.ComponentName) k8s, _, consulHTTPAddr, cleanup := mockReplicatedSetup(t, bootToken) @@ -2541,9 +2559,13 @@ func TestRun_ValidateLoginToken_SecondaryDatacenter(t *testing.T) { responseCode := cmd.Run(cmdArgs) require.Equal(t, 0, responseCode, ui.ErrorWriter.String()) + datacenter := "" + if c.GlobalAuthMethod { + datacenter = "dc1" + } client, err := api.NewClient(&api.Config{ Address: consulHTTPAddr, - Datacenter: "dc1", + Datacenter: datacenter, }) require.NoError(t, err)