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

[WIP] Support custom max Nomad token name length [supersedes https://github.com/hashicorp/vault/pull/4361] #5117

Merged
merged 10 commits into from
Aug 16, 2018

Conversation

catsby
Copy link
Contributor

@catsby catsby commented Aug 16, 2018

Continuing #4361 to allow users to supply a custom max length for Nomad credential token names. For Nomad version 0.8.3 and before, the max length for the name of the token is 64 characters. With Nomad 0.8.4+, the max length is now 256.

Here we apply a default max length of 256, but allow users to override that with either the max_token_length attribute, or using the NOMAD_MAX_TOKEN_LENGTH environment variable.

NOTE: I've switched the tests to use my fork of the Dockerized Nomad at catsby/nomad on docker hub. The current version is 0.8.3 and I needed 0.8.4 to support the new max length.

Updating the docs now and will push when they are done. Opening this PR now for early review.

@chrishoffman chrishoffman added this to the 0.11 milestone Aug 16, 2018
"max_token_length": &framework.FieldSchema{
Type: framework.TypeInt,
Description: "Max length for generated Nomad tokens",
// Default length is 256 as of
Copy link
Contributor

Choose a reason for hiding this comment

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

I would leave these comments out since they can get out of date pretty quickly.

@@ -96,6 +108,20 @@ func (b *backend) pathConfigAccessWrite(ctx context.Context, req *logical.Reques
conf.Token = token.(string)
}

// max_token_length has default of 256
conf.MaxTokenLength = data.Get("max_token_length").(int)
envMaxTokenLength := os.Getenv("NOMAD_MAX_TOKEN_LENGTH")
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need an environment variable for this value. These are usually reserved for sensitive values or cloud SDK symmetry and most things should just get store directly in barrier storage.

conf, _ := b.readConfigAccess(ctx, req.Storage)
// establish a default
tokenNameLength := maxTokenNameLength
if conf != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should only set the value to the config value if it is greater than zero since that will be the default when deserializing.

// of the pseudo randomized token name is the part that gets trimmed off,
// weaking it's randomness.
if len(tokenName) > tokenNameLength {
tokenName = tokenName[0:tokenNameLength]
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the more idiomatic way of doing this is tokenName[:tokenNameLength]

@@ -23,6 +26,14 @@ func pathConfigAccess(b *backend) *framework.Path {
Type: framework.TypeString,
Description: "Token for API calls",
},

"max_token_length": &framework.FieldSchema{
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this parameter should be named max_token_name_length.

@@ -58,8 +64,11 @@ func (b *backend) pathTokenRead(ctx context.Context, req *logical.Request, d *fr

// Handling nomad maximum token length
// https://github.com/hashicorp/nomad/blob/d9276e22b3b74674996fb548cdb6bc4c70d5b0e4/nomad/structs/structs.go#L115
Copy link
Contributor

Choose a reason for hiding this comment

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

You can remove this comment too.

// randomWithPrefix is used to generate a unique name with a prefix, for
// randomizing names in acceptance tests
func randomWithPrefix(name string) string {
reseed()
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the reseed function for? It is seeding the global rand source, but then you're using a new random source in your Sprintf. You can alternatively also use an existing utility like base62.Random() to generate random strings.

{
title: "ConfigOverride-LongName-envtrim",
roleName: "testlongerrolenametoexceed64charsdddddddddddddddddddddddd",
envLengthString: "16",
Copy link
Contributor

Choose a reason for hiding this comment

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

Some good additional test cases would be this envvar being out of range or not a valid integer.

// https://github.com/hashicorp/nomad/blob/d9276e22b3b74674996fb548cdb6bc4c70d5b0e4/nomad/structs/structs.go#L115
if len(tokenName) > 64 {
tokenName = tokenName[0:63]
// Note: if the given role name is suffeciently long, the UnixNano() portion
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: suffeciently

tokenName = tokenName[0:63]
// Note: if the given role name is suffeciently long, the UnixNano() portion
// of the pseudo randomized token name is the part that gets trimmed off,
// weaking it's randomness.
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: weakening

kalafut
kalafut previously approved these changes Aug 16, 2018
Copy link
Contributor

@kalafut kalafut left a comment

Choose a reason for hiding this comment

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

Minor typos, otherwise LGTM!

@catsby
Copy link
Contributor Author

catsby commented Aug 16, 2018

Test results:

[vault][nomad-token-length](3)$ make testacc TEST=./builtin/logical/nomad TESTARGS="-run=TestBackend"                                                                                                                                                      ✭
==> Checking that code complies with gofmt requirements...
==> Checking that build is using go version >= 1.10...
go generate
VAULT_ACC=1 go test -tags='' ./builtin/logical/nomad -v -run=TestBackend -timeout=45m
=== RUN   TestBackend_config_access
--- PASS: TestBackend_config_access (6.55s)
        backend_test.go:68: [WARN] Generated Master token: cdb66d87-2d6b-6858-ea0a-26eb60158a32
=== RUN   TestBackend_renew_revoke
--- PASS: TestBackend_renew_revoke (7.27s)
        backend_test.go:68: [WARN] Generated Master token: 96eaaa95-c799-5b42-861f-699cee6d3aa8
        backend_test.go:216: [WARN] Generated token: e0a6e441-b8a0-c384-1a02-73e5ce119333 with accessor 145d3551-f5bc-6dbc-9b9c-acc97a15ca15
        backend_test.go:227: [WARN] Verifying that the generated token works...
        backend_test.go:259: [WARN] Verifying that the generated token does not exist...
=== RUN   TestBackend_CredsCreateEnvVar
--- PASS: TestBackend_CredsCreateEnvVar (6.86s)
        backend_test.go:68: [WARN] Generated Master token: bb5a1071-17c1-7dfb-42a8-81019ce1dd39
=== RUN   TestBackend_max_token_name_length
=== RUN   TestBackend_max_token_name_length/Default
=== RUN   TestBackend_max_token_name_length/ConfigOverride
=== RUN   TestBackend_max_token_name_length/ConfigOverride-LongName
=== RUN   TestBackend_max_token_name_length/ConfigOverride-LongName-notrim
--- PASS: TestBackend_max_token_name_length (7.77s)
        backend_test.go:68: [WARN] Generated Master token: ffef4d75-3992-1986-fd8e-e95ef719b93a
    --- PASS: TestBackend_max_token_name_length/Default (0.21s)
    --- PASS: TestBackend_max_token_name_length/ConfigOverride (0.21s)
    --- PASS: TestBackend_max_token_name_length/ConfigOverride-LongName (0.21s)
    --- PASS: TestBackend_max_token_name_length/ConfigOverride-LongName-notrim (0.21s)
PASS
ok      github.com/hashicorp/vault/builtin/logical/nomad        (cached)

"max_token_name_length": &framework.FieldSchema{
Type: framework.TypeInt,
Description: "Max length for name of generated Nomad tokens",
Default: maxTokenNameLength,
Copy link
Contributor

Choose a reason for hiding this comment

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

One more thing here. You should probably not set the default value in the path config. This will mean we will store this value in storage and if we change the default again, they will have an explicit value. You can just omit the Default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Omitting the default will leave a zero value in the struct and be serialized like that. We could change the accessConfig.MaxTokenNameLength to be an *int and use nil there, or just ignore the value when it's zero. I'll assume the later for now

Copy link
Contributor

Choose a reason for hiding this comment

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

Or set it the default to -1 maybe?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the zero value is fine, it is the same as default. I don't think we need to do any int pointer work. Does this api support create vs update? If so, you should be able to handle the case where they don't provide the value and just patch the updated fields.

@chrishoffman chrishoffman merged commit ca1e2a7 into master Aug 16, 2018
@kalafut kalafut deleted the nomad-token-length branch December 7, 2021 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants