Thank you, Damian. This concludes the vote for KIP 255. The vote passes with three binding + 1 votes, from Rajini, Jun, and Damian, and three non-binding +1 votes, from Mickael, Manikumar, and myself.
I have marked the KIP as "Accepted". The pull request is available at https://github.com/apache/kafka/pull/4994 and is squashed/rebased onto trunk. Ron On Mon, May 21, 2018 at 8:25 AM, Damian Guy <damian....@gmail.com> wrote: > +1 (binding) > > Thanks > > On Mon, 21 May 2018 at 04:59 Ron Dagostino <rndg...@gmail.com> wrote: > > > Hi Committers. One more binding affirmative vote is required if KIP 255 > > is to have a chance of being included in the 2.0.0 release. Please vote > > today. > > > > Ron > > > > > On May 18, 2018, at 9:27 PM, Ron Dagostino <rndg...@gmail.com> wrote: > > > > > > Hi committers. KIP 255 still needs 1 more binding vote. Currently > > there are two binding + 1 votes, from Rajini and Jun, and three > non-binding > > +1 votes, from Mickael, Manikumar, and myself. > > > > > > Please vote by the Monday deadline. > > > > > > Ron > > > > > >> On Thu, May 17, 2018 at 10:59 AM, Ron Dagostino <rndg...@gmail.com> > > wrote: > > >> Hi Jun. I've updated the KIP to add a new section titled "Summary for > > Production Use" that includes this information along with a consolidated > > set of references to the applicable specifications. Thanks for the > > questions. > > >> > > >> *We still need another binding vote* (currently there are two binding > + > > 1 votes, from Rajini and Jun, and three non-binding +1 votes, from > Mickael, > > Manikumar, and myself). > > >> > > >> Please vote before the May 22nd KIP Freeze deadline so this KIP can be > > included in the 2.0.0 release. > > >> > > >> A pull request is available and includes additional commits reflecting > > initial review comments: https://github.com/apache/kafka/pull/4994 > > >> > > >> Ron > > >> > > >>> On Wed, May 16, 2018 at 8:09 PM, Jun Rao <j...@confluent.io> wrote: > > >>> Hi, Ron, > > >>> > > >>> Thanks. I understand now. It may be useful to add a reference to JWT > > in the > > >>> KIP. > > >>> > > >>> Jun > > >>> > > >>> On Tue, May 15, 2018 at 6:51 PM, Ron Dagostino <rndg...@gmail.com> > > wrote: > > >>> > > >>> > Hi Jun. I think you are getting at the fact that OAuth 2 is a > > flexible > > >>> > framework that allows different installations to do things > > differently. It > > >>> > is true that the principal name in Kafka could come from any claim > > in the > > >>> > token. Most of the time it would come from the 'sub' claim, but it > > could > > >>> > certainly come from another claim, or it could be only indirectly > > based on > > >>> > a claim value (maybe certain text would be trimmed or > > prefixed/suffixed). > > >>> > The point, which I think you are getting at, is that because the > > framework > > >>> > is flexible we need to accommodate that flexibility. The callback > > handler > > >>> > class defined by the listener.name.sasl_ssl. > oauthbearer.sasl.server. > > >>> > callback.handler.class configuration value gives us the required > > >>> > flexibility. As an example, I have an implementation that > leverages > > a > > >>> > popular open source JOSE library to parse the compact > serialization, > > >>> > retrieve the public key if it has not yet been retrieved, verify > the > > >>> > digital signature, and map the 'sub' claim to the > OAuthBearerToken's > > >>> > principal name (which becomes the SASL authorization ID, which > > becomes the > > >>> > Kafka principal name). I could just as easily have mapped a > > different > > >>> > claim to the OAuthBearerToken's principal name, manipulated the > > 'sub' claim > > >>> > value in some way, etc. I write the callback handler code, so I > > complete > > >>> > flexibility to do whatever my OAuth 2 installation requires me to > do. > > >>> > > > >>> > Ron > > >>> > > > >>> > On Tue, May 15, 2018 at 1:39 PM, Jun Rao <j...@confluent.io> wrote: > > >>> > > > >>> > > Hi, Ron, > > >>> > > > > >>> > > Thanks for the reply. I understood your answers to #2 and #3. > > >>> > > > > >>> > > For #1, will the server map all clients' principal name to the > > value > > >>> > > associated with "sub" claim? How do we support mapping different > > clients > > >>> > to > > >>> > > different principal names? > > >>> > > > > >>> > > Jun > > >>> > > > > >>> > > On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino < > rndg...@gmail.com> > > >>> > wrote: > > >>> > > > > >>> > > > Hi Jun. Thanks for the +1 vote. > > >>> > > > > > >>> > > > Regarding the first question about token claims, yes, you have > it > > >>> > correct > > >>> > > > about translating the OAuth token to a principle name via a > JAAS > > module > > >>> > > > option in the default unsecured case. Specifically, the OAuth > > SASL > > >>> > > Server > > >>> > > > implementation is responsible for setting the authorization ID, > > and it > > >>> > > gets > > >>> > > > the authorization ID from the OAuthBearerToken's > principalName() > > >>> > method. > > >>> > > > The listener.name.sasl_ssl.oauthbearer.sasl.server. > > >>> > > callback.handler.class > > >>> > > > is responsible for handling an instance of > > OAuthBearerValidatorCallback > > >>> > > to > > >>> > > > accept a token compact serialization from the client and return > > an > > >>> > > instance > > >>> > > > of OAuthBearerToken (assuming the compact serialization > > validates), and > > >>> > > in > > >>> > > > the default unsecured case the builtin unsecured validator > > callback > > >>> > > handler > > >>> > > > defines the OAuthBearerToken.principalName() method to return > the > > >>> > 'sub' > > >>> > > > claim value by default (with the actual claim it uses being > > >>> > configurable > > >>> > > > via the unsecuredValidatorPrincipalClaimName JAAS module > > option). So > > >>> > > that > > >>> > > > is how we translate from a token to a principal name in the > > default > > >>> > > > unsecured (out-of-the-box) case. > > >>> > > > > > >>> > > > For production use cases, the implementation associated with > > >>> > > > > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class > > >>> > > can > > >>> > > > do whatever it wants. As an example, I have written a class > that > > >>> > wraps a > > >>> > > > com.nimbusds.jwt.SignedJWT instance (see > > >>> > > > https://connect2id.com/products/nimbus-jose-jwt/) and presents > > it as > > >>> > an > > >>> > > > OAuthBearerToken: > > >>> > > > > > >>> > > > public class NimbusSignedJwtOAuthBearerToken implements > > >>> > > OAuthBearerToken { > > >>> > > > private final SignedJWT signedJwt; > > >>> > > > private final String principalName; > > >>> > > > private final Set<String> scope; > > >>> > > > private final Long startTimeMs; > > >>> > > > private final long lifetimeMs; > > >>> > > > > > >>> > > > /** > > >>> > > > * Constructor > > >>> > > > * > > >>> > > > * @param signedJwt > > >>> > > > * the mandatory signed JWT > > >>> > > > * @param principalClaimName > > >>> > > > * the mandatory claim name identifying the > claim > > from > > >>> > > which > > >>> > > > the > > >>> > > > * principal name will be extracted. The claim > > must > > >>> > exist > > >>> > > > and must be > > >>> > > > * a String. > > >>> > > > * @param optionalScopeClaimName > > >>> > > > * the optional claim name identifying the claim > > from > > >>> > > which > > >>> > > > any scope > > >>> > > > * will be extracted. If specified and the claim > > exists > > >>> > > then > > >>> > > > the > > >>> > > > * value must be either a String or a String > List. > > >>> > > > * @throws ParseException > > >>> > > > * if the principal claim does not exist or is > > not a > > >>> > > > String; the > > >>> > > > * scope claim is neither a String nor a String > > List; > > >>> > the > > >>> > > > 'exp' > > >>> > > > * claim does not exist or is not a number; the > > 'iat' > > >>> > > claim > > >>> > > > exists > > >>> > > > * but is not a number; or the 'nbf' claim > > exists and > > >>> > is > > >>> > > > not a > > >>> > > > * number. > > >>> > > > */ > > >>> > > > public NimbusSignedJwtOAuthBearerToken(SignedJWT > signedJwt, > > String > > >>> > > > principalClaimName, > > >>> > > > String optionalScopeClaimName) throws > ParseException > > { > > >>> > > > // etc... > > >>> > > > } > > >>> > > > > > >>> > > > The callback handler runs the following code if the digital > > signature > > >>> > > > validates: > > >>> > > > > > >>> > > > callback.token(new NimbusSignedJwtOAuthBearerToke > n(signedJwt, > > >>> > "sub", > > >>> > > > null)); > > >>> > > > > > >>> > > > I hope that answers the first question. If not let me know > what > > I > > >>> > > > missed/misunderstood and I'll be glad to try to address it. > > >>> > > > > > >>> > > > Regarding the second question, the classes > > OAuthBearerTokenCallback and > > >>> > > > OAuthBearerValidatorCallback implement the Callback interface > -- > > they > > >>> > are > > >>> > > > the callbacks that the AuthenticateCallbackHandler > > implementations need > > >>> > > to > > >>> > > > handle. Specifically, unless the unsecured functionality is > > what is > > >>> > > > desired, the two configuration values [listener.name.sasl_ssl. > > >>> > > oauthbearer. > > >>> > > > ]sasl.login.callback.handler.class and > > >>> > > > > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class > > >>> > > > define the callback handlers that need to handle > > >>> > OAuthBearerTokenCallback > > >>> > > > and OAuthBearerValidatorCallback, respectively. > > >>> > > > > > >>> > > > Regarding the third question, yes, I see your point that the > way > > the > > >>> > spec > > >>> > > > is worded could be taken to imply that the error code is a > single > > >>> > > > character: "A single ASCII..." ( > > >>> > > > https://tools.ietf.org/html/rfc6749#section-5.2). However, it > > is not > > >>> > a > > >>> > > > single character. See the end of that section 5.2 for an > > example that > > >>> > > > shows "error":"invalid_request" as the response. > > >>> > > > > > >>> > > > Thanks again for the +1 vote, Jun, and please do let me know if > > I can > > >>> > > cover > > >>> > > > anything else. > > >>> > > > > > >>> > > > Ron > > >>> > > > > > >>> > > > > > >>> > > > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <j...@confluent.io> > > wrote: > > >>> > > > > > >>> > > > > Hi, Ron, > > >>> > > > > > > >>> > > > > Thanks for the KIP. +1 from me. Just a few minor comments > > below. > > >>> > > > > > > >>> > > > > 1. It seems that we can translate an OAuth token to a > > principle name > > >>> > > > > through the claim name configured in JASS. However, it's not > > clear to > > >>> > > me > > >>> > > > > how an OAuth token is mapped to a claim. Could you clarify > > that? > > >>> > > > > > > >>> > > > > 2. The wiki has the following code. It seems that > > >>> > > > OAuthBearerTokenCallback > > >>> > > > > should implement AuthenticateCallbackHandler? Ditto > > >>> > > > > for OAuthBearerValidatorCallback. > > >>> > > > > > > >>> > > > > public class OAuthBearerTokenCallback implements Callback > > >>> > > > > > > >>> > > > > 3. In OAuthBearerTokenCallback, we have the following method. > > The > > >>> > OAuth > > >>> > > > > spec says the error code is a single ASCII. So, should we > > return a > > >>> > Char > > >>> > > > or > > >>> > > > > a String? > > >>> > > > > > > >>> > > > > public String errorCode() > > >>> > > > > > > >>> > > > > Jun > > >>> > > > > > > >>> > > > > > > >>> > > > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino < > > rndg...@gmail.com> > > >>> > > wrote: > > >>> > > > > > > >>> > > > > > Hi everyone. I would like to start the vote for KIP-255: > > >>> > > > > > https://cwiki.apache.org/confluence/pages/viewpage. > > >>> > > > > action?pageId=75968876 > > >>> > > > > > > > >>> > > > > > This KIP proposes to add the following functionality > related > > to > > >>> > > > > > SASL/OAUTHBEARER: > > >>> > > > > > > > >>> > > > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the > > >>> > > > inter-broker > > >>> > > > > > protocol as well as non-broker clients) to flexibly > retrieve > > an > > >>> > > access > > >>> > > > > > token from an OAuth 2 authorization server based on the > > declaration > > >>> > > of > > >>> > > > a > > >>> > > > > > custom login CallbackHandler implementation and have that > > access > > >>> > > token > > >>> > > > > > transparently and automatically transmitted to a broker for > > >>> > > > > authentication. > > >>> > > > > > > > >>> > > > > > 2) Allow brokers to flexibly validate provided access > tokens > > when a > > >>> > > > > client > > >>> > > > > > establishes a connection based on the declaration of a > > custom SASL > > >>> > > > Server > > >>> > > > > > CallbackHandler implementation. > > >>> > > > > > > > >>> > > > > > 3) Provide implementations of the above retrieval and > > validation > > >>> > > > features > > >>> > > > > > based on an unsecured JSON Web Token that function > > out-of-the-box > > >>> > > with > > >>> > > > > > minimal configuration required (i.e. implementations of the > > two > > >>> > types > > >>> > > > of > > >>> > > > > > callback handlers mentioned above will be used by default > > with no > > >>> > > need > > >>> > > > to > > >>> > > > > > explicitly declare them). > > >>> > > > > > > > >>> > > > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the > > >>> > > > inter-broker > > >>> > > > > > protocol as well as non-broker clients) to transparently > > retrieve a > > >>> > > new > > >>> > > > > > access token in the background before the existing access > > token > > >>> > > expires > > >>> > > > > in > > >>> > > > > > case the client has to open new connections. > > >>> > > > > > > > >>> > > > > > Thanks, > > >>> > > > > > > > >>> > > > > > Ron > > >>> > > > > > > > >>> > > > > > > >>> > > > > > >>> > > > > >>> > > > >> > > > > > >