Skip to content

Commit

Permalink
feat(security)!: Switch Consul's default_policy to deny (#3402)
Browse files Browse the repository at this point in the history
- turn on Consul's "deny" default_policy
- use more restrict policy rules for Consul's agent token

Note: After this switch is on, Consul's GUI access like http://localhost:8500/ui
will be automatically locked with authentication required.  Any direct accesses
to Consul require a legit token.

Closes: #3256

Signed-off-by: Jim Wang <yutsung.jim.wang@intel.com>
  • Loading branch information
jim-wang-intel authored Apr 27, 2021
1 parent 03ff76b commit 15b4cda
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"acl": {
"enabled": true,
"default_policy": "allow",
"default_policy": "deny",
"enable_token_persistence": true
}
}
13 changes: 12 additions & 1 deletion internal/security/bootstrapper/command/setupacl/acltokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,19 @@ func (c *cmd) readTokenIDBy(bootstrapACLToken BootStrapACLTokenInfo, accessorID
// insertNewAgentToken creates a new Consul token
// it returns the token's ID and error if any error occurs
func (c *cmd) insertNewAgentToken(bootstrapACLToken BootStrapACLTokenInfo) (string, error) {
// get a policy for this agent token to associate with
edgexAgentPolicy, err := c.getOrCreateRegistryPolicy(bootstrapACLToken.SecretID,
"edgex-agent-policy",
edgeXPolicyRules)
if err != nil {
return share.EmptyToken, fmt.Errorf("failed to create edgex agent policy: %v", err)
}

unlimitedDuration := "0s"
createToken := NewCreateRegistryToken("edgex-core-consul agent token", bootstrapACLToken.Policies, true, &unlimitedDuration)
createToken := NewCreateRegistryToken("edgex-core-consul agent token",
[]Policy{
*edgexAgentPolicy,
}, true, &unlimitedDuration)
newTokenInfo, err := c.createNewToken(bootstrapACLToken.SecretID, createToken)
if err != nil {
return share.EmptyToken, fmt.Errorf("failed to insert new edgex agent token: %v", err)
Expand Down
21 changes: 13 additions & 8 deletions internal/security/bootstrapper/command/setupacl/acltokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,15 @@ func TestCreateAgentToken(t *testing.T) {
listTokensRetriesOkResponse bool
createTokenOkResponse bool
readTokenOkResponse bool
policyAlreadyExists bool
expectedErr bool
}{
{"Good:agent token ok response", testBootstrapToken, true, true, true, true, false},
{"Bad:list tokens bad response", testBootstrapToken, false, false, true, true, true},
{"Bad:create token bad response", testBootstrapToken, true, true, false, true, true},
{"Bad:read token bad response", testBootstrapToken, true, true, true, false, true},
{"Bad:empty bootstrap token", BootStrapACLTokenInfo{}, false, false, false, true, true},
{"Good:agent token ok response 1st time", testBootstrapToken, true, true, true, true, false, false},
{"Good:agent token ok response 2nd time or later", testBootstrapToken, true, true, true, true, true, false},
{"Bad:list tokens bad response", testBootstrapToken, false, false, true, true, false, true},
{"Bad:create token bad response", testBootstrapToken, true, true, false, true, false, true},
{"Bad:read token bad response", testBootstrapToken, true, true, true, false, false, true},
{"Bad:empty bootstrap token", BootStrapACLTokenInfo{}, false, false, false, true, false, true},
}

for _, tt := range tests {
Expand All @@ -113,9 +115,12 @@ func TestCreateAgentToken(t *testing.T) {
t.Parallel()
// prepare test
responseOpts := serverOptions{
listTokensOk: test.listTokensOkResponse,
createTokenOk: test.createTokenOkResponse,
readTokenOk: test.readTokenOkResponse,
listTokensOk: test.listTokensOkResponse,
createTokenOk: test.createTokenOkResponse,
readTokenOk: test.readTokenOkResponse,
policyAlreadyExists: test.policyAlreadyExists,
readPolicyByNameOk: true,
createNewPolicyOk: true,
}
testSrv := newRegistryTestServer(responseOpts)
conf := testSrv.getRegistryServerConf(t)
Expand Down
19 changes: 9 additions & 10 deletions snap/local/runtime-helpers/bin/start-consul.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ echo "$(date) deploying the default EdgeX configuration for Consul"
# https://github.com/edgexfoundry/edgex-docs/blob/master/docs_src/design/adr/security/0017-consul-security.md#phase-1
cat > "$SNAP_DATA/consul/config/consul_default.json" <<EOF
{
"node_name": "edgex-core-consul",
"enable_local_script_checks": true,
"disable_update_check": true,
"ports": {
Expand All @@ -24,7 +25,7 @@ if [ "${ENABLE_REGISTRY_ACL}" == "true" ]; then
{
"acl": {
"enabled": true,
"default_policy": "allow",
"default_policy": "deny",
"enable_token_persistence": true
}
}
Expand All @@ -43,12 +44,10 @@ fi
# and not when bootstrapping
# see https://github.com/hashicorp/consul/issues/4380

# to actually test if consul is ready, we simply check to see if consul
# itself shows up in it's service catalog
# also note we don't have a timeout here because we use start-timeout for this
# daemon so systemd will kill us if we take too long waiting for this
CONSUL_URL=http://localhost:8500/v1/catalog/service/consul
until [ -n "$(curl -s $CONSUL_URL | jq -r '. | length')" ] &&
[ "$(curl -s $CONSUL_URL | jq -r '. | length')" -gt "0" ] ; do
sleep 1
done
# Note: we no longer loop trying to connect to consul here as it is already
# taken care by security-consul-bootstrapper, in which it actually waits for
# the consul leader being elected
# see details in https://github.com/edgexfoundry/edgex-go/blob/master/internal/security/bootstrapper/command/setupacl/command.go#L117-L131
# this is to avoid the chicken-and-egg problem when it is running in "deny" policy mode
# as the consul token being required for the service checking API to be able to talk to consul
# in tandem with non-blocking startup of security-consul-bootstrapper

0 comments on commit 15b4cda

Please sign in to comment.