Hi Rajini.  I think a class is fine as long as we make sure the semantics
of immutability are clear -- it would have to be a value class, and any
constructor that accepts a Map as input would have to copy that Map rather
than store it in a member variable.  Similarly, any Map that it might
return would have to be unmodifiable.

Ron

On Mon, Jul 23, 2018 at 12:24 PM Rajini Sivaram <rajinisiva...@gmail.com>
wrote:

> Hi Ron, Stanislav,
>
> I agree with Stanislav that it would be better to leave `SaslExtensions` as
> a class rather than make it an interface. We don''t really expect users to
> extends this class, so it is convenient to have an implementation since
> users need to create an instance. The class provided by the public API
> should be sufficient in the vast majority of the cases. Ron, do you agree?
>
> On Mon, Jul 23, 2018 at 11:35 AM, Ron Dagostino <rndg...@gmail.com> wrote:
>
> > Hi Stanislav.  See https://tools.ietf.org/html/rfc7628#section-3.1, and
> > that section refers to the core ABNF productions defined in
> > https://tools.ietf.org/html/rfc5234#appendix-B.
> >
> > Ron
> >
> > > On Jul 23, 2018, at 1:30 AM, Stanislav Kozlovski <
> stanis...@confluent.io>
> > wrote:
> > >
> > > Hey Ron and Rajini,
> > >
> > > Here are my thoughts:
> > > Regarding separators in SaslExtensions - Agreed, that was a bad move.
> > > Should definitely not be a concern of CallbackHandler and LoginModule
> > > implementors.
> > > SaslExtensions interface - Wouldn't implementing it as an interface
> mean
> > > that users will have to make sure they're passing in an unmodifiable
> map
> > > themselves. I believe it would be better if we enforced that through
> > class
> > > constructors instead.
> > > SaslExtensions#map() - I'd also prefer this. The reason I went with
> > > `extensionValue` and `extensionNames` was because I figured it made
> sense
> > > to have `ScramExtensions` extend `SaslExtensions` and therefore have
> > their
> > > API be similar. In the end, do you think that it is worth it to have
> > > `ScramExtensions` extend `SaslExtensions`?
> > > @Ron, could you point me to the SASL OAuth mechanism specific regular
> > > expressions for keys/values you mentioned are in RFC 7628 (
> > > https://tools.ietf.org/html/rfc7628) ? I could not find any while
> > > originally implementing this.
> > >
> > > Best,
> > > Stanislav
> > >
> > >> On Sun, Jul 22, 2018 at 6:46 PM Ron Dagostino <rndg...@gmail.com>
> > wrote:
> > >>
> > >> Hi again, Rajini and Stanislav.  I wonder if making SaslExtensions an
> > >> interface rather than a class might be a good solution.  For example:
> > >>
> > >> public interface SaslExtensions {
> > >>   /**
> > >>    * @return an immutable map view of the SASL extensions
> > >>    */
> > >>    Map<String, String> map();
> > >> }
> > >>
> > >> This solves the issue of lack of clarity on immutability, and it also
> > >> eliminates copying, like this:
> > >>
> > >> SaslExtensions myMethod() {
> > >>    Map<String, String> myRetval = getUnmodifiableSaslExtensionsMap();
> > >>    return new SaslExtensions() {
> > >>        public Map<String, String> map() {
> > >>            return myRetval;
> > >>        }
> > >>    }
> > >> }
> > >>
> > >> Alternatively, we could do it like this:
> > >>
> > >> /**
> > >> * Supplier that returns immutable map view of SASL Extensions
> > >> */
> > >> public interface SaslExtensions extends Supplier<Map<String, String>>
> {
> > >>    // empty
> > >> }
> > >>
> > >> The we could simply return the instance like this, again without
> > copying:
> > >>
> > >> SaslExtensions myMethod() {
> > >>    Map<String, String> myRetval = getUnmodifiableSaslExtensionsMap();
> > >>    return () -> myRetval;
> > >> }
> > >>
> > >> I think the main reason for making SaslExtensions part of the public
> > >> interface is to avoid adding a Map to the Subject's public
> credentials.
> > >> Making SaslExtensions an interface meets that requirement and then
> > allows
> > >> us to be free to implement whatever we want internally.
> > >>
> > >> Thoughts?
> > >>
> > >> Ron
> > >>
> > >>> On Sun, Jul 22, 2018 at 12:45 PM Ron Dagostino <rndg...@gmail.com>
> > wrote:
> > >>>
> > >>> Hi Rajini.  The SaslServer is going to have to validate the
> extensions,
> > >>> too, but I’m okay with keeping the validation logic elsewhere as long
> > as
> > >> it
> > >>> can be reused in both the client and the secret.
> > >>>
> > >>> I strongly prefer exposing a map() method as opposed to
> > extensionNames()
> > >>> and extensionValue(String) methods. It is a smaller API (2 methods
> > >> instead
> > >>> of 1), and it gives clients of the API full map-related functionality
> > >>> (there’s a lot of support for dealing with maps in a variety of
> ways).
> > >>>
> > >>> Regardless of whether we go with a map() method or extensionNames()
> and
> > >>> extensionValue(String) methods, the semantics of mutability need to
> be
> > >>> clear.  I think either way we should never share a map that anyone
> else
> > >>> could possibly mutate — either a map that someone gives us or a map
> > that
> > >> we
> > >>> might expose.
> > >>>
> > >>> Thoughts?
> > >>>
> > >>> Ron
> > >>>
> > >>>> On Jul 22, 2018, at 11:23 AM, Rajini Sivaram <
> rajinisiva...@gmail.com
> > >
> > >>> wrote:
> > >>>>
> > >>>> Hmm.... I think we need a much simpler SaslExtensions class if we
> are
> > >>>> making it part of the public API.
> > >>>>
> > >>>> 1. I don't see the point of including separator anywhere in
> > >>> SaslExtensions.
> > >>>> Extensions provide a map and we propagate the map from client to
> > server
> > >>>> using the protocol associated with the mechanism in use. The
> separator
> > >> is
> > >>>> not configurable and should not be a concern of the implementor of
> > >>>> SaslExtensionsCallback interface that provides an instance of
> > >>> SaslExtensions
> > >>>> .
> > >>>>
> > >>>> 2. I agree with Ron that we need mechanism-specific validation of
> the
> > >>>> values from SaslExtensions. But I think we could do the validation
> in
> > >> the
> > >>>> appropriate `SaslClient` implementation of that mechanism.
> > >>>>
> > >>>> I think we could just have a very simple extensions class and move
> > >>>> everything else to appropriate internal classes of the mechanisms
> > using
> > >>>> extensions. What do you think?
> > >>>>
> > >>>> public class SaslExtensions {
> > >>>>   private final Map<String, String> extensionMap;
> > >>>>
> > >>>>   public SaslExtensions(Map<String, String> extensionMap) {
> > >>>>       this.extensionMap = extensionMap;
> > >>>>   }
> > >>>>
> > >>>>   public String extensionValue(String name) {
> > >>>>       return extensionMap.get(name);
> > >>>>   }
> > >>>>
> > >>>>   public Set<String> extensionNames() {
> > >>>>       return extensionMap.keySet();
> > >>>>   }
> > >>>> }
> > >>>>
> > >>>>
> > >>>>
> > >>>>> On Sat, Jul 21, 2018 at 9:01 PM, Ron Dagostino <rndg...@gmail.com>
> > >>> wrote:
> > >>>>>
> > >>>>> Hi Stanislav and Rajini.  If SaslExtensions is going to part of the
> > >>> public
> > >>>>> API, then it occurred to me that one of the requirements of all
> SASL
> > >>>>> extensions is that the keys and values need to match
> > >> mechanism-specific
> > >>>>> regular expressions.  For example, RFC 5802 (
> > >>>>> https://tools.ietf.org/html/rfc5802) specifies the regular
> > >> expressions
> > >>> for
> > >>>>> the SCRAM-specific SASL mechanisms, and RFC 7628 (
> > >>>>> https://tools.ietf.org/html/rfc7628) specifies different regular
> > >>>>> expressions for the OAUTHBEARER SASL mechanism.  I am thinking the
> > >>>>> SaslExtensions class should probably provide a way to make sure the
> > >> keys
> > >>>>> and values match the appropriate regular expressions.  What do you
> > >>> think of
> > >>>>> something along the lines of the below definition for the
> > >> SaslExtensions
> > >>>>> class?  It is missing Javadoc and toString()/hashCode()/equals()
> > >>> methods,
> > >>>>> of course, but aside from that, do you think this is sufficient and
> > >>>>> appropriate?
> > >>>>>
> > >>>>> Ron
> > >>>>>
> > >>>>> public class SaslExtensions {
> > >>>>>   private final Map<String, String> extensionsMap;
> > >>>>>
> > >>>>>   public SaslExtensions(String mapStr, String keyValueSeparator,
> > >> String
> > >>>>> elementSeparator,
> > >>>>>           Pattern saslNameRegexPattern, Pattern
> > >> saslValueRegexPattern)
> > >>> {
> > >>>>>       this(Utils.parseMap(mapStr, keyValueSeparator,
> > >> elementSeparator),
> > >>>>> saslNameRegexPattern, saslValueRegexPattern);
> > >>>>>   }
> > >>>>>
> > >>>>>   public SaslExtensions(Map<String, String> extensionsMap, Pattern
> > >>>>> saslNameRegexPattern,
> > >>>>>           Pattern saslValueRegexPattern) {
> > >>>>>       Map<String, String> sanitizedCopy = new
> > >>>>> HashMap<>(extensionsMap.size());
> > >>>>>       for (Entry<String, String> entry : extensionsMap.entrySet())
> {
> > >>>>>           if (!saslNameRegexPattern.matcher(entry.getKey()).
> > matches()
> > >>>>>                   ||
> > >>>>> !saslValueRegexPattern.matcher(entry.getValue()).matches())
> > >>>>>               throw new IllegalArgumentException("Invalid key or
> > >>>>> value");
> > >>>>>           sanitizedCopy.put(entry.getKey(), entry.getValue());
> > >>>>>       }
> > >>>>>       this.extensionsMap =
> > >> Collections.unmodifiableMap(sanitizedCopy);
> > >>>>>   }
> > >>>>>
> > >>>>>   public Map<String, String> map() {
> > >>>>>       return extensionsMap;
> > >>>>>   }
> > >>>>> }
> > >>>>>
> > >>>>> On Fri, Jul 20, 2018 at 12:49 PM Stanislav Kozlovski <
> > >>>>> stanis...@confluent.io>
> > >>>>> wrote:
> > >>>>>
> > >>>>>> Hi Ron,
> > >>>>>>
> > >>>>>> I saw that and decided that would be the best approach. The
> current
> > >>>>>> ScramExtensions implementation uses a Map in the public
> credentials
> > >>> and I
> > >>>>>> thought I would follow convention rather than introduce my own
> > thing,
> > >>> but
> > >>>>>> maybe this is best
> > >>>>>>
> > >>>>>>> On Fri, Jul 20, 2018 at 8:39 AM Ron Dagostino <rndg...@gmail.com
> >
> > >>> wrote:
> > >>>>>>>
> > >>>>>>> Hi Stanislav.  I'm wondering if we should make SaslExtensions
> part
> > >> of
> > >>>>> the
> > >>>>>>> public API.  I mentioned this in my review of the PR, too (and
> > >> tagged
> > >>>>>>> Rajini to get her input).  If we add a Map to the Subject's
> public
> > >>>>>>> credentials we are basically making a public commitment that any
> > Map
> > >>>>>>> associated with the public credentials defines the SASL
> extensions
> > >> and
> > >>>>> we
> > >>>>>>> can never add another instance implementing Map to the public
> > >>>>>> credentials.
> > >>>>>>> That's a very big constraint we are committing to, and I'm
> > wondering
> > >>> if
> > >>>>>> we
> > >>>>>>> should make SaslExtensions public and attach an instance of that
> to
> > >>> the
> > >>>>>>> Subject's public credentials instead.
> > >>>>>>>
> > >>>>>>> Ron
> > >>>>>>>
> > >>>>>>> On Thu, Jul 19, 2018 at 8:15 PM Stanislav Kozlovski <
> > >>>>>>> stanis...@confluent.io>
> > >>>>>>> wrote:
> > >>>>>>>
> > >>>>>>>> I have updated the PR and KIP to address the comments made so
> far.
> > >>>>>> Please
> > >>>>>>>> take another look at them and share your thoughts.
> > >>>>>>>> KIP:
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>
> > >>>>>> https://cwiki.apache.org/confluence/display/KAFKA/KIP-
> > >>>>> 342%3A+Add+support+for+Custom+SASL+extensions+in+
> > >>>>> OAuthBearer+authentication
> > >>>>>>>> PR: Pull request <https://github.com/apache/kafka/pull/5379>
> > >>>>>>>>
> > >>>>>>>> Best,
> > >>>>>>>> Stanislav
> > >>>>>>>>
> > >>>>>>>> On Thu, Jul 19, 2018 at 1:58 PM Stanislav Kozlovski <
> > >>>>>>>> stanis...@confluent.io>
> > >>>>>>>> wrote:
> > >>>>>>>>
> > >>>>>>>>> Hi Ron,
> > >>>>>>>>>
> > >>>>>>>>> Agreed. `SaslExtensionsCallback` will be the only public API
> > >>>>> addition
> > >>>>>>> and
> > >>>>>>>>> new documentation for the extension strings.
> > >>>>>>>>> A question that came up - should the LoginCallbackHandler throw
> > an
> > >>>>>>>>> exception or simply ignore key/value extension pairs who do not
> > >>>>> match
> > >>>>>>> the
> > >>>>>>>>> validation regex pattern? I guess it would be better to throw,
> as
> > >>>>> to
> > >>>>>>>> avoid
> > >>>>>>>>> confusion.
> > >>>>>>>>>
> > >>>>>>>>> And yes, I will make sure the key/value are validated on the
> > >> client
> > >>>>>> as
> > >>>>>>>>> well as in the server. Even then, I structured the
> > >>>>>>>> getNegotiatedProperty()
> > >>>>>>>>> method such that the OAUTHBEARER.token can never be
> overridden. I
> > >>>>>>>>> considered adding a test for that, but I figured having the
> regex
> > >>>>>>>>> validation be enough of a guarantee.
> > >>>>>>>>>
> > >>>>>>>>> On Thu, Jul 19, 2018 at 9:49 AM Ron Dagostino <
> rndg...@gmail.com
> > >
> > >>>>>>> wrote:
> > >>>>>>>>>
> > >>>>>>>>>> Hi Rajini and Stanislav.  Rajini, yes, I think you are right
> > >> about
> > >>>>>> the
> > >>>>>>>>>> login callback handler being more appropriate for retrieving
> the
> > >>>>>> SASL
> > >>>>>>>>>> extensions than the login module itself (how many times am I
> > >> going
> > >>>>>> to
> > >>>>>>>> have
> > >>>>>>>>>> to be encouraged to leverage the callback handlers?!? lol).
> > >>>>>>>>>> OAuthBearerLoginModule should ask its login callback handler
> to
> > >>>>>> handle
> > >>>>>>>> an
> > >>>>>>>>>> instance of SaslExtensionsCallback in addition to an instance
> of
> > >>>>>>>>>> OAuthBearerTokenCallback, and the default login callback
> handler
> > >>>>>>>>>> implementation (OAuthBearerUnsecuredLoginCallbackHandler)
> > should
> > >>>>>>> either
> > >>>>>>>>>> return an empty map via callback or it should recognize
> > >> additional
> > >>>>>>> JAAS
> > >>>>>>>>>> module options of the form
> > >>>>>>> unsecuredLoginExtension_<extensionName>=value
> > >>>>>>>>>> so
> > >>>>>>>>>> that arbitrary extensions can be added in development and test
> > >>>>>>> scenarios
> > >>>>>>>>>> (similar to how arbitrary claims on unsecured tokens can be
> > >>>>> created
> > >>>>>> in
> > >>>>>>>>>> those scenarios via the JAAS module options
> > >>>>>>>>>> unsecuredLoginStringClaim_<claimName>=value, etc.).  Then the
> > >>>>>>>>>> OAuthBearerLoginModule can add a map of any extensions to the
> > >>>>>>> Subject's
> > >>>>>>>>>> public credentials where the default SASL client callback
> > handler
> > >>>>>>> class
> > >>>>>>>> (
> > >>>>>>>>>> OAuthBearerSaslClientCallbackHandler) can be amended to
> support
> > >>>>>>>>>> SaslExtensionsCallback and look on the Subject accordingly.
> > >> There
> > >>>>>>> would
> > >>>>>>>>>> be
> > >>>>>>>>>> no need to implement a custom sasl.client.callback.handler.
> > class
> > >>>>> in
> > >>>>>>> this
> > >>>>>>>>>> case, and no logic would need to be moved to a public static
> > >>>>> method
> > >>>>>> on
> > >>>>>>>>>> OAuthBearerLoginModule as I had proposed (at least not right
> > now,
> > >>>>>>> anyway
> > >>>>>>>>>> --
> > >>>>>>>>>> there may come a time when a need for a custom
> > >>>>>>>>>> sasl.client.callback.handler.class is identified, and at that
> > >>>>> point
> > >>>>>>> the
> > >>>>>>>>>> default implementation would either have to made part of the
> > >>>>> public
> > >>>>>>> API
> > >>>>>>>>>> with protected rather than private methods so it could be
> > >> directly
> > >>>>>>>>>> extended
> > >>>>>>>>>> or its logic would have to be moved to public static methods
> on
> > >>>>>>>>>> OAuthBearerLoginModule).
> > >>>>>>>>>>
> > >>>>>>>>>> So, to try to summarize, I think SaslExtensionsCallback will
> be
> > >>>>> the
> > >>>>>>> only
> > >>>>>>>>>> public API addition due to this KIP in terms of code, and then
> > >>>>> maybe
> > >>>>>>> the
> > >>>>>>>>>> recognition of the unsecuredLoginExtension_<
> > extensionName>=value
> > >>>>>>> module
> > >>>>>>>>>> options in the default unsecured case (which would be a
> > >>>>>> documentation
> > >>>>>>>>>> change and an internal implementation issue rather than a
> public
> > >>>>> API
> > >>>>>>> in
> > >>>>>>>>>> terms of code).  And then also the fact that extension names
> and
> > >>>>>>> values
> > >>>>>>>>>> are
> > >>>>>>>>>> accessed on the server side via negotiated properties.  Do I
> > have
> > >>>>>> that
> > >>>>>>>>>> summary right?
> > >>>>>>>>>>
> > >>>>>>>>>> One thing I want to note is that the code needs to make sure
> the
> > >>>>>>>> extension
> > >>>>>>>>>> names are composed of only ALPHA [a-zA-Z] characters as per
> the
> > >>>>> spec
> > >>>>>>>> (not
> > >>>>>>>>>> only for that reason, but to also make sure the token
> available
> > >> at
> > >>>>>> the
> > >>>>>>>>>> OAUTHBEARER.token negotiated property can't be overwritten).
> > >>>>>>>>>>
> > >>>>>>>>>> Ron
> > >>>>>>>>>>
> > >>>>>>>>>> On Thu, Jul 19, 2018 at 12:43 PM Stanislav Kozlovski <
> > >>>>>>>>>> stanis...@confluent.io>
> > >>>>>>>>>> wrote:
> > >>>>>>>>>>
> > >>>>>>>>>>> Hey Ron,
> > >>>>>>>>>>>
> > >>>>>>>>>>> Come to think of it, I think what Rajini said makes more
> sense
> > >>>>>> than
> > >>>>>>> my
> > >>>>>>>>>>> initial proposal. Having the OAuthBearerClientCallbackHandler
> > >>>>>>> populate
> > >>>>>>>>>>> SaslExtensionsCallback by taking a Map from the Subject would
> > >>>>> ease
> > >>>>>>>>>> users'
> > >>>>>>>>>>> implementation - they'd only have to provide a login callback
> > >>>>>>> handler
> > >>>>>>>>>> which
> > >>>>>>>>>>> attaches extensions to the Subject.
> > >>>>>>>>>>> I will now update the PR and the examples in the KIP. Let me
> > >>>>> know
> > >>>>>>> what
> > >>>>>>>>>> you
> > >>>>>>>>>>> think
> > >>>>>>>>>>>
> > >>>>>>>>>>> Hi Rajini,
> > >>>>>>>>>>> Yes, I will switch both classes to private/public as it makes
> > >>>>>> total
> > >>>>>>>>>> sense.
> > >>>>>>>>>>>
> > >>>>>>>>>>> Best,
> > >>>>>>>>>>> Stanislav
> > >>>>>>>>>>> On Thu, Jul 19, 2018 at 9:02 AM Rajini Sivaram <
> > >>>>>>>> rajinisiva...@gmail.com
> > >>>>>>>>>>>
> > >>>>>>>>>>> wrote:
> > >>>>>>>>>>>
> > >>>>>>>>>>>> Hi Stanislav,
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Thanks for the KIP. Since SaslExtensions will be an internal
> > >>>>>>> class,
> > >>>>>>>>>> can
> > >>>>>>>>>>> we
> > >>>>>>>>>>>> remove it from the KIP to avoid confusion? Also, can we add
> > >>>>> the
> > >>>>>>>>>> package
> > >>>>>>>>>>>> name for SaslExtensionsCallback? The PR has it in
> > >>>>>>>>>>>> org.apache.kafka.common.security which is an internal
> > >>>>> package.
> > >>>>>> As
> > >>>>>>> a
> > >>>>>>>>>>> public
> > >>>>>>>>>>>> class, it could be in org.apache.kafka.common.security.auth.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Regards,
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Rajini
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> On Thu, Jul 19, 2018 at 4:50 PM, Rajini Sivaram <
> > >>>>>>>>>> rajinisiva...@gmail.com
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> wrote:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>> Hi Ron,
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>> Is there a reason why wouldn't want to provide extensions
> > >>>>>> using
> > >>>>>>> a
> > >>>>>>>>>> login
> > >>>>>>>>>>>>> callback handler in the same way as we inject tokens? The
> > >>>>>>> easiest
> > >>>>>>>>>> way
> > >>>>>>>>>>> to
> > >>>>>>>>>>>>> inject custom extensions would be using the JAAS config. So
> > >>>>> we
> > >>>>>>>> could
> > >>>>>>>>>>> have
> > >>>>>>>>>>>>> both OAuthBearerTokenCallback and SaslExtensionsCallback
> > >>>>>>>> processed
> > >>>>>>>>>> by
> > >>>>>>>>>>> a
> > >>>>>>>>>>>>> login callback handler. And the map returned by
> > >>>>>>>>>> SaslExtensionsCallback
> > >>>>>>>>>>>>> could be added to Subject by the default
> > >>>>>>>>>>>> OAuthBearerSaslClientCallbackHandler.
> > >>>>>>>>>>>>> Since OAuth users have to provide a login callback handler
> > >>>>>>> anyway,
> > >>>>>>>>>>>> wouldn't
> > >>>>>>>>>>>>> it be a better fit?
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>> Thank you,
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>> Rajini
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>> On Thu, Jul 19, 2018 at 4:08 PM, Ron Dagostino <
> > >>>>>>> rndg...@gmail.com
> > >>>>>>>>>
> > >>>>>>>>>>>> wrote:
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>>> Hi Stanislav.
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>> Implementers of a custom sasl.client.callback.handler.
> > >>>>> class
> > >>>>>>> must
> > >>>>>>>> be
> > >>>>>>>>>>> sure
> > >>>>>>>>>>>>>> to
> > >>>>>>>>>>>>>> provide the existing logic in
> > >>>>>>>>>>>>>> org.apache.kafka.common.security.oauthbearer.
> > >>>>> internals.OAuth
> > >>>>>>>>>>>>>> BearerSaslClientCallbackHandler
> > >>>>>>>>>>>>>> that handles instances of OAuthBearerTokenCallback (by
> > >>>>>>> retrieving
> > >>>>>>>>>> the
> > >>>>>>>>>>>>>> private credential from the Subject); a custom
> > >>>>> implementation
> > >>>>>>>> that
> > >>>>>>>>>>> fails
> > >>>>>>>>>>>>>> to
> > >>>>>>>>>>>>>> do this will not work, so the KIP should state this
> > >>>>>>> requirement.
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>> The question then arises: how should implementers provide
> > >>>>> the
> > >>>>>>>>>> existing
> > >>>>>>>>>>>>>> logic in the OAuthBearerSaslClientCallbackHandler class?
> > >>>>>> That
> > >>>>>>>>>> class
> > >>>>>>>>>>> is
> > >>>>>>>>>>>>>> not
> > >>>>>>>>>>>>>> part of the public API, and its
> > >>>>>>>>>>> handleCallback(OAuthBearerTokenCallback)
> > >>>>>>>>>>>>>> method, which implements the logic, is private anyway (so
> > >>>>>> even
> > >>>>>>> if
> > >>>>>>>>>>>> someone
> > >>>>>>>>>>>>>> took the risk of extending the non-API class the method
> > >>>>> would
> > >>>>>>>>>>> generally
> > >>>>>>>>>>>>>> not
> > >>>>>>>>>>>>>> be available in the subclass).  So as it stands right now
> > >>>>>>>>>> implementers
> > >>>>>>>>>>>> are
> > >>>>>>>>>>>>>> left to copy/paste that logic into their code.  A better
> > >>>>>>> solution
> > >>>>>>>>>>> might
> > >>>>>>>>>>>> be
> > >>>>>>>>>>>>>> to have the private method in
> > >>>>>>>> OAuthBearerSaslClientCallbackHandler
> > >>>>>>>>>>>>>> invoke a
> > >>>>>>>>>>>>>> public static method on the
> > >>>>>>>>>>>>>>
> > >>>>>>>> org.apache.kafka.common.security.oauthbearer.
> > OAuthBearerLoginModule
> > >>>>>>>>>>>> class
> > >>>>>>>>>>>>>> (which is part of the public API) to retrieve the
> > >>>>> credential
> > >>>>>>>> (e.g.
> > >>>>>>>>>>>> public
> > >>>>>>>>>>>>>> static OAuthBearerToken retrieveCredential(Subject)) .
> The
> > >>>>>>>>>> commit()
> > >>>>>>>>>>>>>> method
> > >>>>>>>>>>>>>> of the OAuthBearerLoginModule class is what puts the
> > >>>>>> credential
> > >>>>>>>>>> there
> > >>>>>>>>>>> in
> > >>>>>>>>>>>>>> the first place, so it could make sense for the class to
> > >>>>>> expose
> > >>>>>>>> the
> > >>>>>>>>>>>>>> complementary logic for retrieving the credential in this
> > >>>>>> way.
> > >>>>>>>>>>>> Regarding
> > >>>>>>>>>>>>>> your question about plugability of LoginModules, yes, the
> > >>>>>>>>>> LoginModule
> > >>>>>>>>>>>>>> class
> > >>>>>>>>>>>>>> is explicitly stated in the JAAS config, so it is indeed
> > >>>>>>>>>> pluggable; an
> > >>>>>>>>>>>>>> extending class would override the commit() method, call
> > >>>>>>>>>>> super.commit(),
> > >>>>>>>>>>>>>> and if the return value is true it would do whatever is
> > >>>>>>> necessary
> > >>>>>>>>>> to
> > >>>>>>>>>>> add
> > >>>>>>>>>>>>>> the desired SASL extensions to the Subject -- probably in
> > >>>>> the
> > >>>>>>>>>> public
> > >>>>>>>>>>>>>> credentials -- where a custom
> > >>>>>>> sasl.client.callback.handler.class
> > >>>>>>>>>> would
> > >>>>>>>>>>>> be
> > >>>>>>>>>>>>>> able to find them.  The KIP might state this, too.
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>> I'll look forward to seeing a new PR once the fix for the
> > >>>>>> 0x01
> > >>>>>>>>>>> separator
> > >>>>>>>>>>>>>> issue in the SASL/OAUTHBEARER implementation (KAFKA-7182
> > >>>>>>>>>>>>>> <
> > >>>>>>> https://issues.apache.org/jira/projects/KAFKA/issues/KAFKA-7182
> > >>>>>>>>> )
> > >>>>>>>>>> is
> > >>>>>>>>>>>>>> merged.
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>> Ron
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>> On Wed, Jul 18, 2018 at 6:38 PM Stanislav Kozlovski <
> > >>>>>>>>>>>>>> stanis...@confluent.io>
> > >>>>>>>>>>>>>> wrote:
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> Hey Ron,
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> You brought up some great points. I did my best to
> > >>>>> address
> > >>>>>>> them
> > >>>>>>>>>> and
> > >>>>>>>>>>>>>> updated
> > >>>>>>>>>>>>>>> the KIP.
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> I should mention that I used commas to separate
> > >>>>> extensions
> > >>>>>> in
> > >>>>>>>> the
> > >>>>>>>>>>>>>> protocol,
> > >>>>>>>>>>>>>>> because we did not use the recommended Control-A
> > >>>>> character
> > >>>>>>> for
> > >>>>>>>>>>>>>> separators
> > >>>>>>>>>>>>>>> in the OAuth message and I figured I would not change it.
> > >>>>>>>>>>>>>>> Now that I saw your PR about implementing the proper
> > >>>>>>> separators
> > >>>>>>>>>> in
> > >>>>>>>>>>>> OAUTH
> > >>>>>>>>>>>>>>> <https://github.com/apache/kafka/pull/5391> and will
> > >>>>>> change
> > >>>>>>> my
> > >>>>>>>>>>>>>>> implementation once yours gets merged, meaning commas
> > >>>>> will
> > >>>>>>> be a
> > >>>>>>>>>>>>>> supported
> > >>>>>>>>>>>>>>> value for extensions.
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> About the implementation: yes you're right, you should
> > >>>>>>> define `
> > >>>>>>>>>>>>>>> sasl.client.callback.handler.class` which has the same
> > >>>>>>>>>> functionality
> > >>>>>>>>>>>>>> as `
> > >>>>>>>>>>>>>>> OAuthBearerSaslClientCallbackHandler` plus the
> > >>>>> additional
> > >>>>>>>>>>>>>> functionality of
> > >>>>>>>>>>>>>>> handling the `SaslExtensionsCallback` by attaching
> > >>>>>> extensions
> > >>>>>>>> to
> > >>>>>>>>>> it.
> > >>>>>>>>>>>>>>> The only reason you'd populate the `Subject` object with
> > >>>>>> the
> > >>>>>>>>>>>> extensions
> > >>>>>>>>>>>>>> is
> > >>>>>>>>>>>>>>> if you used the default `SaslClientCallbackHandler`
> > >>>>> (which
> > >>>>>>>>>> handles
> > >>>>>>>>>>> the
> > >>>>>>>>>>>>>>> extensions callback by adding whatever's in the subject),
> > >>>>>> as
> > >>>>>>>> the
> > >>>>>>>>>>> SCRAM
> > >>>>>>>>>>>>>>> authentication does.
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>
> > >>>>>> https://github.com/stanislavkozlovski/kafka/blob/KAFKA-7169-
> > >>>>>>>>>>>>>> custom-sasl-extensions/clients/src/main/java/org/
> > >>>>>>>>>>>>>> apache/kafka/common/security/
> > >>>>> oauthbearer/internals/OAuthBea
> > >>>>>>>>>>>>>> rerSaslClient.java#L92
> > >>>>>>>>>>>>>>> And yes, in that case you would need a custom
> > >>>>> `LoginModule`
> > >>>>>>>> which
> > >>>>>>>>>>>>>> populates
> > >>>>>>>>>>>>>>> the Subject in that case, although I'm not sure if Kafka
> > >>>>>>>> supports
> > >>>>>>>>>>>>>> pluggable
> > >>>>>>>>>>>>>>> LoginModules. Does it?
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> Best,
> > >>>>>>>>>>>>>>> Stanislav
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> On Wed, Jul 18, 2018 at 9:50 AM Ron Dagostino <
> > >>>>>>>> rndg...@gmail.com
> > >>>>>>>>>>>
> > >>>>>>>>>>>>>> wrote:
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>> Hi Stanislav.  Could you add something to the KIP about
> > >>>>>> the
> > >>>>>>>>>>> security
> > >>>>>>>>>>>>>>>> implications related to the CSV name/value pairs sent
> > >>>>> in
> > >>>>>>> the
> > >>>>>>>>>>>>>> extension?
> > >>>>>>>>>>>>>>>> For example, the OAuth access token may have a digital
> > >>>>>>>>>> signature,
> > >>>>>>>>>>>> but
> > >>>>>>>>>>>>>> the
> > >>>>>>>>>>>>>>>> extensions generally will not (unless one of the values
> > >>>>>> is
> > >>>>>>> a
> > >>>>>>>>>> JWS
> > >>>>>>>>>>>>>> compact
> > >>>>>>>>>>>>>>>> serialization, but I doubt anyone would go that far),
> > >>>>> so
> > >>>>>>> the
> > >>>>>>>>>>> server
> > >>>>>>>>>>>>>>>> generally cannot trust the extensions to be accurate
> > >>>>> for
> > >>>>>>>>>> anything
> > >>>>>>>>>>>>>>>> critical.  You mentioned the "better tracing and
> > >>>>>>>>>> troubleshooting"
> > >>>>>>>>>>>> use
> > >>>>>>>>>>>>>>> case,
> > >>>>>>>>>>>>>>>> which I think is fine despite the lack of security;
> > >>>>> given
> > >>>>>>>> that
> > >>>>>>>>>>> lack
> > >>>>>>>>>>>> of
> > >>>>>>>>>>>>>>>> security, though, I believe it is important to also
> > >>>>> state
> > >>>>>>>> what
> > >>>>>>>>>> the
> > >>>>>>>>>>>>>>>> extensions should *not* be used for.
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>> Also, could you indicate in the KIP how the extensions
> > >>>>>>> might
> > >>>>>>>>>>>> actually
> > >>>>>>>>>>>>>> be
> > >>>>>>>>>>>>>>>> added?  My take on that would be to extend
> > >>>>>>>>>> OAuthBearerLoginModule
> > >>>>>>>>>>> to
> > >>>>>>>>>>>>>>>> override the initialize() and commit() methods so that
> > >>>>>> the
> > >>>>>>>>>> derived
> > >>>>>>>>>>>>>> class
> > >>>>>>>>>>>>>>>> would have access to the Subject instance and could
> > >>>>> add a
> > >>>>>>> map
> > >>>>>>>>>> to
> > >>>>>>>>>>> the
> > >>>>>>>>>>>>>>>> subject's public or private credentials when the commit
> > >>>>>>>>>> succeeds;
> > >>>>>>>>>>>>>> then I
> > >>>>>>>>>>>>>>>> think the sasl.client.callback.handler.class would
> > >>>>> have
> > >>>>>> to
> > >>>>>>> be
> > >>>>>>>>>>>>>> explicitly
> > >>>>>>>>>>>>>>>> set to a class that extends the default implementation
> > >>>>>>>>>>>>>>>> (OAuthBearerSaslClientCallbackHandler) and retrieves
> > >>>>> the
> > >>>>>>> map
> > >>>>>>>>>> when
> > >>>>>>>>>>>>>>> handling
> > >>>>>>>>>>>>>>>> the SaslExtensionsCallback.  But maybe you are thinking
> > >>>>>>> about
> > >>>>>>>>>> it
> > >>>>>>>>>>>>>>>> differently?  Some guidance on how to actually take
> > >>>>>>> advantage
> > >>>>>>>>>> of
> > >>>>>>>>>>> the
> > >>>>>>>>>>>>>>>> feature via an implementation would be a useful
> > >>>>> addition
> > >>>>>> to
> > >>>>>>>> the
> > >>>>>>>>>>> KIP.
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>> Finally, I note that the extension parsing does not
> > >>>>>>> support a
> > >>>>>>>>>>> comma
> > >>>>>>>>>>>> in
> > >>>>>>>>>>>>>>> keys
> > >>>>>>>>>>>>>>>> or values.  This should be addressed somehow -- either
> > >>>>> by
> > >>>>>>>>>>> supporting
> > >>>>>>>>>>>>>> via
> > >>>>>>>>>>>>>>> an
> > >>>>>>>>>>>>>>>> escaping mechanism or by explicitly acknowledging that
> > >>>>> it
> > >>>>>>> is
> > >>>>>>>>>>>>>> unsupported.
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>> Thanks for the KIP and the simultaneous PR -- having
> > >>>>> both
> > >>>>>>> at
> > >>>>>>>>>> the
> > >>>>>>>>>>>> same
> > >>>>>>>>>>>>>>> time
> > >>>>>>>>>>>>>>>> really helped.
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>> Ron
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>> On Tue, Jul 17, 2018 at 6:22 PM Stanislav Kozlovski <
> > >>>>>>>>>>>>>>>> stanis...@confluent.io>
> > >>>>>>>>>>>>>>>> wrote:
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>>> Hey group,
> > >>>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>>> I just created a new KIP about adding customizable
> > >>>>> SASL
> > >>>>>>>>>>> extensions
> > >>>>>>>>>>>>>> to
> > >>>>>>>>>>>>>>> the
> > >>>>>>>>>>>>>>>>> OAuthBearer authentication mechanism. More details in
> > >>>>>> the
> > >>>>>>>>>>> proposal
> > >>>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>>> KIP:
> > >>>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> https://cwiki.apache.org/confluence/display/KAFKA/KIP-
> > >>>>> 342%
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>
> > >>>>>>>> 3A+Add+support+for+Custom+SASL+extensions+in+
> > >>>>> OAuthBearer+authentication
> > >>>>>>>>>>>>>>>>> JIRA: KAFKA-7169 <
> > >>>>>>>>>>>> https://issues.apache.org/jira/browse/KAFKA-7169>
> > >>>>>>>>>>>>>>>>> PR: Pull request <
> > >>>>>>>> https://github.com/apache/kafka/pull/5379>
> > >>>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>>> --
> > >>>>>>>>>>>>>>>>> Best,
> > >>>>>>>>>>>>>>>>> Stanislav
> > >>>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>> --
> > >>>>>>>>>>>>>>> Best,
> > >>>>>>>>>>>>>>> Stanislav
> > >>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>
> > >>>>>>>>>>>
> > >>>>>>>>>>>
> > >>>>>>>>>>> --
> > >>>>>>>>>>> Best,
> > >>>>>>>>>>> Stanislav
> > >>>>>>>>>>>
> > >>>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>> --
> > >>>>>>>>> Best,
> > >>>>>>>>> Stanislav
> > >>>>>>>>>
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>> --
> > >>>>>>>> Best,
> > >>>>>>>> Stanislav
> > >>>>>>>>
> > >>>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>>> --
> > >>>>>> Best,
> > >>>>>> Stanislav
> > >>>>>>
> > >>>>>
> > >>>
> > >>
> > >
> > >
> > > --
> > > Best,
> > > Stanislav
> >
>

Reply via email to