Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change log entries for ACL refactor #1119

Merged
merged 28 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7a0d64e
Use kube auth method to provision ACL token for the crd controller (#…
kschoche Mar 2, 2022
bcd5481
Support storing bootstrap token in Vault (#1061)
ishustava Mar 4, 2022
d0f1195
Global auth method (#1075)
Mar 7, 2022
14cc65b
Refactor ConnectInject to use authmethods (#1076)
Mar 8, 2022
917e3ca
Sync token acl refactor (#1081)
Mar 8, 2022
c947200
rename the controller flag (#1089)
kschoche Mar 10, 2022
8128685
Refactor Consul API Gateway Controller to use AuthMethod workflow. (#…
Mar 10, 2022
a549f34
Refactor snapshot agent to use new acl authmethod workflow (#1084)
Mar 10, 2022
ca27fc7
Refactor mesh-gateway ACL flow (#1085)
Mar 10, 2022
3989873
Fix flakey server-acl-init tests with retries (#1095)
jmurret Mar 11, 2022
6af4a4d
Update Binding Rule if it exists for the authmethod (#1094)
Mar 15, 2022
559df7a
Enable ACL Client Token (#1093)
jmurret Mar 15, 2022
a1622f2
vault: add support for admin partitions (#1098)
ishustava Mar 15, 2022
61bae2b
Refactor common.Login (#1101)
ishustava Mar 22, 2022
e38036e
Use bootstrap token from vault to validate exec'ing into consul serve…
ishustava Mar 23, 2022
7d488de
Enable terminating gateways to use ACL Auth Method (#1102)
jmurret Mar 23, 2022
e74f16b
Enable snapshot agent configuration to be retrieved from vault (#1113)
jmurret Mar 30, 2022
e2c8c47
Ability to set initial_management token when using k8s secret store. …
jmurret Mar 30, 2022
8eb9902
Enable ingress gateways to use ACL Auth Method (#1118)
jmurret Mar 30, 2022
df6a8db
Removing the gateway type suffix from the naming conventions for term…
jmurret Mar 30, 2022
b75e81c
Merge branch 'main' into acls-refactor-base-branch
jmurret Mar 31, 2022
1eb749d
Enable ACL Client Token (#1093)
jmurret Mar 15, 2022
277845a
Updating changelog for ACLs work.
jmurret Mar 24, 2022
01a2922
Update CHANGELOG.md
jmurret Mar 29, 2022
6c31fbb
Update CHANGELOG.md
jmurret Mar 29, 2022
f71d03d
Update CHANGELOG.md
jmurret Mar 29, 2022
f5c90d2
Adding note about old acl token cleanup. Adding note about configur…
jmurret Mar 30, 2022
63d7655
Update CHANGELOG.md
jmurret Apr 1, 2022
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
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ executors:
- image: docker.mirror.hashicorp.services/cimg/go:1.17.5
environment:
TEST_RESULTS: /tmp/test-results # path to where test results are saved
CONSUL_VERSION: 1.11.2 # Consul's OSS version to use in tests
CONSUL_ENT_VERSION: 1.11.2+ent # Consul's enterprise version to use in tests
CONSUL_VERSION: 1.11.4 # Consul's OSS version to use in tests
CONSUL_ENT_VERSION: 1.11.4+ent # Consul's enterprise version to use in tests

control-plane-path: &control-plane-path control-plane
cli-path: &cli-path cli
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,35 @@
BREAKING CHANGES:
* Helm
* Minimum Kubernetes version supported is 1.19 and now matches what is stated in the `README.md` file. [[GH-1049](https://github.com/hashicorp/consul-k8s/pull/1049)]
* ACLs
* Support Terminating Gateway obtaining an ACL token using a k8s auth method. [GH-1102](https://github.com/hashicorp/consul-k8s/pull/1102)
* **Note**: If you have updated a token with a new policy for a terminating gateway, this will not apply any more as ACL tokens will be ephemeral and are issued to the terminating gateways when the pod is created and destroyed when the pod is stopped. To achieve the same ACL permissions, you will need to assign the policy to the role for the terminating gateway, rather than the token.
* Support Mesh Gateway obtaining an ACL token using a k8s auth method. [GH-1102](https://github.com/hashicorp/consul-k8s/pull/1102)
* **Note**: This is a breaking change if you are using a mesh gateway with mesh federation. To properly configure mesh federation with mesh gateways, you will need to configure the `global.federation.k8sAuthMethodHost` in secondary datacenters to point to the address of the Kubernetes API server of the secondary datacenter. This address must be reachable from the Consul servers in the primary datacenter.
* **General Note on old ACL Tokens**: As of this release, ACL tokens no longer need to be stored as Kubernetes secrets. They will transparently be provisioned by the Kubernetes Auth Method when client and component pods are provisioned and will also be destroyed when client and component pods are destroyed. Old ACL tokens, however, will still exist as Kubernetes secrets and will need to be identified and manually deleted.

FEATURES:
* ACLs: Enable issuing ACL tokens via Consul login with a Kubernetes Auth Method and replace the need for storing ACL tokens as Kubernetes secrets.
* Support CRD controller obtaining an ACL token via using a k8s auth method. [GH-995](https://github.com/hashicorp/consul-k8s/pull/995)
* Support Connect Inject obtaining an ACL token via using a k8s auth method. [GH-1076](https://github.com/hashicorp/consul-k8s/pull/1076)
* Support Sync Catalog obtaining an ACL token via using a k8s auth method. [GH-1081](https://github.com/hashicorp/consul-k8s/pull/1081), [GHT-1077](https://github.com/hashicorp/consul-k8s/pull/1077)
* Support API Gateway controller obtaining an ACL token via using a k8s auth method. [GH-1083](https://github.com/hashicorp/consul-k8s/pull/1083)
* Support Snapshot Agent obtaining an ACL token via using a k8s auth method. [GH-1084](https://github.com/hashicorp/consul-k8s/pull/1084)
* Support Mesh Gateway obtaining an ACL token via using a k8s auth method. [GH-1085](https://github.com/hashicorp/consul-k8s/pull/1085)
* Support Ingress Gateway obtaining an ACL token via using a k8s auth method. [GH-1118](https://github.com/hashicorp/consul-k8s/pull/1118)
* Support Terminating Gateway obtaining an ACL token via using a k8s auth method. [GH-1102](https://github.com/hashicorp/consul-k8s/pull/1102)
* Support Consul Client obtaining an ACL token via using a k8s auth method. [GH-1093](https://github.com/hashicorp/consul-k8s/pull/1093)
* Support issuing global ACL tokens via k8s auth method. [GH-1075](https://github.com/hashicorp/consul-k8s/pull/1075)


IMPROVEMENTS:
* Control Plane
* Upgrade Docker image Alpine version from 3.14 to 3.15. [[GH-1058](https://github.com/hashicorp/consul-k8s/pull/1058)]
* Helm
* API Gateway: Allow controller to read Kubernetes namespaces in order to determine if route is allowed for gateway. [[GH-1092](https://github.com/hashicorp/consul-k8s/pull/1092)]
* Support a pre-configured bootstrap ACL token. [[GH-1125](https://github.com/hashicorp/consul-k8s/pull/1125)]
* Vault
* Enable snapshot agent configuration to be retrieved from vault. [[GH-1113](https://github.com/hashicorp/consul-k8s/pull/1113)]
* CLI
* Enable users to set up secondary clusters with existing federation secrets. [[GH-1126](https://github.com/hashicorp/consul-k8s/pull/1126)]

Expand Down
42 changes: 23 additions & 19 deletions acceptance/framework/consul/helm_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,25 +386,7 @@ 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{})
})
CreateK8sSecret(t, client, cfg, namespace, config.LicenseSecretName, config.LicenseSecretKey, cfg.EnterpriseLicense)
}

// configureSCCs creates RoleBindings that bind the default service account to cluster roles
Expand Down Expand Up @@ -470,3 +452,25 @@ func defaultValues() map[string]string {
}
return values
}

func CreateK8sSecret(t *testing.T, client kubernetes.Interface, cfg *config.TestConfig, namespace, secretName, secretKey, secret string) {
_, err := client.CoreV1().Secrets(namespace).Get(context.Background(), secretName, metav1.GetOptions{})
if errors.IsNotFound(err) {
_, err := client.CoreV1().Secrets(namespace).Create(context.Background(), &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
},
StringData: map[string]string{
secretKey: secret,
},
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(), secretName, metav1.DeleteOptions{})
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ const (
path "consul/data/secret/gossip" {
capabilities = ["read"]
}`
replicationTokenPolicy = `
path "consul/data/secret/replication" {
capabilities = ["read", "update"]

tokenPolicyTemplate = `
path "consul/data/secret/%s" {
capabilities = ["read"]
}`

enterpriseLicensePolicy = `
path "consul/data/secret/enterpriselicense" {
path "consul/data/secret/license" {
capabilities = ["read"]
}`

Expand Down Expand Up @@ -55,10 +56,15 @@ path "/%s/connect_inter/*" {
path "pki/cert/ca" {
capabilities = ["read"]
}`

snapshotAgentPolicy = `
path "consul/data/secret/snapshot-agent-config" {
capabilities = ["read"]
}`
)

// generateGossipSecret generates a random 32 byte secret returned as a base64 encoded string.
func generateGossipSecret() (string, error) {
// GenerateGossipSecret generates a random 32 byte secret returned as a base64 encoded string.
func GenerateGossipSecret() (string, error) {
// This code was copied from Consul's Keygen command:
// https://github.com/hashicorp/consul/blob/d652cc86e3d0322102c2b5e9026c6a60f36c17a5/command/keygen/keygen.go

Expand All @@ -74,16 +80,16 @@ func generateGossipSecret() (string, error) {
return base64.StdEncoding.EncodeToString(key), nil
}

// configureGossipVaultSecret generates a gossip encryption key,
// stores it in vault as a secret and configures a policy to access it.
func configureGossipVaultSecret(t *testing.T, vaultClient *vapi.Client) string {
// ConfigureGossipVaultSecret generates a gossip encryption key,
// stores it in Vault as a secret and configures a policy to access it.
func ConfigureGossipVaultSecret(t *testing.T, vaultClient *vapi.Client) string {
// Create the Vault Policy for the gossip key.
logger.Log(t, "Creating gossip policy")
err := vaultClient.Sys().PutPolicy("consul-gossip", gossipPolicy)
err := vaultClient.Sys().PutPolicy("gossip", gossipPolicy)
require.NoError(t, err)

// Generate the gossip secret.
gossipKey, err := generateGossipSecret()
gossipKey, err := GenerateGossipSecret()
require.NoError(t, err)

// Create the gossip secret.
Expand All @@ -99,71 +105,75 @@ func configureGossipVaultSecret(t *testing.T, vaultClient *vapi.Client) string {
return gossipKey
}

// configureEnterpriseLicenseVaultSecret stores it in vault as a secret and configures a policy to access it.
func configureEnterpriseLicenseVaultSecret(t *testing.T, vaultClient *vapi.Client, cfg *config.TestConfig) {
// ConfigureEnterpriseLicenseVaultSecret stores it in Vault as a secret and configures a policy to access it.
func ConfigureEnterpriseLicenseVaultSecret(t *testing.T, vaultClient *vapi.Client, cfg *config.TestConfig) {
// Create the enterprise license secret.
logger.Log(t, "Creating the Enterprise License secret")
params := map[string]interface{}{
"data": map[string]interface{}{
"enterpriselicense": cfg.EnterpriseLicense,
"license": cfg.EnterpriseLicense,
},
}
_, err := vaultClient.Logical().Write("consul/data/secret/enterpriselicense", params)
_, err := vaultClient.Logical().Write("consul/data/secret/license", params)
require.NoError(t, err)

// Create the Vault Policy for the consul-enterpriselicense.
err = vaultClient.Sys().PutPolicy("consul-enterpriselicense", enterpriseLicensePolicy)
err = vaultClient.Sys().PutPolicy("license", enterpriseLicensePolicy)
require.NoError(t, err)
}

// configureKubernetesAuthRoles configures roles for the Kubernetes auth method
// that will be used by the test Helm chart installation.
func configureKubernetesAuthRoles(t *testing.T, vaultClient *vapi.Client, consulReleaseName, ns, authPath, datacenter string, cfg *config.TestConfig) {
consulClientServiceAccountName := fmt.Sprintf("%s-consul-client", consulReleaseName)
consulServerServiceAccountName := fmt.Sprintf("%s-consul-server", consulReleaseName)
sharedPolicies := "consul-gossip"
if cfg.EnableEnterprise {
sharedPolicies += ",consul-enterpriselicense"
// ConfigureSnapshotAgentSecret stores it in Vault as a secret and configures a policy to access it.
func ConfigureSnapshotAgentSecret(t *testing.T, vaultClient *vapi.Client, cfg *config.TestConfig, config string) {
logger.Log(t, "Creating the Snapshot Agent Config secret in Vault")
params := map[string]interface{}{
"data": map[string]interface{}{
"config": config,
},
}
_, err := vaultClient.Logical().Write("consul/data/secret/snapshot-agent-config", params)
require.NoError(t, err)

err = vaultClient.Sys().PutPolicy("snapshot-agent-config", snapshotAgentPolicy)
require.NoError(t, err)
}

// ConfigureKubernetesAuthRole configures a role in Vault for the component for the Kubernetes auth method
// that will be used by the test Helm chart installation.
func ConfigureKubernetesAuthRole(t *testing.T, vaultClient *vapi.Client, consulReleaseName, ns, authPath, component, policies string) {
componentServiceAccountName := fmt.Sprintf("%s-consul-%s", consulReleaseName, component)

// Create the Auth Roles for consul-server and consul-client.
// Create the Auth Roles for the component.
// Auth roles bind policies to Kubernetes service accounts, which
// then enables the Vault agent init container to call 'vault login'
// with the Kubernetes auth method to obtain a Vault token.
// Please see https://www.vaultproject.io/docs/auth/kubernetes#configuration
// for more details.
logger.Log(t, "Creating the consul-server and consul-client roles")
logger.Logf(t, "Creating the %q", componentServiceAccountName)
params := map[string]interface{}{
"bound_service_account_names": consulClientServiceAccountName,
"bound_service_account_names": componentServiceAccountName,
"bound_service_account_namespaces": ns,
"policies": sharedPolicies,
"policies": policies,
"ttl": "24h",
}
_, err := vaultClient.Logical().Write(fmt.Sprintf("auth/%s/role/consul-client", authPath), params)
require.NoError(t, err)

params = map[string]interface{}{
"bound_service_account_names": consulServerServiceAccountName,
"bound_service_account_namespaces": ns,
"policies": fmt.Sprintf(sharedPolicies+",connect-ca-%s,consul-server-%s,consul-replication-token", datacenter, datacenter),
"ttl": "24h",
}
_, err = vaultClient.Logical().Write(fmt.Sprintf("auth/%s/role/consul-server", authPath), params)
_, err := vaultClient.Logical().Write(fmt.Sprintf("auth/%s/role/%s", authPath, component), params)
require.NoError(t, err)
}

// ConfigureConsulCAKubernetesAuthRole configures a role in Vault that allows all service accounts
// within the installation namespace access to the Consul server CA.
func ConfigureConsulCAKubernetesAuthRole(t *testing.T, vaultClient *vapi.Client, ns, authPath string) {
// Create the CA role that all components will use to fetch the Server CA certs.
params = map[string]interface{}{
params := map[string]interface{}{
"bound_service_account_names": "*",
"bound_service_account_namespaces": ns,
"policies": "consul-ca",
"ttl": "24h",
}
_, err = vaultClient.Logical().Write(fmt.Sprintf("auth/%s/role/consul-ca", authPath), params)
_, err := vaultClient.Logical().Write(fmt.Sprintf("auth/%s/role/consul-ca", authPath), params)
require.NoError(t, err)
}

// configurePKICA generates a CA in Vault.
func configurePKICA(t *testing.T, vaultClient *vapi.Client) {
// ConfigurePKICA generates a CA in Vault.
func ConfigurePKICA(t *testing.T, vaultClient *vapi.Client) {
// Create root CA to issue Consul server certificates and the `consul-server` PKI role.
// See https://learn.hashicorp.com/tutorials/consul/vault-pki-consul-secure-tls.
// Generate the root CA.
Expand All @@ -178,9 +188,9 @@ func configurePKICA(t *testing.T, vaultClient *vapi.Client) {
require.NoError(t, err)
}

// configurePKICertificates configures roles so that Consul server TLS certificates
// ConfigurePKICertificates configures roles in Vault so that Consul server TLS certificates
// can be issued by Vault.
func configurePKICertificates(t *testing.T, vaultClient *vapi.Client, consulReleaseName, ns, datacenter string) string {
func ConfigurePKICertificates(t *testing.T, vaultClient *vapi.Client, consulReleaseName, ns, datacenter string) string {
// Create the Vault PKI Role.
consulServerDNSName := consulReleaseName + "-consul-server"
allowedDomains := fmt.Sprintf("%s.consul,%s,%s.%s,%s.%s.svc", datacenter, consulServerDNSName, consulServerDNSName, ns, consulServerDNSName, ns)
Expand All @@ -193,7 +203,7 @@ func configurePKICertificates(t *testing.T, vaultClient *vapi.Client, consulRele
"max_ttl": "1h",
}

pkiRoleName := fmt.Sprintf("consul-server-%s", datacenter)
pkiRoleName := fmt.Sprintf("server-cert-%s", datacenter)

_, err := vaultClient.Logical().Write(fmt.Sprintf("pki/roles/%s", pkiRoleName), params)
require.NoError(t, err)
Expand All @@ -211,47 +221,35 @@ path %q {
return certificateIssuePath
}

// configureReplicationTokenVaultSecret generates a replication token secret ID,
// stores it in vault as a secret and configures a policy to access it.
func configureReplicationTokenVaultSecret(t *testing.T, vaultClient *vapi.Client, consulReleaseName, ns string, authMethodPaths ...string) string {
// Create the Vault Policy for the replication token.
logger.Log(t, "Creating replication token policy")
err := vaultClient.Sys().PutPolicy("consul-replication-token", replicationTokenPolicy)
// ConfigureACLTokenVaultSecret generates a token secret ID for a given name,
// stores it in Vault as a secret and configures a policy to access it.
func ConfigureACLTokenVaultSecret(t *testing.T, vaultClient *vapi.Client, tokenName string) string {
// Create the Vault Policy for the token.
logger.Logf(t, "Creating %s token policy", tokenName)
policyName := fmt.Sprintf("%s-token", tokenName)
tokenPolicy := fmt.Sprintf(tokenPolicyTemplate, tokenName)
err := vaultClient.Sys().PutPolicy(policyName, tokenPolicy)
require.NoError(t, err)

// Generate the token secret.
token, err := uuid.GenerateUUID()
require.NoError(t, err)

// Create the replication token secret.
logger.Log(t, "Creating the replication token secret")
logger.Logf(t, "Creating the %s token secret", tokenName)
params := map[string]interface{}{
"data": map[string]interface{}{
"replication": token,
"token": token,
},
}
_, err = vaultClient.Logical().Write("consul/data/secret/replication", params)
_, err = vaultClient.Logical().Write(fmt.Sprintf("consul/data/secret/%s", tokenName), params)
require.NoError(t, err)

logger.Log(t, "Creating kubernetes auth role for the server-acl-init job")
serverACLInitSAName := fmt.Sprintf("%s-consul-server-acl-init", consulReleaseName)
params = map[string]interface{}{
"bound_service_account_names": serverACLInitSAName,
"bound_service_account_namespaces": ns,
"policies": "consul-replication-token",
"ttl": "24h",
}

for _, authMethodPath := range authMethodPaths {
_, err := vaultClient.Logical().Write(fmt.Sprintf("auth/%s/role/server-acl-init", authMethodPath), params)
require.NoError(t, err)
}

return token
}

// createConnectCAPolicy creates the Vault Policy for the connect-ca in a given datacenter.
func createConnectCAPolicy(t *testing.T, vaultClient *vapi.Client, datacenter string) {
// CreateConnectCAPolicy creates the Vault Policy for the connect-ca in a given datacenter.
func CreateConnectCAPolicy(t *testing.T, vaultClient *vapi.Client, datacenter string) {
err := vaultClient.Sys().PutPolicy(
fmt.Sprintf("connect-ca-%s", datacenter),
fmt.Sprintf(connectCAPolicyTemplate, datacenter, datacenter))
Expand Down
2 changes: 1 addition & 1 deletion acceptance/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638
github.com/hashicorp/consul/api v1.12.0
github.com/hashicorp/consul/sdk v0.9.0
github.com/hashicorp/go-uuid v1.0.2
github.com/hashicorp/vault/api v1.2.0
github.com/stretchr/testify v1.7.0
gopkg.in/yaml.v2 v2.4.0
Expand Down Expand Up @@ -49,7 +50,6 @@ require (
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/hashicorp/go-version v1.2.0 // indirect
github.com/hashicorp/golang-lru v0.5.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
Expand Down
Loading