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

adding mtls config #1170

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Conversation

laurafitzgerald
Copy link
Contributor

@laurafitzgerald laurafitzgerald commented Feb 20, 2025

Closes #1157

Changes

  • add a boolean to spec to turn on/off the config
  • add permissions on PeerAuthentication
  • new mtls reconciler
  • configure logic
  • uncofigure logic
  • state of the world new watch and reconcile
  • link peer authentication to gateway logic
  • is limitador installed logic
  • Deployment.spec.template.label mutator
  • LinkDeploymentToLimitador
  • LinkDeploymentToAuthorino
  • tests

Verification steps
Run the following on this branch.
make local-setup
kubectl apply -f config/samples/kuadrant_v1beta1_kuadrant.yaml
Follow steps in https://docs.kuadrant.io/dev/kuadrant-operator/doc/user-guides/full-walkthrough/secure-protect-connect/
Update the kuadrant cr to enable mts using
kubectl patch kuadrant kuadrant-sample --type='json' -p='[{"op": "replace", "path": "/spec/mtls/enable", "value": true}]'
Verify that a Peer Authentication exists
kubectl get peerauthentication default -n default -o yaml
which has the following details

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  labels:
    kuadrant.io/managed: "true"
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT

Verify that the two envoyfilters have a CLUSTER patch with a key "transport_socket" in spec.configPatches applyTo CLUSTER.patch.value
kubectl get envoyfilter -A -o yaml

Verify that the limitador and authorino deployments have the expected labels
kubectl get deployment limitador-limitador -o yaml | yq e '.spec.template.metadata.labels' kubectl get deployment authorino -o yaml | yq e '.spec.template.metadata.labels'
Both should output

authorino-resource: authorino
control-plane: controller-manager
sidecar.istio.io/inject: "true

@laurafitzgerald laurafitzgerald requested a review from a team as a code owner February 20, 2025 13:10
@laurafitzgerald laurafitzgerald marked this pull request as draft February 20, 2025 13:12
Copy link
Contributor

@Boomatang Boomatang left a comment

Choose a reason for hiding this comment

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

There is a few comments that I have. I didn't try running this locally.

I would like to point out with the state of the world and the topology any time you find your self request data from the cluster you are doing something wrong

