Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a custom SASL config option to the Topic Operator #5473 #9606

Merged
merged 103 commits into from
Apr 17, 2024

Conversation

john-mcpeek
Copy link
Contributor

Type of change

Enhancement

Description

I added a custom SASL_MECHANISM so that the Topic Operator in standalone can be used to manage topics in MSK with IAM for example.

Checklist

Please go through this checklist and make sure all applicable tasks have been done

  • Write tests
  • Make sure all tests pass
  • Update documentation
  • Check RBAC rights for Kubernetes / OpenShift roles - NA
  • Try your changes from Pod inside your Kubernetes and OpenShift cluster, not just locally
  • Reference relevant issue(s) and close them after merging
  • Update CHANGELOG.md
  • Supply screenshots for visual changes, such as Grafana dashboards - NA

@scholzj scholzj added this to the 0.40.0 milestone Jan 27, 2024
@scholzj
Copy link
Member

scholzj commented Jan 27, 2024

Thanks for the PR. @tombentley @fvaleri please have a look at it as you are the SMEs for the Topic Operator.

john-mcpeek and others added 4 commits January 28, 2024 09:00
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
…okers still in use (strimzi#9585)

Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
@john-mcpeek john-mcpeek force-pushed the custom-topic-operator-sasl-config-5473 branch from 3fbec7a to 3a50659 Compare January 28, 2024 14:10
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
@scholzj
Copy link
Member

scholzj commented Jan 28, 2024

/azp run regression

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@scholzj
Copy link
Member

scholzj commented Jan 28, 2024

/azp run feature-gates-regression

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Contributor

@fvaleri fvaleri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @john-mcpeek, I think this is a useful feature, thanks. Left some comments.

@@ -144,6 +144,28 @@ env:
<3> The keystore contains the private key for mTLS authentication.
<4> The password for accessing the keystore.

. If you need a custom `SASL` configuration. For example, to access a cluster in a cloud provider with a custom login module, the `custom` `SASL_MECHANISM` allows for `SASL_CUSTOM_CONFIG`. +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add "custom" to the SASL mechanism list on line 118, and rework the documentation about mandatory fields (STRIMZI_SASL_USERNAME and STRIMZI_SASL_PASSWORD are not mandatory with custom).

The same custom SASL config is available for the BTO, so we should also update that documentation.

In order to use the new "custom" SASL mechanism, I guess you would need to extend the default Strimzi operator image to add the required AWS libraries, but there is no mention in the documentation. It would be good to provide an example for AWS_MSK_IAM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expected that if you need AWS IAM or AZURE, etc. you would create an image with those so we don't have to include every possible jar. I would like an standard mechanism for external jars other than a new image, but that may be a different conversation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't know what you mean by BTO?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like an standard mechanism for external jars other than a new image, but that may be a different conversation.

As you say, we can discuss that in a separate thread, but for now, we should include a Dockerfile example for this specific use case, so that other users can easily adapt to their needs.

Sorry, I don't know what you mean by BTO?

Bidirectional Topic Operator, it's the old deprecated implementation. In the latest Strimzi release you have the UTO (Unidirectional Topic Operator) enabled by default. https://strimzi.io/blog/2023/11/02/unidirectional-topic-operator

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roger that, I get that in Dockerfile example.

Ah, I see, I'll get on that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On another note, the details of a working example might be a lot for the docs. What do you all think of a separate doc to explain the AWS example with a link in the Standalone doc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a repo I did to show the example. MSK-IAM-Example

Copy link
Contributor

@fvaleri fvaleri Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a generic Dockerfile example with placeholders is enough. As mentioned before, we should also update the BTO documentation. Alternatively, we can only implement and document this feature for the UTO, as the BTO is going away in two releases.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, BTO is scheduled for removal in 0.41. So unless we change it it will be gone in few weeks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTO is gone in the meantime, so less work to do :)

String key = entry.getKey();
String value = entry.getValue();

