-
Notifications
You must be signed in to change notification settings - Fork 326
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
Always set server acl tokens #832
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,11 +11,6 @@ import ( | |
"sync" | ||
"time" | ||
|
||
"github.com/hashicorp/consul-k8s/control-plane/consul" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand/common" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" | ||
k8sflags "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" | ||
"github.com/hashicorp/consul/api" | ||
"github.com/hashicorp/go-discover" | ||
"github.com/hashicorp/go-hclog" | ||
|
@@ -24,6 +19,12 @@ import ( | |
k8serrors "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
|
||
"github.com/hashicorp/consul-k8s/control-plane/consul" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand/common" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" | ||
k8sflags "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" | ||
) | ||
|
||
type Command struct { | ||
|
@@ -313,7 +314,6 @@ func (c *Command) Run(args []string) int { | |
scheme = "https" | ||
} | ||
|
||
var updateServerPolicy bool | ||
var bootstrapToken string | ||
|
||
if c.flagBootstrapTokenFile != "" { | ||
|
@@ -340,19 +340,13 @@ func (c *Command) Run(args []string) int { | |
|
||
if bootstrapToken != "" { | ||
c.log.Info(fmt.Sprintf("ACLs already bootstrapped - retrieved bootstrap token from Secret %q", bootTokenSecretName)) | ||
|
||
// Mark that we should update the server ACL policy in case | ||
// there are namespace related config changes. Because of the | ||
// organization of the server token creation code, the policy | ||
// otherwise won't be updated. | ||
updateServerPolicy = true | ||
} else { | ||
c.log.Info("No bootstrap token from previous installation found, continuing on to bootstrapping") | ||
bootstrapToken, err = c.bootstrapServers(serverAddresses, bootTokenSecretName, scheme) | ||
if err != nil { | ||
c.log.Error(err.Error()) | ||
return 1 | ||
} | ||
} | ||
bootstrapToken, err = c.bootstrapServers(serverAddresses, bootstrapToken, bootTokenSecretName, scheme) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now we always call this. |
||
if err != nil { | ||
c.log.Error(err.Error()) | ||
return 1 | ||
} | ||
} | ||
|
||
|
@@ -384,18 +378,6 @@ func (c *Command) Run(args []string) int { | |
c.log.Info("Current datacenter", "datacenter", consulDC, "primaryDC", primaryDC) | ||
isPrimary := consulDC == primaryDC | ||
|
||
// With the addition of namespaces, the ACL policies associated | ||
// with the server tokens may need to be updated if Enterprise Consul | ||
// users upgrade to 1.7+. This updates the policy if the bootstrap | ||
// token had previously existed, which signals a potential config change. | ||
if updateServerPolicy { | ||
_, err = c.setServerPolicy(consulClient) | ||
if err != nil { | ||
c.log.Error("Error updating the server ACL policy", "err", err) | ||
return 1 | ||
} | ||
} | ||
|
||
if c.flagEnablePartitions && c.flagPartitionName == consulDefaultPartition && isPrimary { | ||
// Partition token is local because only the Primary datacenter can have Admin Partitions. | ||
err := c.createLocalACL("partitions", partitionRules, consulDC, isPrimary, consulClient) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,10 +15,6 @@ import ( | |
"testing" | ||
"time" | ||
|
||
"github.com/hashicorp/consul-k8s/control-plane/helper/cert" | ||
"github.com/hashicorp/consul-k8s/control-plane/helper/go-discover/mocks" | ||
"github.com/hashicorp/consul-k8s/control-plane/helper/test" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand/common" | ||
"github.com/hashicorp/consul/api" | ||
"github.com/hashicorp/consul/sdk/freeport" | ||
"github.com/hashicorp/consul/sdk/testutil" | ||
|
@@ -31,6 +27,11 @@ import ( | |
v1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes/fake" | ||
|
||
"github.com/hashicorp/consul-k8s/control-plane/helper/cert" | ||
"github.com/hashicorp/consul-k8s/control-plane/helper/go-discover/mocks" | ||
"github.com/hashicorp/consul-k8s/control-plane/helper/test" | ||
"github.com/hashicorp/consul-k8s/control-plane/subcommand/common" | ||
) | ||
|
||
var ns = "default" | ||
|
@@ -1284,6 +1285,8 @@ func TestRun_NoLeader(t *testing.T) { | |
numACLBootCalls++ | ||
case "/v1/agent/self": | ||
fmt.Fprintln(w, `{"Config": {"Datacenter": "dc1", "PrimaryDatacenter": "dc1"}}`) | ||
case "/v1/acl/tokens": | ||
fmt.Fprintln(w, `[]`) | ||
Comment on lines
+1288
to
+1289
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some of these tests get modified because now we do a token list call to ensure we're not recreating server tokens. |
||
default: | ||
fmt.Fprintln(w, "{}") | ||
} | ||
|
@@ -1342,6 +1345,10 @@ func TestRun_NoLeader(t *testing.T) { | |
"PUT", | ||
"/v1/acl/policy", | ||
}, | ||
{ | ||
"GET", | ||
"/v1/acl/tokens", | ||
}, | ||
{ | ||
"PUT", | ||
"/v1/acl/token", | ||
|
@@ -1496,6 +1503,8 @@ func TestRun_ClientTokensRetry(t *testing.T) { | |
numPolicyCalls++ | ||
case "/v1/agent/self": | ||
fmt.Fprintln(w, `{"Config": {"Datacenter": "dc1", "PrimaryDatacenter": "dc1"}}`) | ||
case "/v1/acl/tokens": | ||
fmt.Fprintln(w, `[]`) | ||
default: | ||
fmt.Fprintln(w, "{}") | ||
} | ||
|
@@ -1530,6 +1539,10 @@ func TestRun_ClientTokensRetry(t *testing.T) { | |
"PUT", | ||
"/v1/acl/policy", | ||
}, | ||
{ | ||
"GET", | ||
"/v1/acl/tokens", | ||
}, | ||
{ | ||
"PUT", | ||
"/v1/acl/token", | ||
|
@@ -1558,8 +1571,8 @@ func TestRun_ClientTokensRetry(t *testing.T) { | |
}, consulAPICalls) | ||
} | ||
|
||
// Test if there is an old bootstrap Secret we assume the servers were | ||
// bootstrapped already and continue on to the next step. | ||
// Test if there is an old bootstrap Secret we still try to create and set | ||
// server tokens. | ||
func TestRun_AlreadyBootstrapped(t *testing.T) { | ||
t.Parallel() | ||
require := require.New(t) | ||
|
@@ -1581,6 +1594,8 @@ func TestRun_AlreadyBootstrapped(t *testing.T) { | |
switch r.URL.Path { | ||
case "/v1/agent/self": | ||
fmt.Fprintln(w, `{"Config": {"Datacenter": "dc1", "PrimaryDatacenter": "dc1"}}`) | ||
case "/v1/acl/tokens": | ||
fmt.Fprintln(w, `[]`) | ||
default: | ||
// Send an empty JSON response with code 200 to all calls. | ||
fmt.Fprintln(w, "{}") | ||
|
@@ -1629,15 +1644,27 @@ func TestRun_AlreadyBootstrapped(t *testing.T) { | |
|
||
// Test that the expected API calls were made. | ||
require.Equal([]APICall{ | ||
// We only expect the calls for creating client tokens | ||
// and updating the server policy. | ||
// We expect calls for updating the server policy, setting server tokens, | ||
// and updating client policy. | ||
{ | ||
"PUT", | ||
"/v1/acl/policy", | ||
}, | ||
{ | ||
"GET", | ||
"/v1/agent/self", | ||
"/v1/acl/tokens", | ||
}, | ||
{ | ||
"PUT", | ||
"/v1/acl/policy", | ||
"/v1/acl/token", | ||
}, | ||
{ | ||
"PUT", | ||
"/v1/agent/token/agent", | ||
}, | ||
{ | ||
"GET", | ||
"/v1/agent/self", | ||
}, | ||
{ | ||
"PUT", | ||
|
@@ -1650,6 +1677,81 @@ func TestRun_AlreadyBootstrapped(t *testing.T) { | |
}, consulAPICalls) | ||
} | ||
|
||
// Test if there is an old bootstrap Secret and the server token exists | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this to test that we don't re-create the server tokens if the token already exists. |
||
// that we don't try and recreate the token. | ||
func TestRun_AlreadyBootstrapped_ServerTokenExists(t *testing.T) { | ||
t.Parallel() | ||
require := require.New(t) | ||
|
||
// First set everything up with ACLs bootstrapped. | ||
bootToken := "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" | ||
k8s, testAgent := completeBootstrappedSetup(t, bootToken) | ||
setUpK8sServiceAccount(t, k8s, ns) | ||
defer testAgent.Stop() | ||
k8s.CoreV1().Secrets(ns).Create(context.Background(), &v1.Secret{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: resourcePrefix + "-bootstrap-acl-token", | ||
}, | ||
Data: map[string][]byte{ | ||
"token": []byte(bootToken), | ||
}, | ||
}, metav1.CreateOptions{}) | ||
|
||
consulClient, err := api.NewClient(&api.Config{ | ||
Address: testAgent.HTTPAddr, | ||
Token: bootToken, | ||
}) | ||
require.NoError(err) | ||
ui := cli.NewMockUi() | ||
cmd := Command{ | ||
UI: ui, | ||
clientset: k8s, | ||
} | ||
|
||
// Create the server policy and token _before_ we run the command. | ||
agentPolicyRules, err := cmd.agentRules() | ||
require.NoError(err) | ||
policy, _, err := consulClient.ACL().PolicyCreate(&api.ACLPolicy{ | ||
Name: "agent-token", | ||
Description: "Agent Token Policy", | ||
Rules: agentPolicyRules, | ||
}, nil) | ||
require.NoError(err) | ||
_, _, err = consulClient.ACL().TokenCreate(&api.ACLToken{ | ||
Description: fmt.Sprintf("Server Token for %s", strings.Split(testAgent.HTTPAddr, ":")[0]), | ||
Policies: []*api.ACLTokenPolicyLink{ | ||
{ | ||
Name: policy.Name, | ||
}, | ||
}, | ||
}, nil) | ||
require.NoError(err) | ||
|
||
// Run the command. | ||
cmdArgs := []string{ | ||
"-timeout=1m", | ||
"-k8s-namespace", ns, | ||
"-server-address", strings.Split(testAgent.HTTPAddr, ":")[0], | ||
"-server-port", strings.Split(testAgent.HTTPAddr, ":")[1], | ||
"-resource-prefix", resourcePrefix, | ||
} | ||
|
||
responseCode := cmd.Run(cmdArgs) | ||
require.Equal(0, responseCode, ui.ErrorWriter.String()) | ||
|
||
// Check that only one server token exists, i.e. it didn't create an | ||
// extra token. | ||
tokens, _, err := consulClient.ACL().TokenList(nil) | ||
require.NoError(err) | ||
count := 0 | ||
for _, token := range tokens { | ||
if len(token.Policies) == 1 && token.Policies[0].Name == policy.Name { | ||
count++ | ||
} | ||
} | ||
require.Equal(1, count) | ||
} | ||
|
||
// Test if there is a provided bootstrap we skip bootstrapping of the servers | ||
// and continue on to the next step. | ||
func TestRun_SkipBootstrapping_WhenBootstrapTokenIsProvided(t *testing.T) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer needed. Previously this would be set when there already exists a kube bootstrap secret to ensure that we update the server policy. Now we call
c.bootstrapServers
, even when the kube secret exists. That function then callssetServerTokens
that then callsc.setServerPolicy(consulClient)
. So we don't need this codepath anymore.