Skip to content

Allow Access Operator deploy to a single Namespace or multiple Namespaces#112

Open
OwenCorrigan76 wants to merge 9 commits intostrimzi:mainfrom
OwenCorrigan76:Deploy_with_single_namespace
Open

Allow Access Operator deploy to a single Namespace or multiple Namespaces#112
OwenCorrigan76 wants to merge 9 commits intostrimzi:mainfrom
OwenCorrigan76:Deploy_with_single_namespace

Conversation

@OwenCorrigan76
Copy link
Contributor

@OwenCorrigan76 OwenCorrigan76 commented Nov 26, 2025

By default, the Kafka Access Operator watches all namespaces. This PR allows deployment of a KafkaAccess resource in a defined namespace or namespaces, by using the Optional env STRIMZI_NAMESPACE.
For example:

          env:
            - name: STRIMZI_NAMESPACE
              value: "myproject, test"

This PR fixes:
#106

@OwenCorrigan76 OwenCorrigan76 added this to the 0.3.0 milestone Nov 26, 2025
@OwenCorrigan76 OwenCorrigan76 force-pushed the Deploy_with_single_namespace branch 2 times, most recently from 2f7d88d to ba9f2cb Compare January 28, 2026 13:00
Comment on lines 36 to 43
Set<String> namespaces =
strimziNamespace == null ? Set.of() :
Arrays.stream(strimziNamespace.split(","))
.map(String::trim)
.collect(Collectors.toSet());

operator.register(new KafkaAccessReconciler(operator.getKubernetesClient()),
o -> o.settingNamespaces(namespaces));
Copy link
Member

Choose a reason for hiding this comment

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

Will this work when we configure to watch all (or any) Namespace? That means when you configure STRIMZI_NAMESPACE to *
I think you will need in that case o.watchingAllNamespaces().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the comment @im-konge. That makes sense. Will implement this.

Copy link
Member

Choose a reason for hiding this comment

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

FMPOV you should not have multiple files containing RoleBinding for each Namespace - similarly to the Cluster Operator (and what we have in docs) you can just have one and if needed, it can be created in every Namespace the operator will watch.

@OwenCorrigan76 OwenCorrigan76 force-pushed the Deploy_with_single_namespace branch 4 times, most recently from b74bb48 to 96bb8fb Compare February 12, 2026 11:26
@OwenCorrigan76 OwenCorrigan76 marked this pull request as ready for review February 12, 2026 11:41
@OwenCorrigan76 OwenCorrigan76 self-assigned this Feb 12, 2026
@OwenCorrigan76 OwenCorrigan76 changed the title Allow Access Operator deploy to a single Namespace Allow Access Operator deploy to a single Namespace or multiple Namespaces Feb 12, 2026
operator.register(new KafkaAccessReconciler(operator.getKubernetesClient()));