if (key == null || key.isBlank() || !key.startsWith("sasl.")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also detect the use of one of the standard sasl.mechanism that we support (plain, scram-sha-256, scram-sha-512).

String key = entry.getKey();
String value = entry.getValue();

if (key == null || key.isBlank() || !key.startsWith("sasl.")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also detect the use of one of the standard sasl.mechanism that we support (plain, scram-sha-256, scram-sha-512).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already do that is setSaslConfigs(). If they need this then I think limiting them could be counter productive.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we provide two ways to do the same thing? What's the use case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me like they could need a custom JAAS login module and a standard sasl mechanism. We don't know what they will need.

If you are dead set on it, I'll add the check.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @john-mcpeek has a point here: There are use cases where people want to do funky things with SASL-PLAIN and a custom module, so let's allow this.

@@ -406,12 +413,62 @@ private TopicStore createTopicStore(Zk zk, Config config) {
}

private void setSaslConfigs(Properties kafkaClientProps) {
String saslMechanism;
String jaasConfig;
String configSaslMechanism = config.get(Config.SASL_MECHANISM);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check for empty config, which is different from invalid mechanism.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty or invalid is the same result. Are you meaning a different error message like "SASL_MECHANISM is empty"?

Copy link
Contributor

@fvaleri fvaleri Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but Tom proposed to drop this, and I agree.

CHANGELOG.md Outdated Show resolved Hide resolved
return kafkaClientProps;
}

private void putSaslConfigs(Map<String, Object> kafkaClientProps) {
TopicOperatorConfig config = this;
String configSaslMechanism = config.saslMechanism();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check for empty config, which is different from invalid mechanism.

john-mcpeek and others added 5 commits January 29, 2024 08:25
Co-authored-by: Federico Valeri <fedevaleri@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
….java

Co-authored-by: Federico Valeri <fedevaleri@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
…cOperatorConfig.java

Co-authored-by: Federico Valeri <fedevaleri@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
…cOperatorConfig.java

Co-authored-by: Federico Valeri <fedevaleri@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Copy link
Member

@tombentley tombentley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, this would be a useful addition.

@@ -144,6 +144,28 @@ env:
<3> The keystore contains the private key for mTLS authentication.
<4> The password for accessing the keystore.

. If you need a custom `SASL` configuration. For example, to access a cluster in a cloud provider with a custom login module, the `custom` `SASL_MECHANISM` allows for `SASL_CUSTOM_CONFIG`. +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expected that if you need AWS IAM or AZURE, etc. you would create an image with those so we don't have to include every possible jar.

You should explain this in the documentation. Right now someone reading it might not guess all the steps you're expecting them to make.

@@ -144,6 +144,28 @@ env:
<3> The keystore contains the private key for mTLS authentication.
<4> The password for accessing the keystore.

. If you need a custom `SASL` configuration. For example, to access a cluster in a cloud provider with a custom login module, the `custom` `SASL_MECHANISM` allows for `SASL_CUSTOM_CONFIG`. +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

org.apache.kafka.common.errors.InvalidRequestException: Amazon MSK Serverless doesn't support fetching broker or broker-logger configurations

Perhaps one way to handle this would be to allow the skipping of this check with an env var, e.g. ASSUME_AUTO_CREATE_TOPICS=FALSE. If this was not set we'd do the check which we currently do. If it was =FALSE then we just trust that the person configuring the operator is correct and skip the check. And in the unlikely case where it's =TRUE we fail in the same way as if we'd done the check ourselves.

env:
- name: SASL_MECHANISM # <1>
value: custom
- name: SASL_CUSTOM_CONFIG # <2>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I wonder if SASL_CUSTOM_CONFIG_JSON would be clearer.
  2. But also, did you consider using Properties format rather than JSON? Users would likely be familiar with this because it's what the Kafka Java client's use, so it might avoid them having to convert something they already have as Properties format into JSON.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I like adding JSON to the name.
  2. JSONs easy to parse and I was worried about how it could be a mess getting people to understand the value as properties, but taking properties shouldn't be a big change if you would prefer that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was worried about how it could be a mess getting people to understand the value as properties, but taking properties shouldn't be a big change if you would prefer that.

That's a good point. The case of accidentally using folded style block strings (>), like this, bothers me

- name: SASL_CUSTOM_CONFIG_PROPERTIES
  value: >
    sasl.mechanism: AWS_MSK_IAM
    sasl.jaas.config: software.amazon.msk.auth.iam.IAMLoginModule required;
    sasl.client.callback.handler.class: software.amazon.msk.auth.iam.IAMClientCallbackHandler

That's legal YAML and legal .properties format, but it's not what the user intended because it's just the single key sasl.mechanism with a malformed value made up of the real value and the remaining keys and values. Kafka itself would catch that when/if there was sufficient validation on the first property defined. I think there's a similar issue with plain flow scalar strings. (I guess this kind of problem is worse than other common YAML problems, like writing foo: true [where the value is expected to be a string not a boolean, so needs to be quoted] precisely because in this case the expected and actual types are the same, so it's less likely to be caught.)

So I agree, on balance, that although the JSON is ugly it's less likely to be parsed wrongly.

Can we though:

  • Call it SASL_CUSTOM_CONFIG_JSON
  • Configure the ObjectMapper to support comments. It's non-standard, but I think people might appreciate the possibility to comment on why/how they're setting individual properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I'm working on now. Is SASL_CUSTOM_CONFIG_JSON and not having a custom type the solution we are going with?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@john-mcpeek yes, I think that's what we landed on, right @fvaleri ?

john-mcpeek and others added 7 commits January 31, 2024 19:01
….java

Co-authored-by: Tom Bentley <tombentley@users.noreply.github.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
….java

Co-authored-by: Tom Bentley <tombentley@users.noreply.github.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
….java

Co-authored-by: Tom Bentley <tombentley@users.noreply.github.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
….java

Co-authored-by: Tom Bentley <tombentley@users.noreply.github.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
…cOperatorConfig.java

Co-authored-by: Tom Bentley <tombentley@users.noreply.github.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
@john-mcpeek
Copy link
Contributor Author

@PaulRMellor I like the re-wording. Thank you.

@scholzj
Copy link
Member

scholzj commented Apr 12, 2024

/azp run kraft-regression

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@scholzj
Copy link
Member

scholzj commented Apr 12, 2024

@john-mcpeek Just FYI: you do not have to rebase the PR all the time. It would be needed only if there would be some conflict.

@scholzj
Copy link
Member

scholzj commented Apr 12, 2024

/azp run kraft regression

Copy link

No pipelines are associated with this pull request.

@scholzj
Copy link
Member

scholzj commented Apr 12, 2024

/azp run kraft-regression

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@john-mcpeek
Copy link
Contributor Author

@john-mcpeek Just FYI: you do not have to rebase the PR all the time. It would be needed only if there would be some conflict.

Roger that, thank you.

@john-mcpeek
Copy link
Contributor Author

@scholzj What's next?

@fvaleri
Copy link
Contributor

fvaleri commented Apr 15, 2024

@john-mcpeek, regression tests are all green, so I think we are just waiting for the final reviews from @tombentley and @PaulRMellor.

Copy link
Contributor

@PaulRMellor PaulRMellor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good. A couple of nits and I also think we should add something to the intro, as suggested

john-mcpeek and others added 3 commits April 15, 2024 13:03
…ndalone.adoc

Co-authored-by: PaulRMellor <47596553+PaulRMellor@users.noreply.github.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
…ndalone.adoc

Co-authored-by: PaulRMellor <47596553+PaulRMellor@users.noreply.github.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: John McPeek <juan.mcpeek@gmail.com>
Copy link
Contributor

@PaulRMellor PaulRMellor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

Copy link
Member

@tombentley tombentley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks @john-mcpeek!

private void skipNonAlterableConfigs(Set<AlterConfigOp> alterConfigOps) {
var alterableConfigs = config.alterableTopicConfig();
if (alterableConfigs != null && alterConfigOps != null && !alterableConfigs.isEmpty()) {
if (alterableConfigs.equalsIgnoreCase("none")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

despite there is an ignore case, you are mentioning "none" (lower case) here but "NONE" (upper case) in the previous doc. I would stick with the same on both, i.e. "none" lower case.

Copy link
Contributor

@fvaleri fvaleri Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, let's keep them aligned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so, "none" everywhere including the documentation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say yes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we do for other similar options? Didn't @fvaleri before suggest to use uppercase? This should be also consistent with the ALL I guess?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am just for consistency so even the upper case is fine with me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guys, I just need an answer. Upper or lower? Please.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@john-mcpeek Well, it makes no sense to have none and ALL. So one way or another there will be another change needed. It was actually @tombentley who suggested upper case in #9606 (comment) and I think his logic makes sense. So if Paolo doesn't care you should go with uppercase everywhere.

Copy link
Contributor

@fvaleri fvaleri Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tom originally suggested to have all uppercase as it is more evident comparing to regular configuration, which is lowercase. So let's use UPPERCASE (NONE and ALL).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think we are NONE and ALL everywhere now.


if (reconcilableTopic != null && reconcilableTopic.kt() != null
&& hasConfig(reconcilableTopic.kt()) && alterableConfigs != null) {
if (alterableConfigs.equalsIgnoreCase("NONE")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again despite the ignore case, why are you using "NONE" here instead of "none" as before? I would make consistency everywhere, even across the documentation part.

Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
Signed-off-by: john-mcpeek <juan.mcpeek@gmail.com>
@scholzj scholzj merged commit 14d5ed1 into strimzi:main Apr 17, 2024
13 checks passed
@scholzj
Copy link
Member

scholzj commented Apr 17, 2024

Thanks a lot for the contribution @john-mcpeek.

@fvaleri
Copy link
Contributor

fvaleri commented Apr 17, 2024

Thanks @john-mcpeek, and congrats for your first contribution. Well done.

@john-mcpeek
Copy link
Contributor Author

Thanks @scholzj @fvaleri @tombentley @ppatierno @PaulRMellor, it was an adventure :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants