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