-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Add keyring http endpoints #2509
Conversation
@@ -79,3 +99,61 @@ func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) err | |||
resp.Body.Close() | |||
return nil | |||
} | |||
|
|||
// KeyringInstall is used to install a new gossip encryption key into the cluster | |||
func (op *Operator) KeyringInstall(key string) 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.
Should these functions take an argument for overriding the ACL token used? Some of the other api functions do, but some don't so I wasn't sure.
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.
No, but I'd q *QueryOptions
and q *WriteOptions
arguments to these methods and get the token from there. It kind of sucks that there's some extra fields in those that don't matter here, but that's kind of the common signature for these. We could add a helper that errors if there are things that are not supported, but we can just document for now.
if response.Error != "" { | ||
return nil, fmt.Errorf(response.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.
Is just returning the first error fine for these KeyringResponses? I thought about using multierror but it didn't seem useful because you'd just get a bunch of duplicate errors ("key must be 16/24/32 length" and the like)
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.
Yeah that makes sense. We could dedup them into a multierror maybe so you can tell if you have a handful of problems vs. having to run several times, since a short list would be super useful.
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.
Looks good - put a few comments in the review!
if response.Error != "" { | ||
return nil, fmt.Errorf(response.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.
Yeah that makes sense. We could dedup them into a multierror maybe so you can tell if you have a handful of problems vs. having to run several times, since a short list would be super useful.
@@ -291,6 +291,10 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) { | |||
s.handleFuncMetrics("/v1/kv/", s.wrap(s.KVSEndpoint)) | |||
s.handleFuncMetrics("/v1/operator/raft/configuration", s.wrap(s.OperatorRaftConfiguration)) | |||
s.handleFuncMetrics("/v1/operator/raft/peer", s.wrap(s.OperatorRaftPeer)) | |||
s.handleFuncMetrics("/v1/operator/keyring/install", s.wrap(s.OperatorKeyringInstall)) |
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.
I'm thinking we can get rid of these /verb suffixes in the URLs and use HTTP verbs for everything:
GET /v1/operator/keyring -> list keys
POST /v1/operator/keyring -> Install a key
PUT /v1/operator/keyring -> use a key
DELETE /v1/operator/keyring -> remove a key
Still not super REST-y since we don't have the key in the path, but looks more REST-y and keeps the API a little smaller.
return nil, nil | ||
} | ||
|
||
var args structs.KeyringRequest |
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 has extra fields that we wouldn't ever want to plumb directly (there's currently a panic()
in the internal endpoint handler that we should change to an error if the Op isn't understood), so I'd make a simple unexported struct (define in here is fine) and a local string for the token
and use those. There's stuff we don't use in this big struct so it's confusing to accept that here.
t.Fatalf("err: %s", err) | ||
} | ||
|
||
for _, response := range listResponse.Responses { |
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.
Length check here?
t.Fatalf("err: %v", !ok) | ||
} | ||
|
||
// Check that we get both a LAN and WAN response, and that they both only |
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.
Didn't check a WAN vs. LAN (prolly count and compare at the end).
Available in Consul 0.7.2 and later, the keyring remove endpoint supports the | ||
`PUT` method. | ||
|
||
#### PUT Method |
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 a DELETE.
@@ -43,6 +43,26 @@ type RaftConfiguration struct { | |||
Index uint64 | |||
} | |||
|
|||
// KeyringOpts is used for performing Keyring operations | |||
type KeyringOpts struct { |
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.
I'd make this an unexported struct keyringRequest
since it's not part of your interface for the actual API functions.
@@ -79,3 +99,61 @@ func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) err | |||
resp.Body.Close() | |||
return nil | |||
} | |||
|
|||
// KeyringInstall is used to install a new gossip encryption key into the cluster | |||
func (op *Operator) KeyringInstall(key string) 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.
No, but I'd q *QueryOptions
and q *WriteOptions
arguments to these methods and get the token from there. It kind of sucks that there's some extra fields in those that don't matter here, but that's kind of the common signature for these. We could add a helper that errors if there are things that are not supported, but we can just document for now.
|
||
A JSON body is returned that looks like this: | ||
|
||
```javascript |
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.
It might be nice to add an endpoint here (or in the API client based on this) that summarizes the keys that have been successfully installed everywhere and are safe to switch to. Probably not in this pass, but it would be nice to know as an operator in a very high level way "this key is good to go".
Addressed comments, should be ready for another look |
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.
Just a couple trivial things and this is good to commit.
@@ -43,6 +43,26 @@ type RaftConfiguration struct { | |||
Index uint64 | |||
} | |||
|
|||
// keyringRequest is used for performing Keyring operations | |||
type keyringRequest struct { | |||
Key string `json:",omitempty"` |
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.
Do you need the omitempty
for anything?
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.
I can't remember why I added this - it's the only field in the struct and we only ever decode to it, so there's no reason for it to be in there
t.Fatalf("bad: %d", len(responses)) | ||
} | ||
|
||
// WAN |
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.
Is this order deterministic?
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, it's consistent; here we call executeKeyringOp with wan = true
, then with wan = false
, and in this test we always get back the wan reply first.
into the cluster. There is more information on gossip encryption available | ||
[here](/docs/agent/encryption.html#gossip-encryption). | ||
|
||
The register endpoint expects a JSON request body to be PUT. The request |
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.
These descriptions all say PUT
- need to update with the right verbs.
LGTM |
First pass at adding the keyring endpoints for #2502