-
Notifications
You must be signed in to change notification settings - Fork 4
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 RPKI Signed Message Authentication #30
base: main
Are you sure you want to change the base?
Conversation
Wow, I'm embarrassed--I was out on vacation and completely missed this PR. I'm sorry for the late review! Thanks for writing it up. A few questions:
Thanks for the feedback. We would welcome the rewrite, if it is not in the correct format now. We had attempted to rewrite it here: https://www.ietf.org/archive/id/draft-ramseyer-grow-peering-api-05.html#name-endpoints
Interesting, will take a look. Let's open this one separately as an issue to discuss. [EDIT]: Reported in #32 |
The draft looks good to me! I'll merge it in on Wednesday, assuming no further comments. Thanks for the pull request! |
Yes, that should probably be referenced informatively. |
Whoops, one major oversight a friend just pointed out - there was nothing stopping example.com from taking a nonce from example.org and giving it to AS64496 thereby getting access to example.org as AS64496. I've added a binding to the intended origin to fix this. |
are you sure the information actually needs to be inside files over which one hashes? The relying party was the one that issued the nonce-to-be-signed-over, so it can simply check whether the nonce matches the value in the The relying party knows the All in all, the "filenames" are just labels for SHA256 values |
In other words, the names & hashes themselves can be used to communicate between Issuer and RP; no need to |
This is probably poor wording on my part but I never intended the spec to imply |
Perhaps I am misreading the suggested changes, but it seems that an RSC is only requested in 1 direction, right? Why not in both? Both sides of the to-be-established peering relationship have to authenticate each other that they are who they say they are, right? Doing it both ways should help overcome the need to include the origin in the signed payload. |
I can add mutual authentication, but I don't think this eliminates the need to include an audience and subject in both RSCs. |
I am not an RSC expert, but I like the idea of both sides authenticating. It would give us a better guarantee that both the client and server here are legitimate entities. From a security standpoint in other auth methods, the server is implicitly trusted by the client. You could argue that you shouldn't request peering if you don't believe that the server is trustworthy, but I like the idea that, with mutual RSC verification, the client can confirm that the server is trustworthy as well. I defer to you both on the inclusion of the origin/subject in RSCs. |
@TheEnbyperor Would you mind reporting that to https://github.com/peeringdb/peeringdb/issues? I'm happy to as well if you'd prefer. |
@TheEnbyperor @job OK by both of you to merge this in? I'd like to post a new version before the next IETF meeting, if we can manage it. |
Let's hold off on merging this - a case has been made that an improved version of RSC is needed to do the Peering API any justice. |
@job @TheEnbyperor Thanks for the update, I will wait to merge this PR. We plan to post a new version to the IETF on Monday. If this one is ready, I'll include it. If not, we can leave this one out and include it in a later version. Thanks! |
draft-ramseyer-grow-peering-api.md
Outdated
|
||
Authentication to this API is performed with Bearer tokens. Two methods are defined below to obtain a bearer token, | ||
the choice of which is supported is up to operator preference however the authors recommend the use of RPKI Signed | ||
Checklists over reliance on an external OIDC provider. |
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 missed the requirement, why don't we want an OIDC/OAuth2 provider to carry identity information?
Example, wouldn't the operator of a peering API endpoint want to attribute an incoming request not only to a given ASN but also the concrete identity within it? If the concern is using a privacy preserving protocol across peering API instances, wouldn't a regular JWT access token used as bearer with the Oauth2 token endpoint provide such privacy?
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.
External OIDC provider in this case refers to PeeringDB. We're not here to be making standards track documents that rely on a corporate third party outside the control of the IETF.
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.
Nothing of this relies on any corporate party and is all based on IETF documents. The question still stands, why do we need to use a new exchange token format based on RSC, for which we are not documenting distribution of those checklists either, when there is an existing IETF authorization protocol OAuth2?
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.
(in RPKI-parlance) the two sides of the peering relationship are "Relying Parties", and those entities are relying on so-called Trust Anchors which are operated by the 5 RIRs. So there are corporate parties involved: ARIN, APNIC, RIPE NCC, AfriNIC.
Having cryptographic guarantees tied to the RIR-system is a very strong assurance. Stronger than PeeringDB, because in turn PeeringDB itself has dependencies on the RIR databases.
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 totally agree with the notion of proof of holdership via RPKI. What I still don't think I agree with is the notion that we want to introduce a mechanism to sign every request bearer token with an end certificate, specially when we are already implying that those bearer tokens are produced as a result of an OAuth2 flow.
So what is the protection we are seeking by binding RPKI's relying parties to the OAuth2 Authorization Server artifacts (the bearer tokens or a new nonce to acquire them) instead of the OAuth2 Authorization Servers themselves e.g. via their published cryptographic keys (JKCS)?
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 really struggling to understand what you mean.
How this is supposed to work is:
- AS1 wants to talk to AS2's Peering API
- AS1 goes to AS2's OAuth server 'hi I'd like to authenticate'
- AS1 generates and provides an RSM over the nonce from AS2's OAuth server, with attested resources of its AS
- AS2's OAuth server returns a bearer token (details of what's in such a token implementation dependent)
- The Peering API flow can continue with the bearer token as auth, instead of signing every HTTP request with RPKI certificates
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 understanding of OAuth2 is quite limited, but I think the hoped-for user story is that RPKI is mostly (perhaps only) used to bootstrap the relationship.
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’s exactly how it’s intended to 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.
The security section includes a threat model to explictly model the use cases and substantiate why the standard OAuth2, without additional flows, can be extended for the decentralized authorization of a given claim, and for any flow (human-to-API and API-to-API use cases). We have got previous feedback not to extend Oauth2 itself in this draft but do as a separate one.
The draft keeps the usual expectation that API owners authorize access just like any other Oauth2 Resource Server (RS) do today for non-peering APIs they may have. The discovery method of which API endpoint maps to what ASN is deliberately left out too (feedback). A consequence is that it does not prescribe how API consumers or owners mutually authenticate themselves either, after all neither OAuth2 nor RPKI are authentication protocols.
The amended flow using your example:
- Someone or something at AS1 wants to establish peering with AS2 via AS2's Peering API (note AS1 does not have a way to authenticate AS2's API endpoint represents AS2, deliberately omitted in draft).
- AS2 does not need to authenticate AS1, only needs to authorize the request but AS2 still wants to provide AS1 with visibility (via auditable logs/APIs, etc out of scope in draft) as to who did what on their behalf whilst respecting AS1 authentication procedures (user/pass, MFA, machine creds, PKI, etc).
- AS1 goes to AS1 Oauth2 server and acquires a bearer token through whichever grant flows AS1 uses in its own practices (note that Oauth2 expects to have a prior trust with the RS to emit scoped bearer tokens as per standard OAuth2 an this is also deliberately left out of the draft and may possibly be implemented with another RPKI RSC/RSM or AS1 side).
- AS1 presents the token to AS2's peering API.
- AS2's peering API validates the bearer token using the crypto materials of the bearer issuer (JWT/JKCS, etc). This is standard Oauth2.
- As part of this authorization, AS2 also validates that an OAuth2 claim inside the bearer token containing the ASN or the ASN of the API request (left deliberately out) are bound together with the issuer of the bearer token via an RSC. The discovery of where such RSC is store is also left out of the draft and reason why I mention above that using the standard well-known discovery methods (also IETF standard) looks very nice to me.
- Once AS2 has asserted that the bearer token is valid and that the issuer is authorized by the ASN holder, the request proceeds.
Why do I insist on this detached and offline signing method for RSCs? because it decouples API usage from access to the private crypto materials used to create the RSCs and in standard OAuth2 is already not needed today. The detached signature produced in the RSC can follow the same processes ROAs follow today, which in some organizations is not even owned by the same teams.
Sorry if this may be a wall of text but there is a lot of nuance I want to cover to remain as close as possible to how Oauth2 is already in use today with every API, and still introduce the decentralized identifier notion RPKI helps us bring to this space. If you prefer to speak on a call, I'd be more than happy as we've been doing biweekly meetings all the authors to coordinate and address questions and we could cover this there if you'd 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.
Right, I think I understand how you expect it to work now. This is a little more complicated but I'm not entirely opposed to it.
I'd really appreciate joining the biweekly meeting, thanks for the offer. Please send details to qmisell@mpi-inf.mpg.de
draft-ramseyer-grow-peering-api.md
Outdated
`urn:ietf:params:oauth:grant-type:rpki_signed_checklist`. This grant type has two fields: | ||
|
||
* `state`: the opaque state string associated with the nonce | ||
* `rsc`: a Base64 encoded RPKI Signed Checklist over the ASNs the client wishes to be authorized for |
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 am missing what the RSC is signing, the nonce?
The current proposal is avoiding to create an RSC for every bearer token because that signature requires access to the signing CA on delegated RPKI models, or to the hosted RPKI. Isn't this a concern with this approach?
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 see how else this could work securely?
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.
How so? RSC is used to sign something that has a longer lifetime than a single API request, and that something is used to sign requests for a certain period (1h, 1d, 7d). That's how Oauth2 works with JKCS so why not something similar 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.
That's exactly what this OAuth token exchange does. You sign an RSM once with the nonce from the server, exchange that for an OAuth bearer token, and a refresh token to allow continued access.
I'm now happy with this draft, and that its secure against the issues previously raised. |
ASNs are Internet Number Resources assigned by RIRs and that the OAuth2 Authorization Server in use may not be operated | ||
by any of those RIRs, as it is the case of PeeringDB or any other commercial OAuth2 service, JWT claims that contain an | ||
ASN need be proved to be legitimately used by the initiator. This document proposes to attest ASN resource holdership |
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 agree with this statement as it does not invalidate the reasoning already provided with the text it replaces yet removes all the nuance of why OAuth2 is still the vehicle to convey API authorization, not RPKI.
As an peering API resource provider, I want to offer every other ASNs to use whichever means of OAuth2 authorization they already use to now also be able to call my API. This remains on IETF standards based and not forcing any third party (PeeringDB used as an ubiquitous example), because these ASNs already use their own OAuth2 providers (Keycloack, Jensen, MS ADFS, Okta, ForgeRock, ... or any other from a long list). And the use case in the text replaced above allows them to keep doing so when calling my peeringDB API by now adding a mechanism to bind the holdership of the ASN to those authZ infrastuctures in use by every ASN that may be a client of my API.
If we feel that RSCs don't include enough scoping of context and audience to bind ASN to the OAuth2 AS, and the new RSM includes that, perfect! But the paragraph replaced is removing a lot of the nuance of the use case and I want to make sure that a reader will understand the operational scope and expectations of consuming identity for authorization (XY problem).
### Server Metadata | ||
|
||
A server implementing OAuth with RSMs MUST host an OAuth Authorization Server Metadata ({{!RFC8414}}) at | ||
`/.well-known/oauth-authorization-server`. That is if its Peering API base URL is `https://example.com/peering` |
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 agree this approach as we discussed it during calls early on but opted not to go the OAuth2 standardization path in this draft and leave it for cross-wg collaboration with the OAuth2 WG.
Two questions I still have:
- why we think is better to sign with an one-time end certificate every bearer token through a dedicated grant type than the OAuth2 AS/Issuer or JKCS (as they contain crypto keys used for bearer tokens)? The lifecycle an access to the signing CA are not the same.
- seeing a new proposal on RSM that supersede RSC, why don't we standardize the content of this discovery endpoint to contain the RSM signature and scope proposed there?
The PR adds a definition for how RPKI Signed Checklists can be used to authenticate to a Peering API.
I've also reorganized some parts to fit this in, and made the graphs render as SVGs using
aasvg
.Some more general comments on other bits of the draft from reading through it whilst working on it:
The PeeringDB Auth is woefully underspecified, and maybe even broken. I tried to follow it and made a
client_credentials
application owned by my organization. When I used the access token to queryhttps://auth.peeringdb.com/profile/v1
this returned a 500 Internal Server Error so this doesn't appear to be the correct way to go about things. The draft talks about OAuth Authorization Code Exchange grant type, but that is (to my understanding) for interactive login sessions with a human present. This draft defines a machine to machine API so the Client Credentials grant type should be used instead.I'm also not a fan of defining the API only in an OpenAPI document. This is fine to have in addition but were this document to end up as an RFC it should be a self contained document that doesn't include a file in GitHub as a core part of its functionality. I'm happy to rewrite the API definition into a format that fits into an I-D.
Finally I think the example API flow could do with rewriting to make it easier to follow. It's also lacking in BCP14 terms so its unclear what is a hard requirement and what is a recommendation.