Hi Stanislav.  Could you update the KIP to reflect the latest definition of
SaslExtensions and confirm or correct the impact it has to the
SCRAM-related classes?  I'm not sure if the currently-described impact is
still accurate.  Also, could you mention the changes to
OAuthBearerUnsecuredLoginCallbackHandler in the text in addition to giving
the examples?  The examples show the new
unsecuredLoginExtension_<extensionName> feature, but that feature is not
described anywhere prior to it appearing there.

Ron

On Mon, Jul 23, 2018 at 1:42 PM Ron Dagostino <rndg...@gmail.com> wrote:

> 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