Skip to content

RFC for mTLS#110

Merged
maleck13 merged 2 commits intomainfrom
mtls
Feb 23, 2026
Merged

RFC for mTLS#110
maleck13 merged 2 commits intomainfrom
mtls

Conversation

@david-martin
Copy link
Copy Markdown
Member

Follow on from investigation in Kuadrant/kuadrant-operator#1049 and a possible automated way to enable and manage mTLS for users instead of the manual documented way in Kuadrant/kuadrant-operator#1054

Signed-off-by: David Martin <davmarti@redhat.com>
Comment thread rfcs/0012-mtls.md

When enabled for a specific component, the following changes are performed by the kuadrant-operator and/or component operators. This may require trickling down configuration to other operator resources, like the Authorino or Limitador resources:

## Enabling the Istio sidecar proxy in that component
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should probably add a section for Envoy Gateway as well.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't know what to add for that.
The Istio approach takes advantage of Istio sidecar capabilities to enable mTLS in the kuadrant pods.
If Istio isn't there, would that be some other solution outside of Envoy Gatway completely?

Comment thread rfcs/0012-mtls.md
Comment on lines +30 to +32
mtls:
authorino: true
limitador: true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Although this could work for a first implementation, I wonder if it's clear to the user that the certs will be provisioned via Secret discovery service (SDS).

I can also see how non-mesh users could want this but by configuring certs by other means though. If we don't support such other means right away, should the API be more explicit about using SDS perhaps?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So the available options right now for mTLS seem quite limited (from reading this recent article https://blog.howardjohn.info/posts/mtls-kubernetes/)
There's either a sidecar approach (which this uses), ambient mode, a CNI approach (which doesn't exist yet), or DIY.
Is the abstraction too low if SDS is mentioned in the config?
What about an mTLS mode of 'mesh' being the initial option, with that meaning we'll integrate with the mesh if it's available i.e. if you're using Istio.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So what would be the minimum to allow configuring the certs. Would it just be to provide some paths to the CA for example? If so it would seem like a relatively simple adjustment to allow the needed paths to be provided under the mtls section. I haven't gone through that link in detail, but I can def see both use cases. One simple as possible just make mtls work. 2 the certs have to be specific certs from a the orgs CA etc

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

One thing I am thinking here is we could go with an opinionated mTLS but ensure we allow users to still change values directly if needed. So when reconciling, we would assert that the section is there but not overwrite any new config for example.
So out of the box you get a working version that uses SDS if you want more than that you can configure it directly and we wont overwrite it

Comment thread rfcs/0012-mtls.md

The corresponding EnvoyFilter for the component requires the following `transport_socket` configuration to be added:

