Skip to content

Commit

Permalink
Update templates to support license autoload. (hashicorp#952)
Browse files Browse the repository at this point in the history
* Update templates to support license autoload.
- If autload is enabled, we disable the license job and mount the secret
  with the license as a volume mount on the consul server pods, client
pods and snapshot agent pods. Additionally we set the env CONSUL_LICENSE_PATH on these pods.
- When manageSystemACLs is enabled, we mount the secret only on the
  server pods as the consul clients and snapshot agents pods can grab
the license from the server during startup. This is done in order to
ensure only a server restart is required when the license file is
updates and not clients and snapshot agent as well.

* Drop unneccesary 'and' from blocks and fix indentation.
* Support adding enterprise license as an ENV VAR and not a secret
* Support the flag -enterprise-license and update CONTRIBUTING.md
  • Loading branch information
thisisnotashwin authored May 27, 2021
1 parent 44fbdea commit e35a940
Show file tree
Hide file tree
Showing 26 changed files with 419 additions and 92 deletions.
10 changes: 1 addition & 9 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,6 @@ jobs:
echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV
echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV
- run:
name: Create enterprise license secret
command: |
# Create an enterprise license secret in the primary cluster.
# This license is set as a CircleCI project env variable.
# The license expires 15-Oct-2025.
KUBECONFIG=$primary_kubeconfig kubectl create secret generic ent-license --from-literal=key="${CONSUL_ENT_LICENSE}"
# Restore go module cache if there is one
- restore_cache:
keys:
Expand All @@ -285,7 +277,7 @@ jobs:
- run: mkdir -p $TEST_RESULTS

- run-acceptance-tests:
additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enterprise-license-secret-name=ent-license -enterprise-license-secret-key=key -enable-transparent-proxy
additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy

- store_test_results:
path: /tmp/test-results
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,30 @@ IMPROVEMENTS:
* Connect: Enable OpenShift for the connect-injector so that we can support running with transparent
proxy enabled. [[GH-972](https://github.com/hashicorp/consul-helm/pull/972)]

FEATURES:
* License Autoloading [Enterprise]: Consul Enterprise 1.10+ now requires the enterprise license for Consul to be provided as a Kubernetes secret. Once created, the secret can be
configured in the helm chart with the following values:
```yaml
server:
enterpriseLicense:
secretName: <name-of-kubernetes-secret>
secretKey: <name-of-key-whose-value-is-the-license>
```
BUG FIXES:
* OpenShift: support `server.exposeGossipAndRPCPorts`. [[GH-932](https://github.com/hashicorp/consul-helm/issues/932)]

BREAKING CHANGES:
* [Enterprise] For versions of Consul Enterprise <1.10, if the license was provided as a Kubernetes secret, the key `server.enterpriseLicense.enableLicenseAutoload` needs to explicitly
set to false in order for the license job to run.
```yaml
server:
enterpriseLicense:
secretName: <name-of-kubernetes-secret>
secretKey: <name-of-key-whose-value-is-the-license>
enableLicenseAutoload: false
```

## 0.32.0-beta2 (May 6, 2021)

IMPROVEMENTS:
Expand Down
8 changes: 3 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Below is the list of available flags:
-debug-directory
The directory where to write debug information about failed test runs, such as logs and pod definitions. If not provided, a temporary directory will be created by the tests.
-enable-enterprise
If true, the test suite will run tests for enterprise features. Note that some features may require setting the enterprise license flags below.
If true, the test suite will run tests for enterprise features. Note that some features may require setting the enterprise license flag below or the env var CONSUL_ENT_LICENSE.
-enable-multi-cluster
If true, the tests that require multiple Kubernetes clusters will be run. At least one of -secondary-kubeconfig or -secondary-kubecontext is required when this flag is used.
-enable-openshift
Expand All @@ -99,10 +99,8 @@ Below is the list of available flags:
-enable-transparent-proxy
If true, the test suite will run tests with transparent proxy enabled.
This applies only to tests that enable connectInject.
-enterprise-license-secret-name
The name of the Kubernetes secret containing the enterprise license.
-enterprise-license-secret-key
The key of the Kubernetes secret containing the enterprise license.
-enterprise-license
The enterprise license for Consul.
-kubeconfig string
The path to a kubeconfig file. If this is blank, the default kubeconfig path (~/.kube/config) will be used.
-kubecontext string
Expand Down
16 changes: 16 additions & 0 deletions templates/client-daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ spec:
{{- if .Values.global.acls.manageSystemACLs }}
- name: aclconfig
emptyDir: {}
{{- else }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: consul-license
secret:
secretName: {{ .Values.server.enterpriseLicense.secretName }}
{{- end }}
{{- end }}
containers:
- name: consul
Expand Down Expand Up @@ -165,6 +171,10 @@ spec:
name: {{ .Values.global.gossipEncryption.secretName }}
key: {{ .Values.global.gossipEncryption.secretKey }}
{{- end }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload (not .Values.global.acls.manageSystemACLs)) }}
- name: CONSUL_LICENSE_PATH
value: /consul/license/{{ .Values.server.enterpriseLicense.secretKey }}
{{- end }}
{{- if .Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://localhost:8501
Expand Down Expand Up @@ -271,6 +281,12 @@ spec:
{{- if .Values.global.acls.manageSystemACLs }}
- name: aclconfig
mountPath: /consul/aclconfig
{{- else }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: consul-license
mountPath: /consul/license
readOnly: true
{{- end }}
{{- end }}
ports:
{{- if (or (not .Values.global.tls.enabled) (not .Values.global.tls.httpsOnly)) }}
Expand Down
21 changes: 19 additions & 2 deletions templates/client-snapshot-agent-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ spec:
{{- if .Values.client.priorityClassName }}
priorityClassName: {{ .Values.client.priorityClassName | quote }}
{{- end }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.tls.enabled (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey)) }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.tls.enabled (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload)) }}
volumes:
{{- if (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) }}
- name: snapshot-config
Expand All @@ -50,6 +50,12 @@ spec:
{{- if .Values.global.acls.manageSystemACLs }}
- name: aclconfig
emptyDir: {}
{{- else }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: consul-license
secret:
secretName: {{ .Values.server.enterpriseLicense.secretName }}
{{- end }}
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }}
Expand Down Expand Up @@ -94,6 +100,11 @@ spec:
secretKeyRef:
name: "{{ template "consul.fullname" . }}-client-snapshot-agent-acl-token"
key: "token"
{{- else }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: CONSUL_LICENSE_PATH
value: /consul/license/{{ .Values.server.enterpriseLicense.secretKey }}
{{- end }}
{{- end}}
command:
- "/bin/sh"
Expand All @@ -111,7 +122,7 @@ spec:
{{- if .Values.global.acls.manageSystemACLs }}
-config-dir=/consul/aclconfig \
{{- end }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.tls.enabled (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) ) }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.tls.enabled (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload)) }}
volumeMounts:
{{- if (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) }}
- name: snapshot-config
Expand All @@ -121,6 +132,12 @@ spec:
{{- if .Values.global.acls.manageSystemACLs }}
- name: aclconfig
mountPath: /consul/aclconfig
{{- else }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: consul-license
mountPath: /consul/license
readOnly: true
{{- end }}
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt}}
Expand Down
2 changes: 1 addition & 1 deletion templates/enterprise-license-job.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey (not .Values.server.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: batch/v1
kind: Job
metadata:
Expand Down
2 changes: 1 addition & 1 deletion templates/enterprise-license-podsecuritypolicy.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey (not .Values.server.enterpriseLicense.enableLicenseAutoload)) }}
{{- if .Values.global.enablePodSecurityPolicies }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
Expand Down
2 changes: 1 addition & 1 deletion templates/enterprise-license-role.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey (not .Values.server.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
Expand Down
2 changes: 1 addition & 1 deletion templates/enterprise-license-rolebinding.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey (not .Values.server.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
Expand Down
2 changes: 1 addition & 1 deletion templates/enterprise-license-serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey (not .Values.server.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: v1
kind: ServiceAccount
metadata:
Expand Down
14 changes: 14 additions & 0 deletions templates/server-statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ spec:
secret:
secretName: {{ template "consul.fullname" . }}-server-cert
{{- end }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: consul-license
secret:
secretName: {{ .Values.server.enterpriseLicense.secretName }}
{{- end }}
{{- range .Values.server.extraVolumes }}
- name: userconfig-{{ .name }}
{{ .type }}:
Expand Down Expand Up @@ -153,6 +158,10 @@ spec:
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: CONSUL_LICENSE_PATH
value: /consul/license/{{ .Values.server.enterpriseLicense.secretKey }}
{{- end }}
{{- if (and .Values.global.acls.replicationToken.secretName .Values.global.acls.replicationToken.secretKey) }}
- name: ACL_REPLICATION_TOKEN
valueFrom:
Expand Down Expand Up @@ -238,6 +247,11 @@ spec:
mountPath: /consul/tls/server
readOnly: true
{{- end }}
{{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey .Values.server.enterpriseLicense.enableLicenseAutoload) }}
- name: consul-license
mountPath: /consul/license
readOnly: true
{{- end }}
{{- range .Values.server.extraVolumes }}
- name: userconfig-{{ .name }}
readOnly: true
Expand Down
17 changes: 10 additions & 7 deletions test/acceptance/framework/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import (

// HelmChartPath is the path to the helm chart.
// Note: this will need to be changed if this file is moved.
const HelmChartPath = "../../../.."
const (
HelmChartPath = "../../../.."
LicenseSecretName = "license"
LicenseSecretKey = "key"
)

// TestConfig holds configuration for the test suite.
type TestConfig struct {
Expand All @@ -26,9 +30,8 @@ type TestConfig struct {
SecondaryKubeContext string
SecondaryKubeNamespace string

EnableEnterprise bool
EnterpriseLicenseSecretName string
EnterpriseLicenseSecretKey string
EnableEnterprise bool
EnterpriseLicense string

EnableOpenshift bool

Expand Down Expand Up @@ -62,9 +65,9 @@ func (t *TestConfig) HelmValuesFromConfig() (map[string]string, error) {
setIfNotEmpty(helmValues, "global.image", entImage)
}

if t.EnterpriseLicenseSecretName != "" && t.EnterpriseLicenseSecretKey != "" {
setIfNotEmpty(helmValues, "server.enterpriseLicense.secretName", t.EnterpriseLicenseSecretName)
setIfNotEmpty(helmValues, "server.enterpriseLicense.secretKey", t.EnterpriseLicenseSecretKey)
if t.EnterpriseLicense != "" {
setIfNotEmpty(helmValues, "server.enterpriseLicense.secretName", LicenseSecretName)
setIfNotEmpty(helmValues, "server.enterpriseLicense.secretKey", LicenseSecretKey)
}

if t.EnableOpenshift {
Expand Down
18 changes: 4 additions & 14 deletions test/acceptance/framework/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,18 @@ func TestConfig_HelmValuesFromConfig(t *testing.T) {
{
"sets ent license secret",
TestConfig{
EnterpriseLicenseSecretName: "ent-license",
EnterpriseLicenseSecretKey: "key",
EnterpriseLicense: "ent-license",
},
map[string]string{
"server.enterpriseLicense.secretName": "ent-license",
"server.enterpriseLicense.secretName": "license",
"server.enterpriseLicense.secretKey": "key",
"connectInject.transparentProxy.defaultEnabled": "false",
},
},
{
"doesn't set ent license secret when only secret name is set",
"doesn't set ent license if license is empty",
TestConfig{
EnterpriseLicenseSecretName: "ent-license",
},
map[string]string{
"connectInject.transparentProxy.defaultEnabled": "false",
},
},
{
"doesn't set ent license secret when only secret key is set",
TestConfig{
EnterpriseLicenseSecretKey: "key",
EnterpriseLicense: "",
},
map[string]string{
"connectInject.transparentProxy.defaultEnabled": "false",
Expand Down
26 changes: 26 additions & 0 deletions test/acceptance/framework/consul/consul_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ func NewHelmCluster(
configurePodSecurityPolicies(t, ctx.KubernetesClient(t), cfg, ctx.KubectlOptions(t).Namespace)
}

if cfg.EnterpriseLicense != "" {
createOrUpdateLicenseSecret(t, ctx.KubernetesClient(t), cfg, ctx.KubectlOptions(t).Namespace)
}

// Deploy with the following defaults unless helmValues overwrites it.
values := map[string]string{
"server.replicas": "1",
Expand Down Expand Up @@ -433,6 +437,28 @@ func configurePodSecurityPolicies(t *testing.T, client kubernetes.Interface, cfg
})
}

func createOrUpdateLicenseSecret(t *testing.T, client kubernetes.Interface, cfg *config.TestConfig, namespace string) {
_, err := client.CoreV1().Secrets(namespace).Get(context.Background(), config.LicenseSecretName, metav1.GetOptions{})
if errors.IsNotFound(err) {
_, err := client.CoreV1().Secrets(namespace).Create(context.Background(), &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: config.LicenseSecretName,
},
StringData: map[string]string{
config.LicenseSecretKey: cfg.EnterpriseLicense,
},
Type: corev1.SecretTypeOpaque,
}, metav1.CreateOptions{})
require.NoError(t, err)
} else {
require.NoError(t, err)
}

helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() {
client.CoreV1().Secrets(namespace).Delete(context.Background(), config.LicenseSecretName, metav1.DeleteOptions{})
})
}

// mergeValues will merge the values in b with values in a and save in a.
// If there are conflicts, the values in b will overwrite the values in a.
func mergeMaps(a, b map[string]string) {
Expand Down
Loading

0 comments on commit e35a940

Please sign in to comment.