Skip to content

Commit

Permalink
Add automatic RBAC creation for k8sobjects receiver (#3430)
Browse files Browse the repository at this point in the history
* Add automatic RBAC creation for k8sobjects receiver

Signed-off-by: Israel Blancas <[email protected]>

* Fix documentation

Signed-off-by: Israel Blancas <[email protected]>

* Move to v1beta1

Signed-off-by: Israel Blancas <[email protected]>

---------

Signed-off-by: Israel Blancas <[email protected]>
  • Loading branch information
iblancasa authored Nov 15, 2024
1 parent dfa7dcb commit 7e6b3cf
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .chloggen/3429.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
component: collector

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Create RBAC rules for the k8sobjects receiver automatically.

# One or more tracking issues related to the change
issues: [3429]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
3 changes: 3 additions & 0 deletions internal/components/receivers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ var (
components.NewBuilder[k8seventsConfig]().WithName("k8s_events").
WithRbacGen(generatek8seventsRbacRules).
MustBuild(),
components.NewBuilder[k8sobjectsConfig]().WithName("k8sobjects").
WithRbacGen(generatek8sobjectsRbacRules).
MustBuild(),
NewScraperParser("prometheus"),
NewScraperParser("sshcheck"),
NewScraperParser("cloudfoundry"),
Expand Down
49 changes: 49 additions & 0 deletions internal/components/receivers/k8sobjects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright The OpenTelemetry Authors
//
// Licensed 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 receivers

import (
"github.com/go-logr/logr"
rbacv1 "k8s.io/api/rbac/v1"
)

type k8sobjectsConfig struct {
Objects []k8sObject `yaml:"objects"`
}

type k8sObject struct {
Name string `yaml:"name"`
Mode string `yaml:"mode"`
Group string `yaml:"group,omitempty"`
}

func generatek8sobjectsRbacRules(_ logr.Logger, config k8sobjectsConfig) ([]rbacv1.PolicyRule, error) {
// https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/k8sobjectsreceiver#rbac
prs := []rbacv1.PolicyRule{}
for _, obj := range config.Objects {
permissions := []string{"list"}
if obj.Mode == "pull" && (obj.Name != "events" && obj.Name != "events.k8s.io") {
permissions = append(permissions, "get")
} else if obj.Mode == "watch" {
permissions = append(permissions, "watch")
}
prs = append(prs, rbacv1.PolicyRule{
APIGroups: []string{obj.Group},
Resources: []string{obj.Name},
Verbs: permissions,
})
}
return prs, nil
}
136 changes: 136 additions & 0 deletions internal/components/receivers/k8sobjects_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright The OpenTelemetry Authors
//
// Licensed 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 receivers

import (
"testing"

"github.com/go-logr/logr"
"github.com/stretchr/testify/assert"
rbacv1 "k8s.io/api/rbac/v1"
)

func Test_generatek8sobjectsRbacRules(t *testing.T) {
tests := []struct {
name string
config k8sobjectsConfig
want []rbacv1.PolicyRule
}{
{
name: "basic watch mode",
config: k8sobjectsConfig{
Objects: []k8sObject{
{
Name: "pods",
Mode: "watch",
Group: "v1",
},
},
},
want: []rbacv1.PolicyRule{
{
APIGroups: []string{"v1"},
Resources: []string{"pods"},
Verbs: []string{"list", "watch"},
},
},
},
{
name: "pull mode with events",
config: k8sobjectsConfig{
Objects: []k8sObject{
{
Name: "events",
Mode: "pull",
Group: "v1",
},
},
},
want: []rbacv1.PolicyRule{
{
APIGroups: []string{"v1"},
Resources: []string{"events"},
Verbs: []string{"list"},
},
},
},
{
name: "pull mode with non-events",
config: k8sobjectsConfig{
Objects: []k8sObject{
{
Name: "pods",
Mode: "pull",
Group: "v1",
},
},
},
want: []rbacv1.PolicyRule{
{
APIGroups: []string{"v1"},
Resources: []string{"pods"},
Verbs: []string{"list", "get"},
},
},
},
{
name: "multiple objects",
config: k8sobjectsConfig{
Objects: []k8sObject{
{
Name: "pods",
Mode: "pull",
Group: "v1",
},
{
Name: "events",
Mode: "pull",
Group: "v1",
},
{
Name: "deployments",
Mode: "watch",
Group: "apps/v1",
},
},
},
want: []rbacv1.PolicyRule{
{
APIGroups: []string{"v1"},
Resources: []string{"pods"},
Verbs: []string{"list", "get"},
},
{
APIGroups: []string{"v1"},
Resources: []string{"events"},
Verbs: []string{"list"},
},
{
APIGroups: []string{"apps/v1"},
Resources: []string{"deployments"},
Verbs: []string{"list", "watch"},
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := generatek8sobjectsRbacRules(logr.Logger{}, tt.config)
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
4 changes: 4 additions & 0 deletions tests/e2e-automatic-rbac/receiver-k8sobjects/00-install.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: chainsaw-k8sobjects
31 changes: 31 additions & 0 deletions tests/e2e-automatic-rbac/receiver-k8sobjects/01-assert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: simplest-chainsaw-k8sobjects-cluster-role
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- list
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: opentelemetry-collector
app.kubernetes.io/instance: chainsaw-k8sobjects.simplest
app.kubernetes.io/managed-by: opentelemetry-operator
app.kubernetes.io/name: simplest-chainsaw-k8sobjects-collector
app.kubernetes.io/part-of: opentelemetry
name: simplest-chainsaw-k8sobjects-collector
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: simplest-chainsaw-k8sobjects-cluster-role
subjects:
- kind: ServiceAccount
name: simplest-collector
namespace: chainsaw-k8sobjects
22 changes: 22 additions & 0 deletions tests/e2e-automatic-rbac/receiver-k8sobjects/01-install.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: simplest
namespace: chainsaw-k8sobjects
spec:
config:
receivers:
k8sobjects:
auth_type: serviceAccount
objects:
- name: pods
mode: pull
processors:
exporters:
debug:
service:
pipelines:
traces:
receivers: [k8sobjects]
processors: []
exporters: [debug]
18 changes: 18 additions & 0 deletions tests/e2e-automatic-rbac/receiver-k8sobjects/chainsaw-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: receiver-k8sobjects
spec:
steps:
- name: create-namespace
try:
- apply:
file: 00-install.yaml
- name: pod-pull-config
try:
- apply:
file: 01-install.yaml
- assert:
file: 01-assert.yaml

0 comments on commit 7e6b3cf

Please sign in to comment.