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

Update securityContext to include required configurations when the flag el-security-context is enabled #1736

Merged
merged 1 commit into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/config-defaults-triggers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ data:
# default-service-account contains the default service account name
# to use for TaskRun and PipelineRun, if none is specified.
default-service-account: "default"
default-run-as-user: "65532"
default-run-as-group: "65532"
38 changes: 37 additions & 1 deletion pkg/apis/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@ limitations under the License.
package config

import (
"fmt"
"os"
"strconv"

corev1 "k8s.io/api/core/v1"
)

const (
defaultServiceAccountKey = "default-service-account"
defaultRunAsUserKey = "default-run-as-user"
defaultRunAsGroupKey = "default-run-as-group"
DefaultServiceAccountValue = "default"
defaultRunAsUserValue = 65532
defaultRunAsGroupValue = 65532
)

// Defaults holds the default configurations
// +k8s:deepcopy-gen=true
type Defaults struct {
DefaultServiceAccount string
DefaultRunAsUser int64
DefaultRunAsGroup int64
}

// GetDefaultsConfigName returns the name of the configmap containing all
Expand All @@ -52,19 +60,47 @@ func (cfg *Defaults) Equals(other *Defaults) bool {
return false
}

return other.DefaultServiceAccount == cfg.DefaultServiceAccount
return other.DefaultServiceAccount == cfg.DefaultServiceAccount &&
other.DefaultRunAsUser == cfg.DefaultRunAsUser &&
other.DefaultRunAsGroup == cfg.DefaultRunAsGroup
}

// NewDefaultsFromMap returns a Config given a map corresponding to a ConfigMap
func NewDefaultsFromMap(cfgMap map[string]string) (*Defaults, error) {
tc := Defaults{
DefaultServiceAccount: DefaultServiceAccountValue,
DefaultRunAsUser: defaultRunAsUserValue,
DefaultRunAsGroup: defaultRunAsGroupValue,
}

if defaultServiceAccount, ok := cfgMap[defaultServiceAccountKey]; ok {
tc.DefaultServiceAccount = defaultServiceAccount
}

if defaultRunAsUser, ok := cfgMap[defaultRunAsUserKey]; ok {
if defaultRunAsUser == "" {
tc.DefaultRunAsUser = 0
} else {
runAsUser, err := strconv.ParseInt(defaultRunAsUser, 10, 0)
if err != nil {
return nil, fmt.Errorf("failed parsing runAsUser config %q", defaultRunAsUser)
}
tc.DefaultRunAsUser = runAsUser
}
}

if defaultRunAsGroup, ok := cfgMap[defaultRunAsGroupKey]; ok {
if defaultRunAsGroup == "" {
tc.DefaultRunAsGroup = 0
} else {
runAsGroup, err := strconv.ParseInt(defaultRunAsGroup, 10, 0)
if err != nil {
return nil, fmt.Errorf("failed parsing runAsUser config %q", defaultRunAsGroup)
}
tc.DefaultRunAsGroup = runAsGroup
}
}

return &tc, nil
}