Comment on lines +27 to +41
func MergeMapStringString(modified *bool, existing *map[string]string, desired map[string]string) {
if *existing == nil {
*existing = map[string]string{}
}

// for each desired key value set, e.g. labels
// check if it's present in existing. if not add it to existing.
// e.g. preserving existing labels while adding those that are in the desired set.
for desiredKey, desiredValue := range desired {
if existingValue, exists := (*existing)[desiredKey]; !exists || existingValue != desiredValue {
(*existing)[desiredKey] = desiredValue
*modified = true
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we use labels.Set.Merge from the apimachinery to do this over defining our own.

Copy link
Contributor

Choose a reason for hiding this comment

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

it's not a map merge operation. It's doing what the comments say.

err = r.ReconcileResource(eventCtx, &v12.Deployment{}, deployment, reconcilers.DeploymentMutator(deploymentMutators...))
}

valueMap := map[string]interface{}{
Copy link
Contributor

Choose a reason for hiding this comment

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

Everything here being a map[sting]interface seems like a code smell.

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 believe this is the standard way that EnvoyFilter Config Object Patches arehandle. You can see an exmaple of this here https://github.com/Kuadrant/kuadrant-controller/blob/22535aa8e4f142bf07a69dc6391c84a59b232255/pkg/istio/envoy_filters.go#L14-L47


func IsLimitadorOperatorInstalled(restMapper meta.RESTMapper, logger logr.Logger) (bool, error) {
if ok, err := utils.IsCRDInstalled(restMapper, kuadrantv1beta1.LimitadorGroupKind.Group, kuadrantv1beta1.LimitadorGroupKind.Kind, limitadorv1alpha1.GroupVersion.Version); !ok || err != nil {
logger.V(1).Error(err, "Limitador Operator CRD was not installed", "group", kuadrantv1beta1.AuthorinoGroupKind.Group, "kind", kuadrantv1beta1.AuthorinoGroupKind.Kind, "version", authorinooperatorv1beta1.GroupVersion.Version)
Copy link
Contributor

Choose a reason for hiding this comment

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

Might want to fix the references to the authorino types here.

Copy link
Contributor

@Boomatang Boomatang 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 this is now at the stage where we need to be able to compile and run the operator to do a good review. It is getting close.

Comment on lines +65 to +68
type MTLS struct {
Enable bool `json:"enable,omitempty"`
}

Copy link
Contributor

Choose a reason for hiding this comment

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

At some point can you add a comment to what the mtls struct is for. The comment gets added to the CRD definition as a description. You will also need to run make manifest , bundle and helm at some point.

@laurafitzgerald laurafitzgerald force-pushed the mtls branch 3 times, most recently from da6de62 to e64e213 Compare March 12, 2025 12:45
@laurafitzgerald laurafitzgerald marked this pull request as ready for review March 12, 2025 12:45
Signed-off-by: Laura Fitzgerald <[email protected]>
…ts to limitador and authorino crs

Signed-off-by: Laura Fitzgerald <[email protected]>
…e other cleanup and it's runnable now

Signed-off-by: Laura Fitzgerald <[email protected]>
Signed-off-by: Laura Fitzgerald <[email protected]>
Signed-off-by: Laura Fitzgerald <[email protected]>
Signed-off-by: Laura Fitzgerald <[email protected]>
if kObj == nil && kObj.Spec.MTLS == nil && (!kObj.Spec.MTLS.Enable || anyAttachedAuthorRateLimitPolicy == false) {
defer logger.V(1).Info("mtls not enabled or applicable", "status", "completed")
peerAuthentications := lo.FilterMap(topology.Objects().Items(), func(item machinery.Object, _ int) (machinery.Object, bool) {
if peerAuthentication, ok := item.(*PeerAuthentication); ok {
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 isn't working yet. It's not picking up the exising PeerAuthentications.

Copy link
Contributor

@eguzki eguzki left a comment

Choose a reason for hiding this comment

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

Very good progress.

Few questions:

  • If the gateway provider is not Istio and a user enables mtls, should we report in kuadrant status?
  • When a user deletes a gateway, the peerAuthentications objects gets deleted? (not very important now and can be tackled in follow up PR's)

To: DeploymentGroupKind,
Func: func(child machinery.Object) []machinery.Object {
return lo.Filter(authorinos, func(k machinery.Object, _ int) bool {
return k.GetNamespace() == child.GetNamespace() && child.GetName() == "authorino"
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not very familiar with these linking functions. I still need to educate myself.

Question: child's type is Authorino, isn't it? Then, isn't this linking function linking all deployments in Authorino namespace to Authorino? even those that are not authorino deployment, like limitador deployment?

@@ -3,4 +3,6 @@ apiVersion: kuadrant.io/v1beta1
kind: Kuadrant
metadata:
name: kuadrant-sample
spec: {}
spec:
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the sample being shown in operatorhub web console. Do we want to add (optional) mtls config to it?

"tls_certificate_sds_secret_configs": []interface{}{
map[string]interface{}{
"name": "default",
"sds_config": map[string]interface{}{
Copy link
Contributor

Choose a reason for hiding this comment

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

Am I correct assuming that the gateway will fetch the client certificate from XDS interface?

@@ -56,6 +56,10 @@ func (r *IstioAuthClusterReconciler) Reconcile(ctx context.Context, _ []controll
if kuadrant == nil {
return nil
}
mtls := false
if kuadrant != nil && kuadrant.Spec.MTLS != nil && kuadrant.Spec.MTLS.Enable {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: when this kind of checks depend entirely on an object internal state and can be reused, they can be implemented in the object

diff --git a/api/v1beta1/kuadrant_types.go b/api/v1beta1/kuadrant_types.go
index 12bb1545..10316535 100644
--- a/api/v1beta1/kuadrant_types.go
+++ b/api/v1beta1/kuadrant_types.go
@@ -52,6 +52,14 @@ func (p *Kuadrant) GetLocator() string {
        return machinery.LocatorFromObject(p)
 }
 
+func (p *Kuadrant) IsMTLSEnabled() bool {
+       if p == nil {
+               return false
+       }
+
+       return p.Spec.MTLS != nil && p.Spec.MTLS.Enable
+}
+
 // KuadrantSpec defines the desired state of Kuadrant
 type KuadrantSpec struct {
        Observability Observability `json:"observability,omitempty"`

It works even when kuadrant object is nil.

targetables := topology.Targetables()
gateways := targetables.Items(func(o machinery.Object) bool {
gateway, ok := o.(*machinery.Gateway)
return ok && gateway.Spec.GatewayClassName == "istio"
Copy link
Contributor

Choose a reason for hiding this comment

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

It's better to check the GatewayClass instead of that. Check out how the observability reconciler is doing this https://github.com/Kuadrant/kuadrant-operator/blob/main/controllers/observability_reconciler.go#L399-L422

}
}
*/
func LinkDeploymentToAuthorino(objs controller.Store) machinery.LinkFunc {
Copy link
Contributor

Choose a reason for hiding this comment

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

"k8s.io/apimachinery/pkg/api/meta"
)

func IsLimitadorOperatorInstalled(restMapper meta.RESTMapper, logger logr.Logger) (bool, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is required to check the existence of the operator? Shouldn't it be Limitador itself?

Comment on lines +27 to +41
func MergeMapStringString(modified *bool, existing *map[string]string, desired map[string]string) {
if *existing == nil {
*existing = map[string]string{}
}

// for each desired key value set, e.g. labels
// check if it's present in existing. if not add it to existing.
// e.g. preserving existing labels while adding those that are in the desired set.
for desiredKey, desiredValue := range desired {
if existingValue, exists := (*existing)[desiredKey]; !exists || existingValue != desiredValue {
(*existing)[desiredKey] = desiredValue
*modified = true
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

it's not a map merge operation. It's doing what the comments say.

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.

Expose configuration in the kuadrant cr that controls the mTLS configuration by component
4 participants