-
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
Add the ability to view and list of leases metadata #2650
Conversation
vault/logical_system.go
Outdated
return handleError(err) | ||
} | ||
|
||
return &logical.Response{ |
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.
Check logical.ListResponse
, which does this for you!
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.
Magic :).
vault/logical_system.go
Outdated
func (b *SystemBackend) handleLease( | ||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||
leaseID := data.Get("lease_id").(string) | ||
|
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 have a check for leaseID == ""
here?
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.
Will do.
vault/logical_system.go
Outdated
Data: map[string]interface{}{ | ||
"lease_id": leaseID, | ||
"issue_time": leaseTimes.IssueTime, | ||
"expire_time": nil, |
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 there a reason for setting these 2 fields explicitly to nil
?
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 was really just to serialize to null
in the serializer. I guess omitting would probably be fine.
} | ||
|
||
// Read a key with a LeaseID | ||
req = logical.TestRequest(t, logical.ReadOperation, "secret/foo") |
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.
Generic secret backend does not attach a lease to secrets. I'm not sure if this test would work.
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 does and I was surprised too and this how all the renew and revoke functions are written. I think it might be something in the test harness. Otherwise it isn't straightforward creating a non-token lease without some backing dynamic backend. Maybe pki
with generate_lease
set true
.
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.
When we removed leases from the generic backend in the normal case we still kept the ability to have it issue leases specifically to make testing easier!
} | ||
|
||
// Read a key with a LeaseID | ||
req = logical.TestRequest(t, logical.ReadOperation, "secret/foo") |
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.
Same with this test as well.
vault/logical_system.go
Outdated
}, | ||
|
||
Callbacks: map[logical.Operation]framework.OperationFunc{ | ||
logical.UpdateOperation: b.handleLease, |
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 this be Read operation?
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.
Since lease_id
is sensitive, we determined it made sense to pass lease_id
as a parameter with an update operation. This is currently the preferred method to use in /sys/renew
and /sys/revoke
.
vault/logical_system.go
Outdated
}, | ||
|
||
&framework.Path{ | ||
Pattern: "lease" + framework.OptionalParamRegex("prefix"), |
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.
Instead of making this optional what if the two framework.Paths were merged with both a read op and a list op?
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.
My only concern here was some arbitrary path would not be an "unsupported operation" on update operations because of the optional prefix
.
vault/logical_system.go
Outdated
|
||
func (b *SystemBackend) handleLeaseList( | ||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||
prefix := data.Get("prefix").(string) |
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 you add a check to make sure prefix is not ""
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.
Empty prefix is valid and will list the top level keys.
vault/logical_system.go
Outdated
@@ -63,6 +63,7 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen | |||
"replication/reindex", | |||
"rotate", | |||
"config/auditing/*", | |||
"lease*", |
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.
Also you'll need to update the root paths test after changing this list
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.
Thanks for the head up. I wasn't aware of that test.
vault/logical_system.go
Outdated
@@ -347,7 +371,7 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen | |||
}, | |||
|
|||
&framework.Path{ | |||
Pattern: "revoke-force/(?P<prefix>.+)", | |||
Pattern: "(lease/)?revoke-force" + framework.OptionalParamRegex("prefix"), |
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.
Before this change, I think the prefix
parameter was mandatory and would always be set. If it was not supplied, parsing the path pattern would error out. Now that it is an optional param, missing prefix
I think will not error out. We might want to check explicitly that the required parameters (but optionally set in the URL) are in fact set. This comment applies to all the similar changes below.
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.
You are right. I got a little ambitious in my refactoring. I'll revert out these changes.
vault/logical_system.go
Outdated
"audit", | ||
"audit/*", | ||
"raw/*", | ||
"replication/primary/secondary-token", | ||
"replication/reindex", | ||
"rotate", | ||
"config/auditing/*", | ||
"lease/lookup*", | ||
"lease/revoke-prefix/*", |
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 also add revoke-force/*
and lease/revoke-force/*
to this list?
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 is probably the right thing to do but this would be a change in behavior. I just want to make sure that what we want to do. I will note it in the changelog if we decide to go that route.
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.
If revoke-prefix
is a privileged operation, revoke-force
must be I suppose. If we decide to do this, we should document it in CL as you said, in the docs and as a breaking behavior in the upgrade notes.
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.
Generally we reserve root paths for functions that can be super destructive or super sensitive from a security standpoint. revoke-force
does fit that bill and probably should be privileged, but I wonder if we should reserve that change for 0.8; people will be more likely to expect breaking changes for that release and I don't think this is super high priority.
vault/logical_system.go
Outdated
@@ -1274,6 +1300,56 @@ func (b *SystemBackend) handleTuneWriteCommon( | |||
return nil, nil | |||
} | |||
|
|||
// handleLeasse is use to view the metadata for a given LeaseID |
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.
s/handleLeasse/handleLeaseLookup
vault/logical_system.go
Outdated
"renewable": leaseTimes.renewable(), | ||
}, | ||
} | ||
if !leaseTimes.LastRenewalTime.IsZero() { |
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.
Sorry for circling around on this. On a second thought, the idea of having fields with default values (like you were doing earlier) does seem like a sensible thing to do too. What might be of concern is that this API will not have deterministic number of response fields. That is okay I guess but I am not sure if that is a problem. Bringing this up so we can all agree on this and move forward.
vault/logical_system.go
Outdated
@@ -2429,4 +2505,19 @@ This path responds to the following HTTP methods. | |||
"Lists the headers configured to be audited.", | |||
`Returns a list of headers that have been configured to be audited.`, | |||
}, | |||
|
|||
"lease": { | |||
``, |
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.
Reminder to fill these out.
vault/logical_system.go
Outdated
"audit", | ||
"audit/*", | ||
"raw/*", | ||
"replication/primary/secondary-token", | ||
"replication/reindex", | ||
"rotate", | ||
"config/auditing/*", | ||
"lease/lookup*", |
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 this be leases
not lease
? It's a collection so plural makes sense. (As opposed to a singular system like replication
, e.g. if it was lease-management
, but that's too wordy.)
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 debated this but wanted to match the other paths that had similar functions, like token
and policy
. I am not strongly either way and was just trying for consistency.
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 difference with policy
is that it's supposed to be you acting on a single one, e.g. PUT (write) a policy, GET a policy, and so on. If there were a collection of policy-related APIs under a prefix, having that prefix be policies
instead of policy
would be the right move IMHO.
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.
Also, lease lookup should definitely not be a root path.
vault/expiration.go
Outdated
return false | ||
} | ||
|
||
func (le *leaseEntry) renewableErr() 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.
What is the point of doing this?
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 thought this was a bit confusing and was just consolidating the logic for dealing with the error, which the expiration manager uses, and returning the value of renewable.
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 concerned about people defaulting to use this function when in fact the exact error returned can be useful, e.g. in a debugging/logs context.
vault/logical_system.go
Outdated
resp := &logical.Response{ | ||
Data: map[string]interface{}{ | ||
"id": leaseID, | ||
"creation_time": leaseTimes.IssueTime, |
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 a different type than creation_time
in the token store; there, you set this to issue_time
.
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.
There's a type discrepancy with last_renewal_time
too.
cd314fa
to
54b6bbc
Compare
This should be ready for review again. Notable changes since last full review:
I ended up moving a lot of documentation around. Should we provide landing pages for the old docs locations that point to the new locations? |
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! Please just make sys/leases/revoke-force a sudo operation (and document that) and it's good to go IMHO.
@@ -325,7 +363,7 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen | |||
}, | |||
|
|||
&framework.Path{ | |||
Pattern: "revoke" + framework.OptionalParamRegex("url_lease_id"), | |||
Pattern: "(leases/)?revoke" + framework.OptionalParamRegex("url_lease_id"), |
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.
👍
@@ -1274,6 +1314,61 @@ func (b *SystemBackend) handleTuneWriteCommon( | |||
return nil, nil | |||
} | |||
|
|||
// handleLease is use to view the metadata for a given LeaseID |
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.
s/handleLease/handleLeaseLookup
if leaseTimes == nil { | ||
return logical.ErrorResponse("invalid lease"), logical.ErrInvalidRequest | ||
} | ||
|
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 a comment here explaining why we are setting values to nil beforehand. This will avoid people removing it in future.
}, | ||
|
||
&framework.Path{ | ||
Pattern: "leases/lookup", |
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 we want this to be a root protected path?
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.
@briankassouf Since lease/lookup
doesn't return sensitive information (e.g. the contents of internal data) and you have to know the lease ID ahead of time I don't think it needs to be root. In fact, I am actually thinking we may want to add it to the default
policy. Listing on the other hand does divulge lease IDs which can be used to e.g. renew them, so that should be root protected.
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 that one comment about leases/lookup
being a root path but other that that LGTM!!
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.
LGTM! You might want to update the upgrade notes with the revoke-force change. I think its okay to have a breaking change in 0.7.1 considering that its a very low impact break.
@vishalnayak it's not a breaking change; |
This adds the ability to view and list lease metadata. There are currently no methods to view lease metadata or to list leases by a given prefix. Since there are methods that exist to revoke individual or a prefix of leases and renew individual leases, it makes sense to have endpoints that allow you to view this data as well. The data that will be returned will only be metadata about the lease and will not return any internal lease data.