Expand Down
14 changes: 14 additions & 0 deletions pkg/apis/config/default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ func TestNewDefaultsFromConfigMap(t *testing.T) {
{
expectedConfig: &config.Defaults{
DefaultServiceAccount: "default",
DefaultRunAsUser: 65532,
DefaultRunAsGroup: 65532,
},
fileName: config.GetDefaultsConfigName(),
},
Expand All @@ -54,10 +56,22 @@ func TestNewDefaultsFromEmptyConfigMap(t *testing.T) {
DefaultsConfigEmptyName := "config-defaults-empty"
expectedConfig := &config.Defaults{
DefaultServiceAccount: "default",
DefaultRunAsUser: 65532,
DefaultRunAsGroup: 65532,
}
verifyConfigFileWithExpectedConfig(t, DefaultsConfigEmptyName, expectedConfig)
}

func TestNewDefaultsFromConfigMapWithEmptyVal(t *testing.T) {
DefaultsConfigEmptyVal := "config-defaults-triggers-empty-val"
expectedConfig := &config.Defaults{
DefaultServiceAccount: "default",
DefaultRunAsUser: 0,
DefaultRunAsGroup: 0,
}
verifyConfigFileWithExpectedConfig(t, DefaultsConfigEmptyVal, expectedConfig)
}

func TestEquals(t *testing.T) {
testCases := []struct {
name string
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/config/testdata/config-defaults-empty.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ data:
# default-timeout-minutes contains the default number of
# minutes to use for TaskRun, if none is specified.
default-service-accounts: "default"
default-run-as-user: "65532"
default-run-as-group: "65532"
23 changes: 23 additions & 0 deletions pkg/apis/config/testdata/config-defaults-triggers-empty-val.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2021 The Tekton 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
#
# https://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.

apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults-triggers
namespace: tekton-pipelines
data:
default-service-account: "default"
default-run-as-user: ""
default-run-as-group: ""
2 changes: 2 additions & 0 deletions pkg/apis/config/testdata/config-defaults-triggers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ metadata:
namespace: tekton-pipelines
data:
default-service-account: "default"
default-run-as-user: "65532"
default-run-as-group: "65532"
15 changes: 9 additions & 6 deletions pkg/reconciler/eventlistener/eventlistener.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"strings"
"sync"

"github.com/tektoncd/triggers/pkg/apis/config"
"github.com/tektoncd/triggers/pkg/apis/triggers/contexts"
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
triggersclientset "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
Expand Down Expand Up @@ -108,10 +109,12 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, el *v1beta1.EventListene
// and may not have had all of the assumed default specified.
el.SetDefaults(contexts.WithUpgradeViaDefaulting(ctx))

cfg := config.FromContextOrDefaults(ctx)

if el.Spec.Resources.CustomResource != nil {
return r.reconcileCustomObject(ctx, el)
return r.reconcileCustomObject(ctx, el, cfg)
}
deploymentReconcileError := r.reconcileDeployment(ctx, el)
deploymentReconcileError := r.reconcileDeployment(ctx, el, cfg)
serviceReconcileError := r.reconcileService(ctx, el)
if el.Spec.Resources.CustomResource == nil {
el.Status.SetReadyCondition()
Expand Down Expand Up @@ -184,8 +187,8 @@ func (r *Reconciler) reconcileService(ctx context.Context, el *v1beta1.EventList
return nil
}

func (r *Reconciler) reconcileDeployment(ctx context.Context, el *v1beta1.EventListener) error {
deployment, err := resources.MakeDeployment(ctx, el, r.configAcc, r.config)
func (r *Reconciler) reconcileDeployment(ctx context.Context, el *v1beta1.EventListener, cfg *config.Config) error {
deployment, err := resources.MakeDeployment(ctx, el, r.configAcc, r.config, cfg)
if err != nil {
logging.FromContext(ctx).Error(err)
return err
Expand Down Expand Up @@ -247,8 +250,8 @@ func (r *Reconciler) reconcileDeployment(ctx context.Context, el *v1beta1.EventL
return nil
}

func (r *Reconciler) reconcileCustomObject(ctx context.Context, el *v1beta1.EventListener) error {
data, err := resources.MakeCustomObject(ctx, el, r.configAcc, r.config)
func (r *Reconciler) reconcileCustomObject(ctx context.Context, el *v1beta1.EventListener, cfg *config.Config) error {
data, err := resources.MakeCustomObject(ctx, el, r.configAcc, r.config, cfg)
if err != nil {
logging.FromContext(ctx).Errorf("unable to construct custom object", err)
return err
Expand Down
34 changes: 30 additions & 4 deletions pkg/reconciler/eventlistener/eventlistener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,10 @@ func TestReconcile(t *testing.T) {
c.SetSecurityContext = ptr.Bool(false)
})

configWithSetSecurityContext := resources.MakeConfig(func(c *resources.Config) {
c.SetSecurityContext = ptr.Bool(true)
})

configWithSetEventListenerEventEnable := resources.MakeConfig(func(c *resources.Config) {
c.SetEventListenerEvent = ptr.String("enable")
})
Expand Down Expand Up @@ -889,7 +893,28 @@ func TestReconcile(t *testing.T) {

deploymentMissingSecurityContext := makeDeployment(func(d *appsv1.Deployment) {
d.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{}
d.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{}
d.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
RunAsUser: ptr.Int64(65532),
RunAsGroup: ptr.Int64(65532),
}
})

deploymentWithSecurityContext := makeDeployment(func(d *appsv1.Deployment) {
d.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{
RunAsNonRoot: ptr.Bool(true),
}
d.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
AllowPrivilegeEscalation: ptr.Bool(false),
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{"ALL"},
},
RunAsNonRoot: ptr.Bool(true),
RunAsUser: ptr.Int64(65532),
RunAsGroup: ptr.Int64(65532),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
}
})

deploymentEventListenerEvent := makeDeployment(func(d *appsv1.Deployment) {
Expand Down Expand Up @@ -1332,12 +1357,13 @@ func TestReconcile(t *testing.T) {
Services: []*corev1.Service{elServiceWithTLSConnection},
},
}, {
name: "eventlistener with security context",
key: reconcileKey,
name: "eventlistener with security context",
key: reconcileKey,
config: configWithSetSecurityContext,
startResources: test.Resources{
Namespaces: []*corev1.Namespace{namespaceResource},
EventListeners: []*v1beta1.EventListener{elWithStatus},
Deployments: []*appsv1.Deployment{deploymentMissingSecurityContext},
Deployments: []*appsv1.Deployment{deploymentWithSecurityContext},
},
endResources: test.Resources{
Namespaces: []*corev1.Namespace{namespaceResource},
Expand Down
9 changes: 5 additions & 4 deletions pkg/reconciler/eventlistener/resources/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package resources
import (
"strconv"

"github.com/tektoncd/triggers/pkg/apis/config"
"github.com/tektoncd/triggers/pkg/apis/triggers"
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
corev1 "k8s.io/api/core/v1"
Expand All @@ -28,7 +29,7 @@ import (

type ContainerOption func(*corev1.Container)

func MakeContainer(el *v1beta1.EventListener, configAcc reconcilersource.ConfigAccessor, c Config, opts ...ContainerOption) corev1.Container {
func MakeContainer(el *v1beta1.EventListener, configAcc reconcilersource.ConfigAccessor, c Config, cfg *config.Config, opts ...ContainerOption) corev1.Container {
isMultiNS := false
if len(el.Spec.NamespaceSelector.MatchNames) != 0 {
isMultiNS = true
Expand Down Expand Up @@ -56,16 +57,16 @@ func MakeContainer(el *v1beta1.EventListener, configAcc reconcilersource.ConfigA
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{"ALL"},
},
// 65532 is the distroless nonroot user ID
RunAsUser: ptr.Int64(65532),
RunAsGroup: ptr.Int64(65532),
RunAsNonRoot: ptr.Bool(true),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
}
}

containerSecurityContext.RunAsUser = ptr.Int64(cfg.Defaults.DefaultRunAsUser)
containerSecurityContext.RunAsGroup = ptr.Int64(cfg.Defaults.DefaultRunAsGroup)

container := corev1.Container{
Name: "event-listener",
Image: *c.Image,
Expand Down
5 changes: 4 additions & 1 deletion pkg/reconciler/eventlistener/resources/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ limitations under the License.
package resources

import (
"context"
"strconv"
"testing"

"github.com/google/go-cmp/cmp"
cfg "github.com/tektoncd/triggers/pkg/apis/config"
"github.com/tektoncd/triggers/pkg/apis/triggers"
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
corev1 "k8s.io/api/core/v1"
Expand All @@ -35,6 +37,7 @@ func TestContainer(t *testing.T) {
tests := []struct {
name string
el *v1beta1.EventListener
cm cfg.Config
want corev1.Container
opts []ContainerOption
}{{
Expand Down Expand Up @@ -480,7 +483,7 @@ func TestContainer(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := MakeContainer(tt.el, &reconcilersource.EmptyVarsGenerator{}, config, tt.opts...)
got := MakeContainer(tt.el, &reconcilersource.EmptyVarsGenerator{}, config, cfg.FromContextOrDefaults(context.Background()), tt.opts...)
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("MakeContainer() did not return expected. -want, +got: %s", diff)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/reconciler/eventlistener/resources/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"os"
"reflect"

"github.com/tektoncd/triggers/pkg/apis/config"
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -32,7 +33,7 @@ import (
"knative.dev/pkg/kmeta"
)

func MakeCustomObject(ctx context.Context, el *v1beta1.EventListener, configAcc reconcilersource.ConfigAccessor, c Config) (*unstructured.Unstructured, error) {
func MakeCustomObject(ctx context.Context, el *v1beta1.EventListener, configAcc reconcilersource.ConfigAccessor, c Config, cfg *config.Config) (*unstructured.Unstructured, error) {
original := &duckv1.WithPod{}
decoder := json.NewDecoder(bytes.NewBuffer(el.Spec.Resources.CustomResource.Raw))
if err := decoder.Decode(&original); err != nil {
Expand All @@ -47,7 +48,7 @@ func MakeCustomObject(ctx context.Context, el *v1beta1.EventListener, configAcc
namespace = el.GetNamespace()
}

container := MakeContainer(el, configAcc, c, func(c *corev1.Container) {
container := MakeContainer(el, configAcc, c, cfg, func(c *corev1.Container) {
// handle env and resources for custom object
if len(original.Spec.Template.Spec.Containers) == 1 {
c.Env = append(c.Env, original.Spec.Template.Spec.Containers[0].Env...)
Expand Down
6 changes: 4 additions & 2 deletions pkg/reconciler/eventlistener/resources/custom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
cfg "github.com/tektoncd/triggers/pkg/apis/config"
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -448,7 +449,8 @@ func TestCustomObject(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := MakeCustomObject(context.Background(), tt.el, &reconcilersource.EmptyVarsGenerator{}, config)
got, err := MakeCustomObject(context.Background(), tt.el, &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()))
if err != nil {
t.Fatalf("MakeCustomObject() = %v", err)
}
Expand All @@ -471,7 +473,7 @@ func TestCustomObjectError(t *testing.T) {
Raw: []byte(`garbage`),
},
}
}), &reconcilersource.EmptyVarsGenerator{}, config)
}), &reconcilersource.EmptyVarsGenerator{}, config, cfg.FromContextOrDefaults(context.Background()))
if err == nil {
t.Fatalf("MakeCustomObject() = %v, wanted error", got)
}
Expand Down
7 changes: 3 additions & 4 deletions pkg/reconciler/eventlistener/resources/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"os"
"strconv"

"github.com/tektoncd/triggers/pkg/apis/config"
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand All @@ -41,14 +42,12 @@ var (
}
)

func MakeDeployment(ctx context.Context, el *v1beta1.EventListener, configAcc reconcilersource.ConfigAccessor, c Config) (*appsv1.Deployment, error) {

func MakeDeployment(ctx context.Context, el *v1beta1.EventListener, configAcc reconcilersource.ConfigAccessor, c Config, cfg *config.Config) (*appsv1.Deployment, error) {
opt, err := addDeploymentBits(el, c)
if err != nil {
return nil, err
}

container := MakeContainer(el, configAcc, c, opt, addCertsForSecureConnection(c))
container := MakeContainer(el, configAcc, c, cfg, opt, addCertsForSecureConnection(c))

filteredLabels := FilterLabels(ctx, el.Labels)

Expand Down
Loading