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

feat(knative): Rely on addressable-resolver ClusterRole to transfer RBAC for Knative Sinks (1.8.x backport) #2990

Merged
merged 9 commits into from
Feb 7, 2022
Merged
3 changes: 2 additions & 1 deletion config/rbac/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ resources:
- operator-role-binding.yaml
- operator-cluster-role-custom-resource-definitions.yaml
- operator-cluster-role-binding-custom-resource-definitions.yaml

- operator-cluster-role-addressable-resolver.yaml
- operator-cluster-role-binding-addressable-resolver.yaml
32 changes: 32 additions & 0 deletions config/rbac/operator-cluster-role-addressable-resolver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# ---------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ---------------------------------------------------------------------------

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: camel-k-operator-bind-addressable-resolver
labels:
app: "camel-k"
rules:
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterroles
resourceNames:
- addressable-resolver
verbs:
- bind
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ---------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ---------------------------------------------------------------------------

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: camel-k-operator-bind-addressable-resolver
labels:
app: "camel-k"
subjects:
- kind: ServiceAccount
name: camel-k-operator
namespace: placeholder
roleRef:
kind: ClusterRole
name: camel-k-operator-bind-addressable-resolver
apiGroup: rbac.authorization.k8s.io
15 changes: 0 additions & 15 deletions config/rbac/operator-role-knative.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,3 @@ rules:
- list
- patch
- update
# Required to resolve Addressable Sinks
# We may want to external it and make it extensible
- apiGroups:
- eventing.knative.dev
resources:
- brokers
verbs:
- get
- apiGroups:
- messaging.knative.dev
resources:
- channels
- inmemorychannels
verbs:
- get
1 change: 1 addition & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*** xref:installation/registry/icr.adoc[IBM Container Registry]
*** xref:installation/registry/k3s.adoc[K3s]
** Advanced
*** xref:installation/advanced/knative.adoc[Knative Sinks]
*** xref:installation/advanced/resources.adoc[Resource management]
*** xref:installation/advanced/multi.adoc[Multiple Operators]
* Command Line Interface
Expand Down
48 changes: 48 additions & 0 deletions docs/modules/ROOT/pages/installation/advanced/knative.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[[knative-sinks]]
= Knative Sinks

A https://knative.dev/docs/eventing/sinks[Knative Sink] can be referenced in a producer path of the Camel Knative component, e.g.:

[source,java]
----
from('timer:tick')
.setBody().constant('event')
.to('knative:event/broker')
----

Or as the value of the `sink` field in a `KameletBinding` resource, e.g.:

[source,yaml]
----
apiVersion: camel.apache.org/v1alpha1
kind: KameletBinding
metadata:
name: timer-source-binding
spec:
source:
ref:
kind: Kamelet
apiVersion: camel.apache.org/v1alpha1
name: timer-source
properties:
message: Event
sink:
ref:
kind: Broker
apiVersion: eventing.knative.dev/v1
name: broker
properties:
type: type
----

In the above examples, the Knative Sink is a https://knative.dev/docs/eventing/broker/[Knative Broker].
However, a Knative Sink can be any Kubernetes resource that's _addressable_, i.e., whose URL can be retrieved by reading its `status.address.url`.

This is what the Camel K operator does to resolve the Sink URLs, so that events can be sent to.
That requires the ServiceAccount that runs the operator to be granted permission to GET these resources, while it configures the integration runtime.

As the set of resources is arbitrary, and cannot be known _a-priori_, these permissions are automatically granted to `camel-k-operator` ServiceAccount, by relying on the Knative Addressable resolver aggregated ClusterRole.

For the above examples, that sink into an `eventing.knative.dev/broker` resource, this is already being configured by Knative, that aggregates the required permissions for its own resources by default.

However, if you integrate custom resources as sinks, the required permissions must be added manually, as documented in the https://knative.dev/docs/eventing/sinks/#using-custom-resources-as-sinks[Knative documentation].
6 changes: 3 additions & 3 deletions e2e/common/kustomize/common.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build integration
// +build integration

// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
Expand Down Expand Up @@ -46,7 +47,8 @@ const (

// camel-k-edit
// camel-k-operator-custom-resource-definitions
ExpKubeClusterRoles = 2
// camel-k-operator-bind-addressable-resolver
ExpKubeClusterRoles = 3

// camel-k-operator-openshift
ExpOSPromoteRoles = 1
Expand Down Expand Up @@ -75,8 +77,6 @@ func ExecMake(t *testing.T, command *exec.Cmd) {
}

func Uninstall() {
//
// Removes all items including CRDs and ClusterRoles
//
Kamel("uninstall", "--olm=false", "--all").Execute()
}
13 changes: 0 additions & 13 deletions helm/camel-k/templates/operator-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -235,19 +235,6 @@ rules:
- list
- patch
- update
- apiGroups:
- eventing.knative.dev
resources:
- brokers
verbs:
- get
- apiGroups:
- messaging.knative.dev
resources:
- channels
- inmemorychannels
verbs:
- get
- apiGroups:
- coordination.k8s.io
resources:
Expand Down
18 changes: 18 additions & 0 deletions pkg/install/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (

"github.com/apache/camel-k/pkg/client"
"github.com/apache/camel-k/pkg/resources"
"github.com/apache/camel-k/pkg/util/knative"
"github.com/apache/camel-k/pkg/util/kubernetes"
)

Expand Down Expand Up @@ -193,6 +194,23 @@ func SetupClusterWideResourcesOrCollect(ctx context.Context, clientProvider clie
}
}

isKnative, err := knative.IsInstalled(ctx, c)
if err != nil {
return err
}
if isKnative {
ok, err := isClusterRoleInstalled(ctx, c, "camel-k-operator-bind-addressable-resolver")
if err != nil {
return err
}
if !ok || collection != nil {
err := installResource(ctx, c, collection, "/rbac/operator-cluster-role-addressable-resolver.yaml")
if err != nil {
return err
}
}
}

return nil
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/install/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import (
"github.com/apache/camel-k/pkg/util/openshift"
)

const serviceAccountName = "camel-k-operator"

// ResourceCustomizer can be used to inject code that changes the objects before they are created.
type ResourceCustomizer func(object ctrl.Object) ctrl.Object

Expand Down
85 changes: 85 additions & 0 deletions pkg/install/knative.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package install

import (
"context"
"fmt"

rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

rbacv1ac "k8s.io/client-go/applyconfigurations/rbac/v1"
"k8s.io/client-go/kubernetes"

"github.com/apache/camel-k/pkg/util/knative"
)

const knativeAddressableResolverClusterRoleName = "addressable-resolver"

// BindKnativeAddressableResolverClusterRole binds the Knative Addressable resolver aggregated ClusterRole
// to the operator ServiceAccount.
func BindKnativeAddressableResolverClusterRole(ctx context.Context, c kubernetes.Interface, namespace string) error {
if isKnative, err := knative.IsInstalled(ctx, c); err != nil {
return err
} else if !isKnative {
return nil
}
if namespace != "" {
return applyAddressableResolverRoleBinding(ctx, c, namespace)
}
return applyAddressableResolverClusterRoleBinding(ctx, c, namespace)
}

func applyAddressableResolverRoleBinding(ctx context.Context, c kubernetes.Interface, namespace string) error {
rb := rbacv1ac.RoleBinding(fmt.Sprintf("%s-addressable-resolver", serviceAccountName), namespace).
WithSubjects(
rbacv1ac.Subject().
WithKind("ServiceAccount").
WithNamespace(namespace).
WithName(serviceAccountName),
).
WithRoleRef(rbacv1ac.RoleRef().
WithAPIGroup(rbacv1.GroupName).
WithKind("ClusterRole").
WithName(knativeAddressableResolverClusterRoleName))

_, err := c.RbacV1().RoleBindings(namespace).
Apply(ctx, rb, metav1.ApplyOptions{FieldManager: serviceAccountName, Force: true})

return err
}

func applyAddressableResolverClusterRoleBinding(ctx context.Context, c kubernetes.Interface, namespace string) error {
crb := rbacv1ac.ClusterRoleBinding(fmt.Sprintf("%s-addressable-resolver", serviceAccountName)).
WithSubjects(
rbacv1ac.Subject().
WithKind("ServiceAccount").
WithNamespace(namespace).
WithName(serviceAccountName),
).
WithRoleRef(rbacv1ac.RoleRef().
WithAPIGroup(rbacv1.GroupName).
WithKind("ClusterRole").
WithName(knativeAddressableResolverClusterRoleName))

_, err := c.RbacV1().ClusterRoleBindings().
Apply(ctx, crb, metav1.ApplyOptions{FieldManager: serviceAccountName, Force: true})

return err
}
Loading