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

Adds support for agent-side ACL token management via API instead of config files. #3324

Merged
merged 7 commits into from
Jul 26, 2017

Conversation

slackpad
Copy link
Contributor

@slackpad slackpad commented Jul 26, 2017

This is the first phase of secure ACL token introduction where we change the agent-side token management to happen via a new token store instead of the config object directly, and then we add an API to manage the token store on the fly. This lets us use APIs to manage the agent tokens vs. having to place ACL tokens in config files on the agent.

When we do the server side we will cover the other tokens: acl_replication_token and acl_master_token. The acl_replication_token will get added to the token store (we don't expect to add any other things to the token store), and the acl_master_token will be handled with a new /v1/acl/bootstrap API.

@slackpad slackpad requested a review from magiconair July 26, 2017 04:55
@slackpad slackpad added type/enhancement Proposed improvement or new feature theme/acls ACL and token generation labels Jul 26, 2017
}

// UpdateUserToken replaces the current user token in the store.
func (t *TokenStore) UpdateUserToken(userToken string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/userToken/token/

}

// UpdateAgentToken replaces the current agent token in the store.
func (t *TokenStore) UpdateAgentToken(agentToken string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/agentToken/token/

}

// GetTokenForUser returns the best token to use for user operations.
func (t *TokenStore) GetTokenForUser() string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/GetTokenForUser/UserToken/

t.l.RLock()
defer t.l.RUnlock()

if t.userToken != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's redundant. return t.userToken should be sufficient.

}

// GetTokenForAgent returns the best token to use for internal agent operations.
func (t *TokenStore) GetTokenForAgent() string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/GetTokenForAgent/AgentToken/

}
}

func TestTokenStore_UserToken(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you rewrite the previous test as a table driven test then you can roll this test in there as well.

}
}

func TestTokenStore_AgentMasterToken(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test feels a bit verbose. Not sure if a helper func would make it shorter but less readable though. You could add a helper to bail on wrong tokens but I'm not sure it really helps.

isNot := func(toks ...string) {
    for _, tok := range toks {
        if tokens.IsAgentMasterToken(tok) {
            t.Fatalf("token %q is agent master token although it shouldn't be", tok)
        }
    }
}

...
isNot("", "nope")

a := NewTestAgent(t.Name(), TestACLConfig())
defer a.Shutdown()

t.Run("bad method", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test bad json as well? Also, you can write this as a table driven test

tests := []struct {
    name string
    method, urlstr string
    body io.Reader
    code int
    agentToken, masterToken string
}{
    {"bad method", "HEAD", "...", nil, http.StatusMethodNotAllowed, "", "" },
    ... 
}

})
}

func TestAgent_Token_ACLDeny(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roll this one into the previous test if you refactor to table driven?

}
})

t.Run("management token", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works b/c the mgmt token is root set in TestACLConfig? Just curious?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - "root" is the default management token in all our test helpers. That's a little obscure.

@@ -155,7 +149,7 @@ func (m *aclManager) lookupACL(a *Agent, id string) (acl.ACL, error) {
id = anonymousToken
} else if acl.RootACL(id) != nil {
return nil, errors.New(rootDenied)
} else if m.master != nil && id == a.config.ACLAgentMasterToken {
} else if a.tokens.IsAgentMasterToken(id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can agent.tokens be nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No - the token store is created as part of constructing an agent, so it will be there even if ACLs aren't enabled.

@slackpad slackpad merged commit 496b0bc into master Jul 26, 2017
@slackpad slackpad deleted the acl-intro-agent branch July 26, 2017 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme/acls ACL and token generation type/enhancement Proposed improvement or new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants