-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Support root issuer generation #14975
Support root issuer generation #14975
Conversation
57f2df8
to
a76ec20
Compare
45b2633
to
240d51c
Compare
- Update all new API endpoints to use the new agreed upon argument names. - issuer_ref & key_ref to refer to existing - issuer_name & key_name for new definitions - Update returned values to always user issuer_id and key_id
- Add utility methods to fetch the issuer_name, issuer_ref, key_name and key_ref arguments from data fields. - Centralize the logic to clean up these inputs and apply various validations to all of them.
4a34597
to
d2f24d7
Compare
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.
Looking good :-) Some minor comments.
- Use the buildPath convention for the function name instead of common...
…suer} methods - PR feedback, move setting up the default configuration references within the import methods instead of within the writeCaBundle method. This should now cover all use cases of us setting up the defaults properly.
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 pretty damn good, super impressed by some of the generate tests, have quite a few nits (though not nearly as many as expected on 721 lines of code)
var keyBits int | ||
|
||
switch exportedStr { | ||
case "internal": |
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.
can we add case "kms" here too?
exportedStr := data.Get("exported").(string) | ||
switch exportedStr { | ||
case "exported": | ||
exported = true | ||
case "internal": | ||
case "existing": |
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.
we switch on the type twice here - here, and then in getKeyTypeAndBitsForRole, could we split that function up instead (to one function for exported, one for internal, one for exsiting, one for kms)?
} | ||
|
||
var pubKey crypto.PublicKey | ||
if kmsRequestedFromFieldData(data) { |
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 looks like part of the case statement? Can we do this, or as a case statement, and not both?
builtin/logical/pki/config_util.go
Outdated
|
||
"github.com/hashicorp/vault/sdk/logical" | ||
) | ||
|
||
func isKeyDefaultSet(ctx context.Context, s logical.Storage) (bool, error) { |
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 doesn't look like it sets the KeyDefault? Key default isn't a set?
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.
Nevermind, I'm an idiot, leaving this as I clearly was confused by it, another person might be too [existsKeyDefault is kinda wordy though]
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.
Definitely not an idiot, it was badly named. Updating to isDefaultKeySet and isDefaultIssuerSet in a hope to make this clearer.
|
||
return fields | ||
} | ||
|
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.
total nit: ordering here (next six functions) is super weird - can all the key be together (and all the issuer together), or pair off NameFields
; RefField
; NameField
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "issuer name already used") | ||
|
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.
what happens if we try generating a root credential with a name which is the Issuer's Key ID? (I'm hoping that this would fail)
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.
Yes that would fail if an end-user were to try to use an existing id for a Name value. Now if they could predict the uuid we would generate in the future though, that would be a bad day...
|
||
require.NotEqual(t, myKeyId1, myKeyId2) | ||
require.Equal(t, myKeyId1, myKeyId3) | ||
} |
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.
key name reusue? issuer name reuse (for non roots?)
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.
Validating that the new CA we generated re-used a key that we had previous generated. Will add a clearer message on this test.
require.NoError(t, err) | ||
require.False(t, existing) | ||
require.Equal(t, key1.PrivateKey, key1_ref1.PrivateKey) | ||
|
||
key1_ref2, existing, err := importKey(ctx, s, key1.PrivateKey) | ||
key1_ref2, existing, err := importKey(ctx, s, key1.PrivateKey, "ignore-me") |
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.
what are we trying to test here? Like, this is a test on a helper function, what are we trying to guarantee to the user?
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.
The "contract" as far as I understand it, is if we determine that the key/issuer already exists no updates occur from the importXXX functions and that the existing flag is set to true. Will add some comments around these tests.
@@ -61,25 +61,17 @@ their identifier and their name (if set). | |||
) | |||
|
|||
func pathGetIssuer(b *backend) *framework.Path { | |||
pattern := "issuer/" + framework.GenericNameRegex("ref") + "(/der|/pem)?" | |||
pattern := "issuer/" + framework.GenericNameRegex("issuer_ref") + "(/der|/pem)?" |
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.
nit: the number of places this is referred to, i would love to see a constant
Manually merging :-) |
Add initial very basic support for creating issuers through the new /issuers/generate/root api.