String strimziNamespace = System.getenv("STRIMZI_NAMESPACE");
if (strimziNamespace != null && strimziNamespace.matches("\\*")) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (strimziNamespace != null && strimziNamespace.matches("\\*")) {
if (strimziNamespace != null && strimziNamespace.equals("*")) {

I think this will be better than the regex stuff.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, as Jakub mentioned couple of times even before, this is the best thing:

Suggested change
if (strimziNamespace != null && strimziNamespace.matches("\\*")) {
if ("*".equals(strimziNamespace)) {

and you don't need the null check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored

.withUseSSAToPatchPrimaryResource(false));
operator.register(new KafkaAccessReconciler(operator.getKubernetesClient()));

String strimziNamespace = System.getenv("STRIMZI_NAMESPACE");
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if having something like this:

Suggested change
String strimziNamespace = System.getenv("STRIMZI_NAMESPACE");
String strimziNamespace = System.getenv().getOrDefault("STRIMZI_NAMESPACE", "*");

would be better.
TBH it would be better to have some configuration class that would check everything and return configuration for the operator, but I don't think it's scope of this PR.
That way you would keep the current behavior of the operator -> in case that you didn't configure this env variable, the operator will watch all Namespaces. Otherwise it will watch the set of Namespaces configured inside the STRIMZI_NAMESPACE env variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Default added.

Comment on lines 41 to 45
Set<String> namespaces =
strimziNamespace == null ? Set.of() :
Arrays.stream(strimziNamespace.split(","))
.map(String::trim)
.collect(Collectors.toSet());
Copy link
Member

Choose a reason for hiding this comment

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

So I think that this is not the correct way. What will happen when you pass the empty list of Namespaces into the settingNamespaces() method?
I would change the if-else here:

  • check if the strimziNamespace is null or empty (the null shouldn't happen here, but it's better to be safe)
  • then check if it's wildcard (you should cover also cases when you have space there - so using trim())
  • I think you should cover case when you have wildcard and Namespace there (so something like - *,namespace-0)
  • then you can split it by the ,
  • if there is something wrong, you should throw exception and not pass there empty Set

You can check how it's done in cluster-operator: https://github.com/strimzi/strimzi-kafka-operator/blob/main/operator-common/src/main/java/io/strimzi/operator/common/config/ConfigParameterParser.java#L179-L195

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it better now with the latest changes?

assertThat(currentKafkaAccess).isNotNull();
currentKafkaAccess.getSpec().setSecretName(NEW_USER_PROVIDED_SECRET_NAME);
client.resources(KafkaAccess.class).resource(currentKafkaAccess).update();
updated = true;
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't break be better than having another boolean value?
Also, if you would like to keep it, I would use different loop type - like while, which you can break and then fail inside it.

However what I saw as the cleanest solution is to use the edit:

        client.resources(KafkaAccess.class).resource(currentKafkaAccess).edit(ka -> {
            ka.getSpec().setSecretName(NEW_USER_PROVIDED_SECRET_NAME);
            return ka;
        });

or

        client.resources(KafkaAccess.class).resource(currentKafkaAccess).edit(ka -> new KafkaAccessBuilder(ka)
            .editOrNewSpec()
                .withSecretName(NEW_USER_PROVIDED_SECRET_NAME)
            .endSpec()
            .build()
        );

it should handle the conflict IIRC.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @im-konge. Changed

OwenCorrigan76 and others added 5 commits February 25, 2026 10:40
Signed-off-by: OwenCorrigan76 <owencorrigan76@gmail.com>
Signed-off-by: ocorriga <ocorriga@redhat.com>
Signed-off-by: ocorriga <ocorriga@redhat.com>
Signed-off-by: ocorriga <ocorriga@redhat.com>
Signed-off-by: ocorriga <ocorriga@redhat.com>
@OwenCorrigan76 OwenCorrigan76 force-pushed the Deploy_with_single_namespace branch 2 times, most recently from 7292fef to 43dd26b Compare February 25, 2026 13:25
Signed-off-by: ocorriga <ocorriga@redhat.com>
@OwenCorrigan76 OwenCorrigan76 force-pushed the Deploy_with_single_namespace branch from 43dd26b to b2ce8a1 Compare February 25, 2026 13:39
ocorriga added 2 commits February 25, 2026 14:40
Signed-off-by: ocorriga <ocorriga@redhat.com>
Signed-off-by: ocorriga <ocorriga@redhat.com>
@OwenCorrigan76
Copy link
Contributor Author

@im-konge @katheris Systemtests seem to be timing out in the Azure pipeline. Not sure what the issue is by looking at the logs??

@im-konge
Copy link
Member

im-konge commented Feb 25, 2026

@im-konge @katheris Systemtests seem to be timing out in the Azure pipeline. Not sure what the issue is by looking at the logs??

You should check what is happening in AZPs, it seems to be related to your changes. If there is nothing useful in the logs, you need to check the STs locally, debug the things.

Also it doesn't fail just on AZP, but also GHA, that means there is something wrong in your changes.

Signed-off-by: ocorriga <ocorriga@redhat.com>
Copy link
Member

@scholzj scholzj left a comment

Choose a reason for hiding this comment

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

I think the main issue with this is that it is breaking compatibility. AFAIU, the AO was watching all namespaces by default before. So it should probably continue to do so now? Otherwise, the upgrade likely breaks it for almost everyone.

{{- if .Values.watchAnyNamespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
Copy link
Member

Choose a reason for hiding this comment

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

Why is the file named RoleBinding when it contains a ClusterRoleBinding?

@scholzj
Copy link
Member

scholzj commented Feb 26, 2026

I think the main issue with this is that it is breaking compatibility. AFAIU, the AO was watching all namespaces by default before. So it should probably continue to do so now? Otherwise, the upgrade likely breaks it for almost everyone.

Or at least I think that was not the intended way this should have been done. My understanding is that all it should have done was to add support for single namespace. Not switch to it.

@im-konge
Copy link
Member

im-konge commented Feb 26, 2026

I think the main issue with this is that it is breaking compatibility. AFAIU, the AO was watching all namespaces by default before. So it should probably continue to do so now? Otherwise, the upgrade likely breaks it for almost everyone.

Or at least I think that was not the intended way this should have been done. My understanding is that all it should have done was to add support for single namespace. Not switch to it.

Yes I think I mentioned it in one of the comments, that the STRIMZI_NAMESPACE should be * all as it was before.
But what I think that breaks the installation is this:

operator.register(new KafkaAccessReconciler(operator.getKubernetesClient()),
            configuration -> configuration.settingNamespaces(namespaces));

which (from what I saw in the documentation) works fine for single/multiple Namespaces, but doesn't work with the all Namespaces configuration and you should use o.watchingAllNamespaces(). You should probably bring it back.

I mean the code where you checked if the namespaces is just the * or not and based on that configured the operator was fine. Just the Namespace parsing needed some improvement.

@OwenCorrigan76
Copy link
Contributor Author

OwenCorrigan76 commented Feb 26, 2026

By watching all namespaces as default, we need to bring back the ClusterRoleBinding.yaml or?

@im-konge
Copy link
Member

By watching all namespaces as default, we need to bring back the ClusterRoleBinding.yaml or?

I think it depends. When you take a look on Strimzi Cluster Operator, we have there RoleBindings (for single/multiple Namespace deployment) and ClusterRole -> in case that you want to watch all Namespaces, you are creating the ClusterRoleBindings by command - you can anyway check the documentation how it's done: https://strimzi.io/docs/operators/latest/deploying#deploying-cluster-operator-to-watch-whole-cluster-str

However, if you would like to do it same way, you would have to have the change as you did with RoleBinding instead of ClusterRoleBinding, you will need to change it in the tests (because the change in STs is that it works now because we have single Namespace there, once you add test having multiple/all namespaces you will end up with same failure as you did now) and mainly you need to mention it in the documentation.

I think that during the upgrade users will anyway have the CRB already created, so we will have to mention it in the release notes for sure that there was this change.

From my side, I think having it consistent across repositories is a good thing. It will just be a bit of breaking change and users will need to change the way how they are installing the operator.

But I will leave others to say what they think about it.

@OwenCorrigan76
Copy link
Contributor Author

OwenCorrigan76 commented Feb 26, 2026

Thanks a mil @im-konge for the useful comments. Myself and @katheris discussed having compatibility with how it's done in the Cluster Operator and agreed that is was the best way to proceed. Also having the changes documented in the docs (that premature PR I opened a couple of weeks ago) but maybe others will disagree?

@im-konge
Copy link
Member

Thanks a mil @im-konge for the useful comments. Myself and @katheris discussed having compatibility with how it's done in the Cluster Operator and agreed that is was the best way to proceed. Also having the changes documented in the docs (that premature PR I opened a couple of weeks ago) but maybe others will disagree?

I wonder if it would make sense to have documentation stuff here as we have for Bridge - and I'm sure there was some discussion in the past. But in the operators, it was premature because there could be still some changes and you don't have new release of KAO yet (and then you have to add it to operators repo). That's why I think having the documentation here would help in these cases when you have some change, you want to have it prepared and then you can just use it in case that there is new release. However, I'm not sure what were the points why it's not here.

@im-konge im-konge linked an issue Feb 26, 2026 that may be closed by this pull request
@scholzj
Copy link
Member

scholzj commented Feb 26, 2026

Thanks a mil @im-konge for the useful comments. Myself and @katheris discussed having compatibility with how it's done in the Cluster Operator and agreed that is was the best way to proceed. Also having the changes documented in the docs (that premature PR I opened a couple of weeks ago) but maybe others will disagree?

You agreed on what? To change the default installation mode? (I mean, I'm not really sure what exactly you agreed on)

Set<String> namespaces = parseNamespaces(strimziNamespace);

operator.register(new KafkaAccessReconciler(operator.getKubernetesClient()),
configuration -> configuration.settingNamespaces(namespaces));
Copy link
Member

Choose a reason for hiding this comment

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

Does called configuration.settingNamespaces("*") really work?

Copy link
Member

Choose a reason for hiding this comment

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

No, that's why I had previous comment(s) about adding the watchingAllNamespaces().

@katheris
Copy link
Member

@im-konge @scholzj just to be clear on what Owen and I discussed here's my take. So today in the Access Operator by default we have a ClusterRoleBinding and the operator is watching all namespaces and is being granted access to all namespaces. However, I don't think that was something that was properly thought through and in hindsight was a mistake and as noted is different to what we have in the cluster-operator.

To be more secure by default I think the Access Operator installation files should be updated so that by default it is only granted access to a single namespace, and then we should document how to expand that to a set of namespaces or all namespaces.

This may cause a breaking change to users, however I think it provides a better experience both security wise and in terms of consistency, so as long as we properly document what users should do to maintain the old behaviour then I think this is acceptable.

Owen and I should have been clearer about this discussion and the change in direction from the original issue so I apologise for that. I'm happy to open a separate issue to be triaged formally if you would prefer to get input from the wider set of maintainers.

@OwenCorrigan76
Copy link
Contributor Author

Thanks for clarifying @katheris

@scholzj
Copy link
Member

scholzj commented Feb 26, 2026

@katheris Thanks for the explanation. To be honest, I disagree with it.

  • It will cause a lot of issues to users upgrading from previous versions. We know from experience that documentation doesn't really solve these issues.
  • It goes against the natural state of being for operators (with CRDs being cluster-wide, the natural state of the operator to be in is cluster-wide). So while the security is a good argument, there are also other arguments that go in a different direction.
  • I think that, unlike Cluster Operator, watching only one namespace is basically useless because it beats the whole purpose of the Access Operator. It will copy the data from one Secret to another Secret. So it would be hard to convince people of the value.
  • The system test changes that now seem to test only the mode that has the least value for the users is also pretty dangerous.
  • While the security aspect is important, I'm not sure what we get from having the default setup super-secure but completely crippled. And then tell the users that to use it they would need to anyway grant it the rights.

I wonder if we can make it more secure and more usable out of the box. For example by breaking the configuration:

  • where we watch for the KafkaAccess resources
  • where we watch for the Kafka / KafkaUser resources
  • Split the RBAC resources accordingly

Then you can, for example, have some default to pull the credentials from namespace A to namespace B that would make the purpose of the tool a bit more obvious. You would still break the compatibility. But the default would be somehow useful. And it will be more secure with a purpose. Instead of being more secure just to force everyone to reconfigure it to make it less secure and useful.

If this is something we want to do ... then it is really important to think about what Lukas mentioned with the documentation. You cannot release a breaking change with the idea that the docs will be released later with the next operator release. You need to document all of it here. For example in the README.md. You should ale make sure these things are super clear in the Helm Chart README.md (which I guess should have been updated in the first place).

@scholzj
Copy link
Member

scholzj commented Feb 26, 2026

PS: I do not want to constantly be the one breaking people's plans for Access Operator. So if you wanna do whatever you want with it, be my guest. But stop asking for my reviews 😜.

@katheris
Copy link
Member

@scholzj thanks, I think you do have valid points (which is why I ask for your reviews 😄 ) so we'll have a think

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.

Deploy operator with access to a set of namespaces

4 participants