-
Notifications
You must be signed in to change notification settings - Fork 33
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
Introduce local authority api #37
Conversation
|
||
message PushStatusRequest { | ||
// Required. Serial number of the bundle used to sign Agent identity. | ||
string authority_serial = 1; |
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 idea of this serial is to keep on server database the current serial number used for registered agent.
In POC I didn't implement this, so we'll require some changes to access this data (maybe on agent endpoint)
We can avoid this on initial implementation too...
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 think this is a pretty important part of the forced rotation story. Whether it should be introduced now or later, I'm not sure.
I think the comment and name of the field should be updated to reflect the fact that this is the serial number of the bundle copy that the agent currently has. E.g. Serial number of the bundle currently being served by the agent
and current_bundle_serial
. The agent can't know against what bundle serial its SVID was issued if the CA that issued it is present across multiple serial numbers. The serial number also pertains to the bundle, which IMO is a collection of authorities.
Finally, taking this will require changes in other APIs and probably schema, we know that right away agent version will be very useful to have here, so it probably makes sense to throw a version number in here while we're at it 😁
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.
agree, maybe we can create an issue on spire to track all the work about persisting and recovering this information with some APIs
|
||
message PushStatusResponse { | ||
// Keys that are no longer secure and must be rotated. | ||
repeated bytes taintedKeys = 1; |
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 intention here is to return the list of tainted keys (JWT or X.509) so agent can react renewing all affected SVIDs (agent SVID, cached workload X.509 SVIDs, cached JWT SVIDs)
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 are the actual pubkeys themselves? Or pubkey for JWT and CA for X.509? How are they encoded etc? We should capture this information in the comment
Also I think that snake case is standard for these field names?
repeated bytes taintedKeys = 1; | |
repeated bytes tainted_keys = 1; |
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.
for now it is a simple list, and we verify if that key was used for jwt or x509, and taint any of them,
Maybe I overthink this, and we can just create 2 lists and didn't verify if the key was used by only one of our bundles
|
||
message TaintJWTAuthorityRequest { | ||
// The key ID of the local authority to taint | ||
string key_id = 1; |
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 idea is to use "old" authority if no key_id is provided, and X.509 implementation requires a public key...
I'm worried about the difference about both, we may use public key here too..
but our endpoints returns a key_id so I think this can be more natural to use that key id (and our JWT SVIDs has the key ID too)
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 worried about the difference about both
I worry about this too. We should be able to address/name an authority in a single way regardless of what type it is (x.509 or jwt).
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.
ok, so move to taint using public keys on both looks like the correct call, and more natural based in our "Get" responses
|
||
message TaintX509AuthorityRequest { | ||
// The public key of the local authority to taint | ||
bytes public_key = 1; |
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.
an alternative to public key is to use Serial number,
and this proposal has the PushStatus that contains the serial number of the bundle used to sign Agent SVID too,
I was worried about 2 bundles using the same Serial number, but I have the feeling I overkill 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.
We have certificate serial number, and bundle serial number, which are different. For this RPC, I think we don't want bundle serial number, we want the one associated with the CA cert we're trying to taint.
As you noted, JWT has a nice solution because there we already have a key ID. For X.509, I feel it is natural to have this identifier be a function of the key itself rather than the CA certificate, because if we are doing this it's a result of key compromise. For SPIRE I don't think it makes too much of a difference because we always cut a new key when creating a new CA cert, but there's nothing stopping us from changing that behavior in the future.
X.509 does have an "SKID" field (Subject Key Identifier) .. I believe it is required for CA certificates, and that SPIRE sets it. Maybe we can use this SKID or some derivative of it as our key 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.
Making sure that these key IDs are easily typed and copy/pasted will also be important .. they will pop up in CLI commands etc.
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 was what worry me...
a simple key ID is easier to use, than a public key...
but our GET are getting that public keys, and at the same time, it is easy to get the public key from the affected bundle if you have it..
So maybe it is safer to keep public key for now... and as you said nothing prevents to get the same key in multiple bundles (that is why I added a single TaintedKey list to agent, so we can be sure we taint any affected bundle, no matter if it was a JWT or X.509)
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.
Using SKID looks like something possible, of course it will be only for endpoints but internally I think we must keep tainting Public keys, and another endpoints may propagates pubic keys
This commit introduces an API that allows callers to manage key preparation/activation/rotation in SPIRE. It is currently a work in progress. Signed-off-by: Evan Gilman <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
aef980d
to
cf1e886
Compare
Signed-off-by: Marcos Yacob <[email protected]>
// | ||
// The caller must present an active agent X509-SVID, i.e. the X509-SVID | ||
// returned by the AttestAgent or the most recent RenewAgent call. | ||
rpc PushStatus(PushStatusRequest) returns (PushStatusResponse); |
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 I see Push
here, it makes me think that there should be a stream, or that this is being sent from Server to somewhere else synchronously. Maybe something like PostStatus
or ReportStatus
would be clearer?
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.
agree, that sounds like an stream, I'm rename to PostStatus
|
||
message PushStatusRequest { | ||
// Required. Serial number of the bundle used to sign Agent identity. | ||
string authority_serial = 1; |
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 think this is a pretty important part of the forced rotation story. Whether it should be introduced now or later, I'm not sure.
I think the comment and name of the field should be updated to reflect the fact that this is the serial number of the bundle copy that the agent currently has. E.g. Serial number of the bundle currently being served by the agent
and current_bundle_serial
. The agent can't know against what bundle serial its SVID was issued if the CA that issued it is present across multiple serial numbers. The serial number also pertains to the bundle, which IMO is a collection of authorities.
Finally, taking this will require changes in other APIs and probably schema, we know that right away agent version will be very useful to have here, so it probably makes sense to throw a version number in here while we're at it 😁
|
||
message PushStatusResponse { | ||
// Keys that are no longer secure and must be rotated. | ||
repeated bytes taintedKeys = 1; |
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 are the actual pubkeys themselves? Or pubkey for JWT and CA for X.509? How are they encoded etc? We should capture this information in the comment
Also I think that snake case is standard for these field names?
repeated bytes taintedKeys = 1; | |
repeated bytes tainted_keys = 1; |
|
||
message TaintJWTAuthorityRequest { | ||
// The key ID of the local authority to taint | ||
string key_id = 1; |
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 worried about the difference about both
I worry about this too. We should be able to address/name an authority in a single way regardless of what type it is (x.509 or jwt).
|
||
message TaintX509AuthorityRequest { | ||
// The public key of the local authority to taint | ||
bytes public_key = 1; |
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 have certificate serial number, and bundle serial number, which are different. For this RPC, I think we don't want bundle serial number, we want the one associated with the CA cert we're trying to taint.
As you noted, JWT has a nice solution because there we already have a key ID. For X.509, I feel it is natural to have this identifier be a function of the key itself rather than the CA certificate, because if we are doing this it's a result of key compromise. For SPIRE I don't think it makes too much of a difference because we always cut a new key when creating a new CA cert, but there's nothing stopping us from changing that behavior in the future.
X.509 does have an "SKID" field (Subject Key Identifier) .. I believe it is required for CA certificates, and that SPIRE sets it. Maybe we can use this SKID or some derivative of it as our key ID?
|
||
message TaintX509AuthorityRequest { | ||
// The public key of the local authority to taint | ||
bytes public_key = 1; |
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.
Making sure that these key IDs are easily typed and copy/pasted will also be important .. they will pop up in CLI commands etc.
AuthorityState revoked_authority = 1; | ||
} | ||
|
||
message AuthorityState { |
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 think we need key ID as part of this message. An operator will first want to list the authorities, and then will want to taint one, and to taint you need the key 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.
yeah, I was thinking on adding that based is what we decide about taint and revoke, if unify using public key on both or use key_id for one and public key for another one,
based in what we choose here is what we must return
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
…tifier instead of public key Refactor Taint and Revoke JWT authority to use authoirty_id Remove tained keys from Agent.PostStatus, the idea is to use Bundle updates to get the tainted keys. Signed-off-by: Marcos Yacob <[email protected]>
|
||
message PostStatusRequest { | ||
// Required. Serial number of the bundle currently being served by the agent | ||
int64 current_bundle_serial = 1; |
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.
may we use uint64 here?
Signed-off-by: Marcos Yacob <[email 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.
thanks for your patience @MarcosDY ❤️
// Publishes Agent status, relevant information is returned to the agent to keep it | ||
// updated on server changes. |
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: stale comment
AuthorityState prepared_authority = 1; | ||
} | ||
|
||
message ActivateJWTAuthorityRequest {} |
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 don't think it's strictly required right now (maybe it is something we can implement later), but I wonder if we might have an authority ID parameter here in the future, or something that would otherwise allow an operator to re-activate an "old" authority
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 was thinking the same thing, but I was not sure about implementing that on the first version,
I agree it can be useful, and we can implement this, with some changes on code (nothing too bad)
So I'll add it now, and we can discuss on implementation.
// will perform proactive rotations of any key material related to | ||
// the tainted authority. The result of this action will be observed | ||
// cluster-wide. | ||
// It can receive the KeyID of an old JWT authority. |
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: a few of these lines referencing KeyID
that I think should be updated to authority ID
or similar?
// The authority ID of the local X.509 authority to taint. | ||
// This is the subject key identifier, that's calculated by | ||
// doing a SHA-1 hash over the ASN.1 encoding of the public key. |
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: it would be good to be specific about how/where this SKID can be found
// The authority ID of the local X.509 authority to taint. | |
// This is the subject key identifier, that's calculated by | |
// doing a SHA-1 hash over the ASN.1 encoding of the public key. | |
// The authority ID of the local X.509 authority to taint. | |
// This is the X.509 Subject Key Identifier (or SKID) of the | |
// authority's CA certificate, which is calculated by doing a | |
// SHA-1 hash over the ASN.1 encoding of the public key. |
Agree using bundles as a workaround can be useful, in the end we'll be using that after initial connection is done. |
Signed-off-by: Marcos Yacob <[email protected]>
…bundle Signed-off-by: Marcos Yacob <[email 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.
🪨 🥧
thank you Marcos ❤️ looks great
* Introduce an API for key management Introduces an API that allows callers to manage key preparation/activation/rotation/revocation in SPIRE. Update bundle API to propagate tainted keys. Add an endpoint to Agent API to post current agent status. --------- Signed-off-by: Evan Gilman <[email protected]> Signed-off-by: Marcos Yacob <[email protected]> Co-authored-by: Evan Gilman <[email protected]>
* Introduce an API for key management Introduces an API that allows callers to manage key preparation/activation/rotation/revocation in SPIRE. Update bundle API to propagate tainted keys. Add an endpoint to Agent API to post current agent status. --------- Signed-off-by: Evan Gilman <[email protected]> Signed-off-by: Marcos Yacob <[email protected]> Co-authored-by: Evan Gilman <[email protected]>
* Introduce an API for key management Introduces an API that allows callers to manage key preparation/activation/rotation/revocation in SPIRE. Update bundle API to propagate tainted keys. Add an endpoint to Agent API to post current agent status. --------- Signed-off-by: Evan Gilman <[email protected]> Signed-off-by: Marcos Yacob <[email protected]> Co-authored-by: Evan Gilman <[email protected]>
Update Evan's proposal with a the introduction of some required changes found on POC implementation,
and add some simplifications.
Fixes: spiffe/spire#3885