```yaml
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@guicassolato I believe I am correct in saying we don't create these envoy filters until an Auth or RateLimit policy is created?
@david-martin I think we would need to make sure if mtls is enabled that part of marking the policy ready / accepted would mean ensuring this configuration was in place first.

Comment thread rfcs/0012-mtls.md
authorino: true
limitador: true
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it would be good to call out that if we don't support mTLS configuration for a gateway provider, it will be reflected in the status of the kuadrant resource. Also given how important this can be for users, kuadrant should probably not become ready until the specified mTLS can be handled or the mTLS section is removed.

Copy link
Copy Markdown
Collaborator

@maleck13 maleck13 left a comment

Choose a reason for hiding this comment

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

Some minor improvements suggest but, I like this as an initial pass at allowing configuration of mTLS when using Istio. Avoids users having to mess with resources owned by the kaudrant operator and also kuadrant users not needing to understand the innards of Envoy. It also seems relatively easy to extend with things like a specific CA etc.

Comment thread rfcs/0012-mtls.md
Comment on lines +30 to +32
mtls:
authorino: true
limitador: true
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think there is a design issue here. More so when we think of the whole CR and just this feature. As this feature only has two components that is affected this will be harder to visualize, but I will try explain it from a generic features point of view.

spec:
  feature:
    activate: false # optional, boolean, defaults to false
    enabled: [] # optional, list of strings
    disabled: [] # optional, list of strings

Under the feature all fields are optional to ensure backwards compatibility. The feature will not be activated on less the activate field is set to true. This allows the feature to be enabled or disabled without changing the configuration for that feature. A feature would have a list of defaults components that would be affected by the feature being enabled. In this case that would be two, authorino & limitador, but this would not always be the case.

If the user wanted to disable the feature on a component lets say limitador they would add the following spec.

spec:
  feature:
    activate: true 
    disabled: ['limitador']

In this example only limitador will not have the feature enabled, but also if any new components are added to the defaults list that will be auto enabled. Being auto enabled by default may not be what the user wants. That is where the enabled list comes in. If the user wants to only have the feature enabled for authorino no matter what components are add in the future they could use the following spec.

spec:
  feature:
    activate: true 
    enable: ['authorino']

The enable list would be an explicit list. Only components listed would be affected. This ensures that behaviour would not change if a component is added to the support list later in the future. However, if there are a lot of components that is supported by default filling this list in could be tedious, but as it is a string list there is nothing stopping use from supporting keywords like 'defaults'. An example of this being used could be service monitors whereby default we only add them to the operands. A user many also add them to the operator that they care about. The below example shows that looks like.

spec:
  feature:
    activate: true
    enable: 
      - 'defaults'
      - 'authorino-operator'

So advantage that I see with doing this design are.

  • All features have the same basic interface.
  • New components don't require CRD updates to be supported. The change will only be required with the operator.
  • The common interface make documentation simpler

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I like this approach.
Are the enabled & disabled lists mutually exclusive?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

At first pass I think they should be exclusive, but I am not sure how we would enforce that. There might be something that could be done with CEL black magic and sets. If CEL doesn't work, a validating web hook is always an option. The bigger question around exclusive comes if we decide to allow keywords such as 'defaults'. There may be a component in the default list that the user wants to disable.

The example the comes to mind is a generic feature that works on both the operand and operator, but we decide that by default it only applies to the operand. The default list could be:

- authorino
- limitador

In this case the user may not be using authorino but also wants to use the feature with the limitador operator. The configuration they create would be something like:

spec:
  generic_feature:
    activate: true
    enable:
      - 'defaults'
      - 'limitador-operator'
    disable:
      - 'authorino'

For clarity this is the list that the feature would be applied to with the above configuration.

- limitador
- limitador-operator

In this scenario when building the list of component to apply the feature too, the disable list needs to read secondary. If the list were exclusive the order should not matter.

I think the behaviour around the keywords like 'defaults' needs a bit more refinement to explain what is regarded as expected behaviour.

I understood the question to mean one thing, but on second pass I can see it could be asking a different question to what I answer. The second way could be; are the enabled & disabled lists mutually exclusive within the Kuadrant Spec? As in, you can only have one or the other but not both at the same time. If this was want was meant by the question the answer would be no they are not mutually exclusive. If they were configuration like that give in the scenario above would not be possible, and I think that is where the real value of this interface is.

@Boomatang
Copy link
Copy Markdown
Member

As this would be configured inside the kuadrant CR, it would be worth looking at #112 as it is trying to define a standardized API design for new features added to the kuadrant CR

Comment thread rfcs/0012-mtls.md Outdated
[unresolved-questions]: #unresolved-questions

- What components will create and manage the resources and configuration detailed above?
- What configuration options makes sense to bubble up via the Limitador and Authorino components, if any?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Discussion around this happening -> https://groups.google.com/a/redhat.com/g/kuadrant-dev/c/rbsY4kDaSnE
And at the community call -> https://docs.google.com/document/d/1Dkcqu1MgCJlvJHF_iCYibPNsnSHu1aIeG5-WoqlKtGU/edit?tab=t.0#heading=h.5a78l4pgyj90
Will relay the outcome here via update with an answer to this question.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The outcome was decided and communicated via a recent reply to the kuadrant-dev mailing list. We will no expose any config via limitador or authorino cr. Instead we will allow the addition of the label to the deployment.spec.template.labels by external user/component and the operators will not remove them.

@maleck13
Copy link
Copy Markdown
Collaborator

@david-martin not sure what state we are in with this one. We have the feature so is the RFC implemented and can be merged?

@maleck13
Copy link
Copy Markdown
Collaborator

@david-martin is this still relevant? Be good for it reflect the current state and be merged

Signed-off-by: David Martin <davmarti@redhat.com>
@david-martin
Copy link
Copy Markdown
Member Author

@maleck13 I've updated the rfc to reflect the current status (implemented) and how the spec looks.
I think we can merge this now.

Copy link
Copy Markdown
Collaborator

@maleck13 maleck13 left a comment

Choose a reason for hiding this comment

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

approving as this is in place now updates or changes can be added via a new RFC

@maleck13 maleck13 merged commit 014d24e into main Feb 23, 2026
2 checks passed
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.

5 participants