From 59a9639ee69e448c861e285dd4e5fa1a9fee0371 Mon Sep 17 00:00:00 2001 From: Khurram Baig Date: Tue, 23 Jun 2026 03:12:19 +0530 Subject: [PATCH 1/3] feat: add NetworkPolicyConfig API type and shared networkpolicy package Introduce NetworkPolicyConfig struct embedded in component specs, allowing operators to disable NetworkPolicies or override individual policies by name. Add pkg/reconciler/common/networkpolicy with: - platform.go: PlatformParams for Kubernetes and OpenShift DNS/Prometheus defaults - networkpolicy.go: Generate() with map-merge and deterministic sorted output - networkpolicy_test.go: 13 unit tests covering merge, disable, and rule helpers Wire NetworkPolicyConfig into TektonTriggerSpec and TektonConfigSpec (reconciler integration for TektonConfig is deferred). Regenerate zz_generated.deepcopy.go. Signed-off-by: Khurram Baig Assisted-by: Claude Sonnet 4.6 --- .../operator/v1alpha1/networkpolicy_config.go | 36 +++ .../operator/v1alpha1/tektonconfig_types.go | 3 + .../operator/v1alpha1/tektontrigger_types.go | 3 + .../v1alpha1/zz_generated.deepcopy.go | 26 ++ .../common/networkpolicy/networkpolicy.go | 166 +++++++++++++ .../networkpolicy/networkpolicy_test.go | 228 ++++++++++++++++++ .../common/networkpolicy/platform.go | 43 ++++ 7 files changed, 505 insertions(+) create mode 100644 pkg/apis/operator/v1alpha1/networkpolicy_config.go create mode 100644 pkg/reconciler/common/networkpolicy/networkpolicy.go create mode 100644 pkg/reconciler/common/networkpolicy/networkpolicy_test.go create mode 100644 pkg/reconciler/common/networkpolicy/platform.go diff --git a/pkg/apis/operator/v1alpha1/networkpolicy_config.go b/pkg/apis/operator/v1alpha1/networkpolicy_config.go new file mode 100644 index 0000000000..952f6b7c06 --- /dev/null +++ b/pkg/apis/operator/v1alpha1/networkpolicy_config.go @@ -0,0 +1,36 @@ +/* +Copyright 2024 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 + + 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 v1alpha1 + +import networkingv1 "k8s.io/api/networking/v1" + +// NetworkPolicyConfig configures NetworkPolicy creation for a Tekton component. +type NetworkPolicyConfig struct { + // Disabled disables all NetworkPolicy creation for this component. + // Existing policies are removed on the next reconcile. + // +optional + Disabled bool `json:"disabled,omitempty"` + + // Policies merges with the operator's default NetworkPolicies by name. + // A key matching a default policy name replaces that default entirely. + // A key not matching any default is added alongside the defaults. + // If nil or empty, all operator defaults are applied unchanged. + // +optional + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Schemaless + Policies map[string]networkingv1.NetworkPolicySpec `json:"policies,omitempty"` +} diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_types.go b/pkg/apis/operator/v1alpha1/tektonconfig_types.go index c8cc186cf5..4b62bb200e 100644 --- a/pkg/apis/operator/v1alpha1/tektonconfig_types.go +++ b/pkg/apis/operator/v1alpha1/tektonconfig_types.go @@ -134,6 +134,9 @@ type TektonConfigSpec struct { // holds target namespace metadata // +optional TargetNamespaceMetadata *NamespaceMetadata `json:"targetNamespaceMetadata,omitempty"` + // NetworkPolicy configures namespace-wide NetworkPolicies for the operand namespace. + // +optional + NetworkPolicy NetworkPolicyConfig `json:"networkPolicy,omitempty"` } // PipelinesAsCodeForCurrentPlatform returns the PipelinesAsCode block for the operator build diff --git a/pkg/apis/operator/v1alpha1/tektontrigger_types.go b/pkg/apis/operator/v1alpha1/tektontrigger_types.go index 611ba3eb63..8ea4d506e7 100644 --- a/pkg/apis/operator/v1alpha1/tektontrigger_types.go +++ b/pkg/apis/operator/v1alpha1/tektontrigger_types.go @@ -57,6 +57,9 @@ type TektonTriggerSpec struct { // Config holds the configuration for resources created by TektonTrigger // +optional Config Config `json:"config,omitempty"` + // NetworkPolicy configures NetworkPolicy creation for TektonTrigger workloads. + // +optional + NetworkPolicy NetworkPolicyConfig `json:"networkPolicy,omitempty"` } // TektonTriggerStatus defines the observed state of TektonTrigger diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go index 57bf17c3bc..f5d8de6fee 100644 --- a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go @@ -27,6 +27,7 @@ import ( appsv1 "k8s.io/api/apps/v1" v2 "k8s.io/api/autoscaling/v2" v1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -654,6 +655,29 @@ func (in *NamespaceMetadata) DeepCopy() *NamespaceMetadata { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkPolicyConfig) DeepCopyInto(out *NetworkPolicyConfig) { + *out = *in + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make(map[string]networkingv1.NetworkPolicySpec, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyConfig. +func (in *NetworkPolicyConfig) DeepCopy() *NetworkPolicyConfig { + if in == nil { + return nil + } + out := new(NetworkPolicyConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenShift) DeepCopyInto(out *OpenShift) { *out = *in @@ -1855,6 +1879,7 @@ func (in *TektonConfigSpec) DeepCopyInto(out *TektonConfigSpec) { *out = new(NamespaceMetadata) (*in).DeepCopyInto(*out) } + in.NetworkPolicy.DeepCopyInto(&out.NetworkPolicy) return } @@ -2786,6 +2811,7 @@ func (in *TektonTriggerSpec) DeepCopyInto(out *TektonTriggerSpec) { out.CommonSpec = in.CommonSpec in.Trigger.DeepCopyInto(&out.Trigger) in.Config.DeepCopyInto(&out.Config) + in.NetworkPolicy.DeepCopyInto(&out.NetworkPolicy) return } diff --git a/pkg/reconciler/common/networkpolicy/networkpolicy.go b/pkg/reconciler/common/networkpolicy/networkpolicy.go new file mode 100644 index 0000000000..6a1723344f --- /dev/null +++ b/pkg/reconciler/common/networkpolicy/networkpolicy.go @@ -0,0 +1,166 @@ +/* +Copyright 2024 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 + + 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 networkpolicy + +import ( + "fmt" + "sort" + + mf "github.com/manifestival/manifestival" + "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1" + corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + apimachineryRuntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// Generate builds a Manifest by merging defaults with cfg.Policies. +// +// - Returns an empty manifest when cfg.Disabled is true. +// - Starts with defaults keyed by name; cfg.Policies entries overwrite on +// collision and add when new. +// - Injects namespace into every NetworkPolicy object. +// - Output is sorted by name for deterministic InstallerSet checksums. +func Generate( + cfg v1alpha1.NetworkPolicyConfig, + ns string, + defaults []networkingv1.NetworkPolicy, +) (mf.Manifest, error) { + if cfg.Disabled { + return mf.Manifest{}, nil + } + + merged := make(map[string]networkingv1.NetworkPolicy, len(defaults)) + for _, p := range defaults { + merged[p.Name] = p + } + for name, spec := range cfg.Policies { + merged[name] = networkingv1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: name}, + Spec: spec, + } + } + + names := make([]string, 0, len(merged)) + for name := range merged { + names = append(names, name) + } + sort.Strings(names) + + resources := make([]unstructured.Unstructured, 0, len(names)) + for _, name := range names { + np := merged[name] + np.Namespace = ns + np.TypeMeta = metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + } + obj, err := apimachineryRuntime.DefaultUnstructuredConverter.ToUnstructured(&np) + if err != nil { + return mf.Manifest{}, fmt.Errorf("converting NetworkPolicy %q: %w", name, err) + } + u := unstructured.Unstructured{} + u.SetUnstructuredContent(obj) + resources = append(resources, u) + } + + return mf.ManifestFrom(mf.Slice(resources)) +} + +// DNSEgressRule allows egress to DNS resolver pods on UDP and TCP port 5353. +func DNSEgressRule(p PlatformParams) networkingv1.NetworkPolicyEgressRule { + udp := corev1.ProtocolUDP + tcp := corev1.ProtocolTCP + dnsPort := intstr.FromInt32(5353) + return networkingv1.NetworkPolicyEgressRule{ + Ports: []networkingv1.NetworkPolicyPort{ + {Protocol: &udp, Port: &dnsPort}, + {Protocol: &tcp, Port: &dnsPort}, + }, + To: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"kubernetes.io/metadata.name": p.DNSResolverNamespace}, + }, + PodSelector: &metav1.LabelSelector{ + MatchLabels: p.DNSResolverPodLabel, + }, + }, + }, + } +} + +// APIServerEgressRule allows egress on TCP 6443 to any destination. +// The API server is typically host-networked so no pod/namespace selector is needed. +func APIServerEgressRule() networkingv1.NetworkPolicyEgressRule { + tcp := corev1.ProtocolTCP + apiPort := intstr.FromInt32(6443) + return networkingv1.NetworkPolicyEgressRule{ + Ports: []networkingv1.NetworkPolicyPort{ + {Protocol: &tcp, Port: &apiPort}, + }, + } +} + +// InternetEgressRule allows egress on TCP 80 and 443 to any destination. +func InternetEgressRule() networkingv1.NetworkPolicyEgressRule { + tcp := corev1.ProtocolTCP + httpPort := intstr.FromInt32(80) + httpsPort := intstr.FromInt32(443) + return networkingv1.NetworkPolicyEgressRule{ + Ports: []networkingv1.NetworkPolicyPort{ + {Protocol: &tcp, Port: &httpPort}, + {Protocol: &tcp, Port: &httpsPort}, + }, + } +} + +// PrometheusIngressRule allows ingress from the monitoring namespace on the given port. +func PrometheusIngressRule(p PlatformParams, port intstr.IntOrString) networkingv1.NetworkPolicyIngressRule { + tcp := corev1.ProtocolTCP + return networkingv1.NetworkPolicyIngressRule{ + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: p.PrometheusNamespaceLabel, + }, + }, + }, + Ports: []networkingv1.NetworkPolicyPort{ + {Protocol: &tcp, Port: &port}, + }, + } +} + +// WebhookIngressRule allows ingress on port for admission webhooks. +// If cidr is empty, allows from any source (no From restriction). +func WebhookIngressRule(cidr string, port intstr.IntOrString) networkingv1.NetworkPolicyIngressRule { + tcp := corev1.ProtocolTCP + rule := networkingv1.NetworkPolicyIngressRule{ + Ports: []networkingv1.NetworkPolicyPort{ + {Protocol: &tcp, Port: &port}, + }, + } + if cidr != "" { + rule.From = []networkingv1.NetworkPolicyPeer{ + {IPBlock: &networkingv1.IPBlock{CIDR: cidr}}, + } + } + return rule +} diff --git a/pkg/reconciler/common/networkpolicy/networkpolicy_test.go b/pkg/reconciler/common/networkpolicy/networkpolicy_test.go new file mode 100644 index 0000000000..6683918404 --- /dev/null +++ b/pkg/reconciler/common/networkpolicy/networkpolicy_test.go @@ -0,0 +1,228 @@ +/* +Copyright 2024 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 + + 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 networkpolicy_test + +import ( + "testing" + + "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1" + "github.com/tektoncd/operator/pkg/reconciler/common/networkpolicy" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func defaultPolicies() []networkingv1.NetworkPolicy { + return []networkingv1.NetworkPolicy{ + {ObjectMeta: metav1.ObjectMeta{Name: "policy-a"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "policy-b"}}, + } +} + +func TestGenerate_Disabled(t *testing.T) { + cfg := v1alpha1.NetworkPolicyConfig{Disabled: true} + m, err := networkpolicy.Generate(cfg, "tekton-pipelines", defaultPolicies()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got := len(m.Resources()); got != 0 { + t.Errorf("expected empty manifest when disabled, got %d resources", got) + } +} + +func TestGenerate_DefaultsOnly(t *testing.T) { + cfg := v1alpha1.NetworkPolicyConfig{} + m, err := networkpolicy.Generate(cfg, "tekton-pipelines", defaultPolicies()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got := len(m.Resources()); got != 2 { + t.Errorf("expected 2 resources, got %d", got) + } + for _, r := range m.Resources() { + if r.GetNamespace() != "tekton-pipelines" { + t.Errorf("resource %q: expected namespace tekton-pipelines, got %q", r.GetName(), r.GetNamespace()) + } + if r.GetKind() != "NetworkPolicy" { + t.Errorf("resource %q: expected kind NetworkPolicy, got %q", r.GetName(), r.GetKind()) + } + if r.GetAPIVersion() != "networking.k8s.io/v1" { + t.Errorf("resource %q: expected apiVersion networking.k8s.io/v1, got %q", r.GetName(), r.GetAPIVersion()) + } + } +} + +func TestGenerate_UserOverridesDefault(t *testing.T) { + cfg := v1alpha1.NetworkPolicyConfig{ + Policies: map[string]networkingv1.NetworkPolicySpec{ + "policy-a": { + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "override"}, + }, + }, + }, + } + m, err := networkpolicy.Generate(cfg, "tekton-pipelines", defaultPolicies()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + // policy-a overridden, policy-b kept — still 2 total + if got := len(m.Resources()); got != 2 { + t.Errorf("expected 2 resources, got %d", got) + } + for _, r := range m.Resources() { + if r.GetName() != "policy-a" { + continue + } + labels, _, _ := unstructured.NestedStringMap(r.Object, "spec", "podSelector", "matchLabels") + if labels["app"] != "override" { + t.Errorf("policy-a: expected override label, got %v", labels) + } + } +} + +func TestGenerate_UserAddsNewPolicy(t *testing.T) { + cfg := v1alpha1.NetworkPolicyConfig{ + Policies: map[string]networkingv1.NetworkPolicySpec{ + "policy-new": {}, + }, + } + m, err := networkpolicy.Generate(cfg, "tekton-pipelines", defaultPolicies()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got := len(m.Resources()); got != 3 { + t.Errorf("expected 3 resources (2 defaults + 1 new), got %d", got) + } +} + +func TestGenerate_DeterministicOrder(t *testing.T) { + cfg := v1alpha1.NetworkPolicyConfig{} + defaults := []networkingv1.NetworkPolicy{ + {ObjectMeta: metav1.ObjectMeta{Name: "policy-c"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "policy-a"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "policy-b"}}, + } + m, err := networkpolicy.Generate(cfg, "ns", defaults) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + resources := m.Resources() + expected := []string{"policy-a", "policy-b", "policy-c"} + for i, r := range resources { + if r.GetName() != expected[i] { + t.Errorf("position %d: expected %q, got %q", i, expected[i], r.GetName()) + } + } +} + +func TestGenerate_EmptyDefaults(t *testing.T) { + cfg := v1alpha1.NetworkPolicyConfig{} + m, err := networkpolicy.Generate(cfg, "ns", nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got := len(m.Resources()); got != 0 { + t.Errorf("expected 0 resources, got %d", got) + } +} + +func TestWebhookIngressRule_NoCIDR(t *testing.T) { + port := intstr.FromInt32(8443) + rule := networkpolicy.WebhookIngressRule("", port) + if len(rule.From) != 0 { + t.Errorf("expected no From restriction when cidr empty, got %v", rule.From) + } + if len(rule.Ports) != 1 || rule.Ports[0].Port.IntVal != 8443 { + t.Errorf("expected port 8443, got %v", rule.Ports) + } +} + +func TestWebhookIngressRule_WithCIDR(t *testing.T) { + port := intstr.FromInt32(8443) + rule := networkpolicy.WebhookIngressRule("10.0.1.0/24", port) + if len(rule.From) != 1 || rule.From[0].IPBlock == nil { + t.Fatalf("expected From with IPBlock, got %v", rule.From) + } + if rule.From[0].IPBlock.CIDR != "10.0.1.0/24" { + t.Errorf("expected CIDR 10.0.1.0/24, got %q", rule.From[0].IPBlock.CIDR) + } +} + +func TestInternetEgressRule(t *testing.T) { + rule := networkpolicy.InternetEgressRule() + if len(rule.Ports) != 2 { + t.Fatalf("expected 2 ports, got %d", len(rule.Ports)) + } + if rule.Ports[0].Port.IntVal != 80 || rule.Ports[1].Port.IntVal != 443 { + t.Errorf("expected ports 80 and 443, got %v and %v", rule.Ports[0].Port.IntVal, rule.Ports[1].Port.IntVal) + } + if len(rule.To) != 0 { + t.Errorf("expected no To restriction for internet egress, got %v", rule.To) + } +} + +func TestAPIServerEgressRule(t *testing.T) { + rule := networkpolicy.APIServerEgressRule() + if len(rule.Ports) != 1 || rule.Ports[0].Port.IntVal != 6443 { + t.Fatalf("expected port 6443, got %v", rule.Ports) + } + if len(rule.To) != 0 { + t.Errorf("expected no To restriction for API server egress, got %v", rule.To) + } +} + +func TestDNSEgressRule_Kubernetes(t *testing.T) { + params := networkpolicy.KubernetesPlatformDefaults() + rule := networkpolicy.DNSEgressRule(params) + if len(rule.Ports) != 2 { + t.Fatalf("expected 2 ports (UDP+TCP 5353), got %d", len(rule.Ports)) + } + if len(rule.To) != 1 || rule.To[0].NamespaceSelector == nil { + t.Fatalf("expected 1 To with NamespaceSelector, got %v", rule.To) + } + nsLabels := rule.To[0].NamespaceSelector.MatchLabels + if nsLabels["kubernetes.io/metadata.name"] != "kube-system" { + t.Errorf("expected kube-system namespace selector, got %v", nsLabels) + } +} + +func TestDNSEgressRule_OpenShift(t *testing.T) { + params := networkpolicy.OpenShiftPlatformDefaults() + rule := networkpolicy.DNSEgressRule(params) + nsLabels := rule.To[0].NamespaceSelector.MatchLabels + if nsLabels["kubernetes.io/metadata.name"] != "openshift-dns" { + t.Errorf("expected openshift-dns namespace selector, got %v", nsLabels) + } +} + +func TestPrometheusIngressRule(t *testing.T) { + params := networkpolicy.KubernetesPlatformDefaults() + port := intstr.FromInt32(9000) + rule := networkpolicy.PrometheusIngressRule(params, port) + if len(rule.From) != 1 || rule.From[0].NamespaceSelector == nil { + t.Fatalf("expected 1 From with NamespaceSelector, got %v", rule.From) + } + nsLabels := rule.From[0].NamespaceSelector.MatchLabels + if nsLabels["kubernetes.io/metadata.name"] != "monitoring" { + t.Errorf("expected monitoring namespace, got %v", nsLabels) + } + if len(rule.Ports) != 1 || rule.Ports[0].Port.IntVal != 9000 { + t.Errorf("expected port 9000, got %v", rule.Ports) + } +} diff --git a/pkg/reconciler/common/networkpolicy/platform.go b/pkg/reconciler/common/networkpolicy/platform.go new file mode 100644 index 0000000000..3bf87e2d59 --- /dev/null +++ b/pkg/reconciler/common/networkpolicy/platform.go @@ -0,0 +1,43 @@ +/* +Copyright 2024 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 + + 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 networkpolicy + +// PlatformParams holds platform-specific values for building default NetworkPolicy rules. +// It is an internal type — it never appears in CRD API fields. +type PlatformParams struct { + DNSResolverNamespace string + DNSResolverPodLabel map[string]string + PrometheusNamespaceLabel map[string]string +} + +// KubernetesPlatformDefaults returns PlatformParams for vanilla Kubernetes. +func KubernetesPlatformDefaults() PlatformParams { + return PlatformParams{ + DNSResolverNamespace: "kube-system", + DNSResolverPodLabel: map[string]string{"k8s-app": "kube-dns"}, + PrometheusNamespaceLabel: map[string]string{"kubernetes.io/metadata.name": "monitoring"}, + } +} + +// OpenShiftPlatformDefaults returns PlatformParams for OpenShift. +func OpenShiftPlatformDefaults() PlatformParams { + return PlatformParams{ + DNSResolverNamespace: "openshift-dns", + DNSResolverPodLabel: map[string]string{"dns.operator.openshift.io/daemonset-dns": "default"}, + PrometheusNamespaceLabel: map[string]string{"openshift.io/cluster-monitoring": "true"}, + } +} From 2b6f6d970a05fc931555992c2d23f1578fc4f843 Mon Sep 17 00:00:00 2001 From: Khurram Baig Date: Tue, 30 Jun 2026 08:03:32 +0530 Subject: [PATCH 2/3] feat(triggers): wire NetworkPolicy reconciliation into TektonTrigger Add triggersDefaultPolicies() defining four NetworkPolicies for the Triggers workloads (controller, webhook, core-interceptors ingress, core-interceptors egress). Platform-specific DNS and Prometheus values are resolved at controller startup via v1alpha1.IsOpenShiftPlatform(). reconcileNetworkPolicies() applies policies as a named CustomSet ("triggers-network-policies") or cleans it up when disabled. Signed-off-by: Khurram Baig Assisted-by: Claude Sonnet 4.6 --- .../templates/kubernetes-crds.yaml | 98 +- .../templates/kubernetes-rbac.yaml | 12 + .../templates/openshift-crds.yaml | 3967 ----------------- .../templates/openshift-rbac.yaml | 12 + .../operator.tekton.dev_tektonconfigs.yaml | 20 + .../operator.tekton.dev_tektontriggers.yaml | 17 + config/base/role.yaml | 12 + config/openshift/base/role.yaml | 12 + .../operator/v1alpha1/tektonconfig_types.go | 15 +- .../common/networkpolicy/networkpolicy.go | 46 +- .../networkpolicy/networkpolicy_test.go | 49 +- .../common/networkpolicy/platform.go | 14 + .../kubernetes/tektontrigger/controller.go | 7 + .../kubernetes/tektontrigger/finalize.go | 11 +- .../tektontrigger/networkpolicies.go | 158 + .../kubernetes/tektontrigger/reconcile.go | 21 +- .../shared/tektonconfig/trigger/trigger.go | 10 +- 17 files changed, 444 insertions(+), 4037 deletions(-) create mode 100644 pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go diff --git a/charts/tekton-operator/templates/kubernetes-crds.yaml b/charts/tekton-operator/templates/kubernetes-crds.yaml index 9b29362e87..0b402f54b3 100644 --- a/charts/tekton-operator/templates/kubernetes-crds.yaml +++ b/charts/tekton-operator/templates/kubernetes-crds.yaml @@ -89,8 +89,6 @@ spec: targetNamespace: description: TargetNamespace is where resources will be installed type: string - required: - - options type: object status: description: ManualApprovalGateStatus defines the observed state of ManualApprovalGate @@ -328,8 +326,6 @@ spec: targetNamespace: description: TargetNamespace is where resources will be installed type: string - required: - - options type: object status: description: OpenShiftPipelinesAsCodeStatus defines the observed state @@ -811,7 +807,6 @@ spec: type: string required: - disabled - - options type: object status: description: TektonChainStatus defines the observed state of TektonChain @@ -1266,7 +1261,6 @@ spec: type: string required: - disabled - - options type: object config: description: Config holds the configuration for resources created @@ -1362,7 +1356,6 @@ spec: in read-only mode type: boolean required: - - options - readonly type: object hub: @@ -1412,8 +1405,6 @@ spec: type: string type: object type: array - required: - - options type: object multiclusterProxyAAE: description: MulticlusterProxyAAE holds the customizable options for @@ -1451,8 +1442,26 @@ spec: type: object type: object type: object - required: - - options + type: object + networkPolicy: + description: |- + NetworkPolicy configures NetworkPolicy resources for the operand namespace. + This field is propagated to TektonTrigger, which is the only component with + NetworkPolicy reconciliation implemented. Other components (Pipeline, Chains, + Results, Dashboard) do not yet act on this field. + properties: + disabled: + description: |- + Disabled disables all NetworkPolicy creation for this component. + Existing policies are removed on the next reconcile. + type: boolean + policies: + description: |- + Policies merges with the operator's default NetworkPolicies by name. + A key matching a default policy name replaces that default entirely. + A key not matching any default is added alongside the defaults. + If nil or empty, all operator defaults are applied unchanged. + x-kubernetes-preserve-unknown-fields: true type: object params: description: Params is the list of params passed for all platforms @@ -1649,6 +1658,13 @@ spec: used. type: boolean send-cloudevents-for-runs: + description: |- + Deprecated: send-cloudevents-for-runs is deprecated in tektoncd/pipeline v1.12.0 + (https://github.com/tektoncd/pipeline/pull/9774) and will be removed in a future release. + CloudEvents for CustomRuns are now enabled by default when a sink is configured in + the config-events ConfigMap. This field only affects CustomRun objects; it has no + effect on TaskRuns or PipelineRuns. Set to false only to suppress duplicate events + when a custom task controller already sends its own CloudEvents. type: boolean set-security-context: type: boolean @@ -1666,8 +1682,6 @@ spec: type: string verification-mode: type: string - required: - - options type: object platforms: description: Platforms allows configuring platform specific configurations @@ -1746,8 +1760,6 @@ spec: additionalProperties: type: string type: object - required: - - options type: object type: object openshift: @@ -1756,14 +1768,13 @@ spec: properties: enableCentralTLSConfig: description: |- - EnableCentralTLSConfig enables TLS configuration inheritance from - the cluster's APIServer TLS security profile. When enabled, TLS settings - (minimum version, cipher suites, curve preferences) are automatically - derived from the cluster-wide security policy and injected into Tekton - component containers that support TLS configuration. - If the APIServer does not have a TLS profile configured, user-specified - TLS settings in component configurations will be used as fallback. - Default: false (opt-in) + EnableCentralTLSConfig controls TLS configuration inheritance from the + cluster's APIServer TLS security profile. When enabled (the default), + TLS settings (minimum version, cipher suites, curve preferences) are + automatically derived from the cluster-wide security policy and injected + into Tekton component containers that support TLS configuration. + Set to false to opt out and manage TLS settings manually. + Default: true (opt-out) type: boolean pipelinesAsCode: description: PipelinesAsCode allows configuring PipelinesAsCode @@ -1835,8 +1846,6 @@ spec: additionalProperties: type: string type: object - required: - - options type: object scc: description: SCC allows configuring security context constraints @@ -2057,7 +2066,6 @@ spec: required: - disabled - is_external_db - - options type: object scheduler: description: To enable Pipeline Scheduling on Single Cluster or Multiple @@ -2115,7 +2123,6 @@ spec: - disabled - multi-cluster-disabled - multi-cluster-role - - options type: object targetNamespace: description: TargetNamespace is where resources will be installed @@ -2176,7 +2183,6 @@ spec: required: - disabled - global-config - - options type: object trigger: description: Trigger holds the customizable option for triggers component @@ -2222,7 +2228,6 @@ spec: type: object required: - disabled - - options type: object type: object status: @@ -2443,7 +2448,6 @@ spec: description: TargetNamespace is where resources will be installed type: string required: - - options - readonly type: object status: @@ -2686,8 +2690,6 @@ spec: targetNamespace: description: TargetNamespace is where resources will be installed type: string - required: - - options type: object status: description: TektonHubStatus defines the observed state of TektonHub @@ -3169,6 +3171,13 @@ spec: description: ScopeWhenExpressionsToTask is deprecated and never used. type: boolean send-cloudevents-for-runs: + description: |- + Deprecated: send-cloudevents-for-runs is deprecated in tektoncd/pipeline v1.12.0 + (https://github.com/tektoncd/pipeline/pull/9774) and will be removed in a future release. + CloudEvents for CustomRuns are now enabled by default when a sink is configured in + the config-events ConfigMap. This field only affects CustomRun objects; it has no + effect on TaskRuns or PipelineRuns. Set to false only to suppress duplicate events + when a custom task controller already sends its own CloudEvents. type: boolean set-security-context: type: boolean @@ -3189,8 +3198,6 @@ spec: type: string verification-mode: type: string - required: - - options type: object status: description: TektonPipelineStatus defines the observed state of TektonPipeline @@ -3532,7 +3539,6 @@ spec: required: - disabled - is_external_db - - options type: object status: description: TektonResultStatus defines the observed state of TektonResult @@ -3712,6 +3718,23 @@ spec: type: boolean enable-api-fields: type: string + networkPolicy: + description: NetworkPolicy configures NetworkPolicy creation for TektonTrigger + workloads. + properties: + disabled: + description: |- + Disabled disables all NetworkPolicy creation for this component. + Existing policies are removed on the next reconcile. + type: boolean + policies: + description: |- + Policies merges with the operator's default NetworkPolicies by name. + A key matching a default policy name replaces that default entirely. + A key not matching any default is added alongside the defaults. + If nil or empty, all operator defaults are applied unchanged. + x-kubernetes-preserve-unknown-fields: true + type: object options: description: options holds additions fields and these fields will be updated on the manifests @@ -3749,7 +3772,6 @@ spec: type: string required: - disabled - - options type: object status: description: TektonTriggerStatus defines the observed state of TektonTrigger @@ -3964,7 +3986,6 @@ spec: required: - disabled - global-config - - options type: object status: description: TektonPrunerStatus defines the observed state of TektonPruner @@ -4140,7 +4161,6 @@ spec: - disabled - multi-cluster-disabled - multi-cluster-role - - options type: object status: description: TektonSchedulerStatus defines the observed state of TektonScheduler @@ -4297,8 +4317,6 @@ spec: targetNamespace: description: TargetNamespace is where resources will be installed type: string - required: - - options type: object status: description: TektonMulticlusterProxyAAEStatus defines the observed state diff --git a/charts/tekton-operator/templates/kubernetes-rbac.yaml b/charts/tekton-operator/templates/kubernetes-rbac.yaml index 0d71f6f073..ae12115e91 100644 --- a/charts/tekton-operator/templates/kubernetes-rbac.yaml +++ b/charts/tekton-operator/templates/kubernetes-rbac.yaml @@ -88,6 +88,18 @@ rules: - list - update - watch + - apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - delete + - create + - patch + - get + - list + - update + - watch - apiGroups: - "" resources: diff --git a/charts/tekton-operator/templates/openshift-crds.yaml b/charts/tekton-operator/templates/openshift-crds.yaml index 9aa4b5bf5d..ec87b46d60 100644 --- a/charts/tekton-operator/templates/openshift-crds.yaml +++ b/charts/tekton-operator/templates/openshift-crds.yaml @@ -89,8 +89,6 @@ spec: targetNamespace: description: TargetNamespace is where resources will be installed type: string - required: - - options type: object status: description: ManualApprovalGateStatus defines the observed state of ManualApprovalGate @@ -328,8 +326,6 @@ spec: targetNamespace: description: TargetNamespace is where resources will be installed type: string - required: - - options type: object status: description: OpenShiftPipelinesAsCodeStatus defines the observed state @@ -590,3966 +586,3 @@ spec: subresources: status: {} --- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonchains.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonChain - listKind: TektonChainList - plural: tektonchains - singular: tektonchain - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonChain is the Schema for the tektonchain API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: TektonChainSpec defines the desired state of TektonChain - properties: - artifacts.oci.format: - description: oci artifacts config - type: string - artifacts.oci.signer: - type: string - artifacts.oci.storage: - type: string - artifacts.pipelinerun.enable-deep-inspection: - type: string - artifacts.pipelinerun.format: - description: pipelinerun artifacts config - type: string - artifacts.pipelinerun.signer: - type: string - artifacts.pipelinerun.storage: - type: string - artifacts.taskrun.format: - description: taskrun artifacts config - type: string - artifacts.taskrun.signer: - type: string - artifacts.taskrun.storage: - type: string - builddefinition.buildtype: - type: string - builder.id: - description: builder config - type: string - config: - description: Config holds the configuration for resources created - by TektonChain - properties: - nodeSelector: - additionalProperties: - type: string - type: object - priorityClassName: - description: PriorityClassName holds the priority class to be - set to pod template - type: string - tolerations: - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - controllerEnvs: - items: - description: EnvVar represents an environment variable present in - a Container. - properties: - name: - description: |- - Name of the environment variable. - May consist of any printable ASCII characters except '='. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. Cannot - be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath is - written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified - API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - fileKeyRef: - description: |- - FileKeyRef selects a key of the env file. - Requires the EnvFiles feature gate to be enabled. - properties: - key: - description: |- - The key within the env file. An invalid key will prevent the pod from starting. - The keys defined within a source may consist of any printable ASCII characters except '='. - During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. - type: string - optional: - default: false - description: |- - Specify whether the file or its key must be defined. If the file or key - does not exist, then the env var is not published. - If optional is set to true and the specified key does not exist, - the environment variable will not be set in the Pod's containers. - - If optional is set to false and the specified key does not exist, - an error will be returned during Pod creation. - type: boolean - path: - description: |- - The path within the volume from which to select the file. - Must be relative and may not contain the '..' path or start with '..'. - type: string - volumeName: - description: The name of the volume mount containing - the env file. - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key must - be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - disabled: - description: enable or disable chains feature - type: boolean - generateSigningSecret: - description: generate signing key - type: boolean - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - performance: - description: |- - PerformanceProperties defines the fields which are configurable - to tune the performance of component controller - properties: - buckets: - type: integer - disable-ha: - description: if it is true, disables the HA feature - type: boolean - kube-api-burst: - type: integer - kube-api-qps: - description: |- - queries per second (QPS) and burst to the master from rest API client - actually the number multiplied by 2 - https://github.com/pierretasci/pipeline/blob/05d67e427c722a2a57e58328d7097e21429b7524/cmd/controller/main.go#L85-L87 - defaults: https://github.com/tektoncd/pipeline/blob/34618964300620dca44d10a595e4af84e9903a55/vendor/k8s.io/client-go/rest/config.go#L45-L46 - type: number - replicas: - type: integer - statefulset-ordinals: - description: if is true, enable StatefulsetOrdinals mode - type: boolean - threads-per-controller: - description: The number of workers to use when processing the - component controller's work queue - type: integer - required: - - disable-ha - type: object - signers.kms.auth.address: - type: string - signers.kms.auth.oidc.path: - type: string - signers.kms.auth.oidc.role: - type: string - signers.kms.auth.spire.audience: - type: string - signers.kms.auth.spire.sock: - type: string - signers.kms.auth.token: - type: string - signers.kms.auth.token-path: - type: string - signers.kms.kmsref: - description: kms signer config - type: string - signers.x509.fulcio.address: - type: string - signers.x509.fulcio.enabled: - description: x509 signer config - type: boolean - signers.x509.fulcio.issuer: - type: string - signers.x509.fulcio.provider: - type: string - signers.x509.identity.token.file: - type: string - signers.x509.tuf.mirror.url: - type: string - storage.docdb.mongo-server-url: - type: string - storage.docdb.mongo-server-url-dir: - type: string - storage.docdb.url: - type: string - storage.gcs.bucket: - description: storage configs - type: string - storage.grafeas.notehint: - type: string - storage.grafeas.noteid: - type: string - storage.grafeas.projectid: - type: string - storage.oci.repository: - type: string - storage.oci.repository.insecure: - type: boolean - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - transparency.enabled: - type: string - transparency.url: - type: string - required: - - disabled - - options - type: object - status: - description: TektonChainStatus defines the observed state of TektonChain - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - tektonInstallerSet: - description: The current installer set name for TektonChain - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonconfigs.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonConfig - listKind: TektonConfigList - plural: tektonconfigs - singular: tektonconfig - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonConfig is the Schema for the TektonConfigs API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: TektonConfigSpec defines the desired state of TektonConfig - properties: - addon: - description: Addon holds the addons config - properties: - enablePipelinesAsCode: - description: |- - Deprecated, will be removed in further release - EnablePAC field defines whether to install PAC - type: boolean - params: - description: Params is the list of params passed for Addon customization - items: - description: Param declares an string value to use for the parameter - called name. - properties: - name: - type: string - value: - type: string - type: object - type: array - type: object - chain: - description: Chain holds the customizable option for chains component - properties: - artifacts.oci.format: - description: oci artifacts config - type: string - artifacts.oci.signer: - type: string - artifacts.oci.storage: - type: string - artifacts.pipelinerun.enable-deep-inspection: - type: string - artifacts.pipelinerun.format: - description: pipelinerun artifacts config - type: string - artifacts.pipelinerun.signer: - type: string - artifacts.pipelinerun.storage: - type: string - artifacts.taskrun.format: - description: taskrun artifacts config - type: string - artifacts.taskrun.signer: - type: string - artifacts.taskrun.storage: - type: string - builddefinition.buildtype: - type: string - builder.id: - description: builder config - type: string - controllerEnvs: - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: |- - Name of the environment variable. - May consist of any printable ASCII characters except '='. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the - specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - fileKeyRef: - description: |- - FileKeyRef selects a key of the env file. - Requires the EnvFiles feature gate to be enabled. - properties: - key: - description: |- - The key within the env file. An invalid key will prevent the pod from starting. - The keys defined within a source may consist of any printable ASCII characters except '='. - During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. - type: string - optional: - default: false - description: |- - Specify whether the file or its key must be defined. If the file or key - does not exist, then the env var is not published. - If optional is set to true and the specified key does not exist, - the environment variable will not be set in the Pod's containers. - - If optional is set to false and the specified key does not exist, - an error will be returned during Pod creation. - type: boolean - path: - description: |- - The path within the volume from which to select the file. - Must be relative and may not contain the '..' path or start with '..'. - type: string - volumeName: - description: The name of the volume mount containing - the env file. - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - disabled: - description: enable or disable chains feature - type: boolean - generateSigningSecret: - description: generate signing key - type: boolean - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - performance: - description: |- - PerformanceProperties defines the fields which are configurable - to tune the performance of component controller - properties: - buckets: - type: integer - disable-ha: - description: if it is true, disables the HA feature - type: boolean - kube-api-burst: - type: integer - kube-api-qps: - description: |- - queries per second (QPS) and burst to the master from rest API client - actually the number multiplied by 2 - https://github.com/pierretasci/pipeline/blob/05d67e427c722a2a57e58328d7097e21429b7524/cmd/controller/main.go#L85-L87 - defaults: https://github.com/tektoncd/pipeline/blob/34618964300620dca44d10a595e4af84e9903a55/vendor/k8s.io/client-go/rest/config.go#L45-L46 - type: number - replicas: - type: integer - statefulset-ordinals: - description: if is true, enable StatefulsetOrdinals mode - type: boolean - threads-per-controller: - description: The number of workers to use when processing - the component controller's work queue - type: integer - required: - - disable-ha - type: object - signers.kms.auth.address: - type: string - signers.kms.auth.oidc.path: - type: string - signers.kms.auth.oidc.role: - type: string - signers.kms.auth.spire.audience: - type: string - signers.kms.auth.spire.sock: - type: string - signers.kms.auth.token: - type: string - signers.kms.auth.token-path: - type: string - signers.kms.kmsref: - description: kms signer config - type: string - signers.x509.fulcio.address: - type: string - signers.x509.fulcio.enabled: - description: x509 signer config - type: boolean - signers.x509.fulcio.issuer: - type: string - signers.x509.fulcio.provider: - type: string - signers.x509.identity.token.file: - type: string - signers.x509.tuf.mirror.url: - type: string - storage.docdb.mongo-server-url: - type: string - storage.docdb.mongo-server-url-dir: - type: string - storage.docdb.url: - type: string - storage.gcs.bucket: - description: storage configs - type: string - storage.grafeas.notehint: - type: string - storage.grafeas.noteid: - type: string - storage.grafeas.projectid: - type: string - storage.oci.repository: - type: string - storage.oci.repository.insecure: - type: boolean - transparency.enabled: - type: string - transparency.url: - type: string - required: - - disabled - - options - type: object - config: - description: Config holds the configuration for resources created - by TektonConfig - properties: - nodeSelector: - additionalProperties: - type: string - type: object - priorityClassName: - description: PriorityClassName holds the priority class to be - set to pod template - type: string - tolerations: - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - dashboard: - description: Dashboard holds the customizable options for dashboards - component - properties: - external-logs: - type: string - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - readonly: - description: Readonly when set to true configures the Tekton dashboard - in read-only mode - type: boolean - required: - - options - - readonly - type: object - hub: - description: Hub holds the hub config - properties: - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - params: - description: Params is the list of params passed for Hub customization - items: - description: Param declares an string value to use for the parameter - called name. - properties: - name: - type: string - value: - type: string - type: object - type: array - required: - - options - type: object - multiclusterProxyAAE: - description: MulticlusterProxyAAE holds the customizable options for - the multicluster-proxy-aae component - properties: - options: - description: options holds additional fields and these fields - will be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - required: - - options - type: object - params: - description: Params is the list of params passed for all platforms - items: - description: Param declares an string value to use for the parameter - called name. - properties: - name: - type: string - value: - type: string - type: object - type: array - pipeline: - description: Pipeline holds the customizable option for pipeline component - properties: - await-sidecar-readiness: - type: boolean - bundles-resolver-config: - additionalProperties: - type: string - type: object - cluster-resolver-config: - additionalProperties: - type: string - type: object - coschedule: - type: string - default-affinity-assistant-pod-template: - type: string - default-cloud-events-sink: - type: string - default-forbidden-env: - type: string - default-managed-by-label-value: - type: string - default-max-matrix-combinations-count: - type: string - default-pod-template: - type: string - default-resolver-type: - type: string - default-service-account: - type: string - default-task-run-workspace-binding: - type: string - default-timeout-minutes: - type: integer - disable-affinity-assistant: - description: |- - Deprecated: DisableAffinityAssistant is deprecated and no longer used. - This field is removed from pipeline component. - Keeping here to maintain API compatibility during upgrades. - type: boolean - disable-creds-init: - type: boolean - disable-inline-spec: - type: string - embedded-status: - type: string - enable-api-fields: - type: string - enable-bundles-resolver: - type: boolean - enable-cel-in-whenexpression: - type: boolean - enable-cluster-resolver: - type: boolean - enable-custom-tasks: - type: boolean - enable-git-resolver: - type: boolean - enable-hub-resolver: - type: boolean - enable-param-enum: - type: boolean - enable-provenance-in-status: - type: boolean - enable-step-actions: - type: boolean - enable-tekton-oci-bundles: - description: |- - not in use, see: https://github.com/tektoncd/pipeline/pull/7789 - this field is removed from pipeline component - keeping here to maintain the API compatibility - type: boolean - enforce-nonfalsifiability: - type: string - git-resolver-config: - additionalProperties: - type: string - type: object - hub-resolver-config: - additionalProperties: - type: string - type: object - keep-pod-on-cancel: - type: boolean - max-result-size: - type: integer - metrics.count.enable-reason: - type: boolean - metrics.pipelinerun.duration-type: - type: string - metrics.pipelinerun.level: - type: string - metrics.taskrun.duration-type: - type: string - metrics.taskrun.level: - type: string - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - params: - description: The params to customize different components of Pipelines - items: - description: Param declares an string value to use for the parameter - called name. - properties: - name: - type: string - value: - type: string - type: object - type: array - performance: - description: |- - PerformanceProperties defines the fields which are configurable - to tune the performance of component controller - properties: - buckets: - type: integer - disable-ha: - description: if it is true, disables the HA feature - type: boolean - kube-api-burst: - type: integer - kube-api-qps: - description: |- - queries per second (QPS) and burst to the master from rest API client - actually the number multiplied by 2 - https://github.com/pierretasci/pipeline/blob/05d67e427c722a2a57e58328d7097e21429b7524/cmd/controller/main.go#L85-L87 - defaults: https://github.com/tektoncd/pipeline/blob/34618964300620dca44d10a595e4af84e9903a55/vendor/k8s.io/client-go/rest/config.go#L45-L46 - type: number - replicas: - type: integer - statefulset-ordinals: - description: if is true, enable StatefulsetOrdinals mode - type: boolean - threads-per-controller: - description: The number of workers to use when processing - the component controller's work queue - type: integer - required: - - disable-ha - type: object - require-git-ssh-secret-known-hosts: - type: boolean - results-from: - type: string - running-in-environment-with-injected-sidecars: - type: boolean - scope-when-expressions-to-task: - description: ScopeWhenExpressionsToTask is deprecated and never - used. - type: boolean - send-cloudevents-for-runs: - type: boolean - set-security-context: - type: boolean - traces.credentialsSecret: - description: CredentialsSecret is the name of the secret containing - credentials for the tracing endpoint - type: string - traces.enabled: - description: Enabled controls whether tracing is enabled or not - type: boolean - traces.endpoint: - description: Endpoint is the URL for the OpenTelemetry trace collector - type: string - trusted-resources-verification-no-match-policy: - type: string - verification-mode: - type: string - required: - - options - type: object - platforms: - description: Platforms allows configuring platform specific configurations - properties: - kubernetes: - description: Kubernetes allows configuring kubernetes specific - components and configurations - properties: - pipelinesAsCode: - description: PipelinesAsCode allows configuring PipelinesAsCode - configurations - properties: - additionalPACControllers: - additionalProperties: - description: AdditionalPACControllerConfig contains - config for additionalPACControllers - properties: - configMapName: - description: Name of the additional controller configMap - type: string - enable: - description: Enable or disable this additional pipelines - as code instance by changing this bool - type: boolean - secretName: - description: Name of the additional controller Secret - type: string - settings: - additionalProperties: - type: string - description: Setting will contains the configMap - data - type: object - type: object - description: AdditionalPACControllers allows to deploy - additional PAC controller - type: object - enable: - description: Enable or disable pipelines as code by changing - this bool - type: boolean - options: - description: options holds additions fields and these - fields will be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for - webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure - policy that defines how unrecognized errors - from the admission endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types - of side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - settings: - additionalProperties: - type: string - type: object - required: - - options - type: object - type: object - openshift: - description: OpenShift allows configuring openshift specific components - and configurations - properties: - enableCentralTLSConfig: - description: |- - EnableCentralTLSConfig enables TLS configuration inheritance from - the cluster's APIServer TLS security profile. When enabled, TLS settings - (minimum version, cipher suites, curve preferences) are automatically - derived from the cluster-wide security policy and injected into Tekton - component containers that support TLS configuration. - If the APIServer does not have a TLS profile configured, user-specified - TLS settings in component configurations will be used as fallback. - Default: false (opt-in) - type: boolean - pipelinesAsCode: - description: PipelinesAsCode allows configuring PipelinesAsCode - configurations - properties: - additionalPACControllers: - additionalProperties: - description: AdditionalPACControllerConfig contains - config for additionalPACControllers - properties: - configMapName: - description: Name of the additional controller configMap - type: string - enable: - description: Enable or disable this additional pipelines - as code instance by changing this bool - type: boolean - secretName: - description: Name of the additional controller Secret - type: string - settings: - additionalProperties: - type: string - description: Setting will contains the configMap - data - type: object - type: object - description: AdditionalPACControllers allows to deploy - additional PAC controller - type: object - enable: - description: Enable or disable pipelines as code by changing - this bool - type: boolean - options: - description: options holds additions fields and these - fields will be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for - webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure - policy that defines how unrecognized errors - from the admission endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types - of side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - settings: - additionalProperties: - type: string - type: object - required: - - options - type: object - scc: - description: SCC allows configuring security context constraints - used by workloads - properties: - default: - description: |- - Default contains the default SCC that will be attached to the service - account used for workloads (`pipeline` SA by default) and defined in - PipelineProperties.OptionalPipelineProperties.DefaultServiceAccount - type: string - maxAllowed: - description: |- - MaxAllowed specifies the highest SCC that can be requested for in a - namespace or in the Default field. - type: string - type: object - type: object - type: object - profile: - type: string - pruner: - description: Pruner holds the prune config - properties: - disabled: - description: enable or disable pruner feature - type: boolean - keep: - description: |- - The number of resource to keep - You dont want to delete all the pipelinerun/taskrun's by a cron - type: integer - keep-since: - description: |- - KeepSince keeps the resources younger than the specified value - Its value is taken in minutes - type: integer - prune-per-resource: - description: apply the prune job to the individual resources - type: boolean - resources: - description: The resources which need to be pruned - items: - type: string - type: array - schedule: - description: How frequent pruning should happen - type: string - startingDeadlineSeconds: - description: |- - Optional deadline in seconds for starting the job if it misses scheduled time for any reason. - Missed jobs executions will be counted as failed ones. - type: integer - required: - - disabled - type: object - result: - description: Result holds the customize option for results component - properties: - auth_disable: - type: boolean - auth_impersonate: - type: boolean - db_enable_auto_migration: - type: boolean - db_host: - type: string - db_name: - type: string - db_port: - type: integer - db_secret_name: - type: string - db_secret_password_key: - type: string - db_secret_user_key: - type: string - db_sslmode: - type: string - db_sslrootcert: - type: string - disabled: - description: enable or disable Result Component - type: boolean - gcs_bucket_name: - type: string - gcs_creds_secret_key: - type: string - gcs_creds_secret_name: - type: string - is_external_db: - type: boolean - log_level: - type: string - logging_plugin_api_url: - type: string - logging_plugin_ca_cert: - type: string - logging_plugin_forwarder_delay_duration: - type: integer - logging_plugin_multipart_regex: - type: string - logging_plugin_namespace_key: - type: string - logging_plugin_proxy_path: - type: string - logging_plugin_query_limit: - type: integer - logging_plugin_query_params: - type: string - logging_plugin_static_labels: - type: string - logging_plugin_tls_verification_disable: - type: boolean - logging_plugin_token_path: - type: string - logging_pvc_name: - type: string - logs_api: - type: boolean - logs_buffer_size: - type: integer - logs_path: - type: string - logs_type: - type: string - loki_stack_name: - type: string - loki_stack_namespace: - type: string - options: - description: Options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - performance: - description: |- - PerformanceProperties defines the fields which are configurable - to tune the performance of component controller - properties: - buckets: - type: integer - disable-ha: - description: if it is true, disables the HA feature - type: boolean - kube-api-burst: - type: integer - kube-api-qps: - description: |- - queries per second (QPS) and burst to the master from rest API client - actually the number multiplied by 2 - https://github.com/pierretasci/pipeline/blob/05d67e427c722a2a57e58328d7097e21429b7524/cmd/controller/main.go#L85-L87 - defaults: https://github.com/tektoncd/pipeline/blob/34618964300620dca44d10a595e4af84e9903a55/vendor/k8s.io/client-go/rest/config.go#L45-L46 - type: number - replicas: - type: integer - statefulset-ordinals: - description: if is true, enable StatefulsetOrdinals mode - type: boolean - threads-per-controller: - description: The number of workers to use when processing - the component controller's work queue - type: integer - required: - - disable-ha - type: object - prometheus_histogram: - type: boolean - prometheus_port: - type: integer - route_enabled: - description: Route configuration for Results API service exposure - type: boolean - route_host: - type: string - route_path: - type: string - route_tls_termination: - type: string - secret_name: - description: |- - name of the secret used to get S3 credentials and - pass it as environment variables to the "tekton-results-api" deployment under "api" container - type: string - server_port: - type: integer - storage_emulator_host: - type: string - tls_hostname_override: - type: string - required: - - disabled - - is_external_db - - options - type: object - scheduler: - description: To enable Pipeline Scheduling on Single Cluster or Multiple - Clusters - properties: - config.yaml: - description: |- - This hold the config data from tekton-kueue. ConfigMap in tekton kueue is loaded as config.yaml so we need to - match the key here - x-kubernetes-preserve-unknown-fields: true - disabled: - description: enable or disable TektonScheduler Component - type: boolean - multi-cluster-disabled: - type: boolean - multi-cluster-role: - description: |- - MultiClusterRole Define the role of current cluster in multi-cluster environment. The MultiClusterRole - can be one of Hub or Spoke - type: string - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - required: - - config.yaml - - disabled - - multi-cluster-disabled - - multi-cluster-role - - options - type: object - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - targetNamespaceMetadata: - description: holds target namespace metadata - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - tektonpruner: - description: New EventBasedPruner which provides more granular control - over TaskRun and PipelineRuns - properties: - disabled: - description: enable or disable TektonPruner Component - type: boolean - global-config: - x-kubernetes-preserve-unknown-fields: true - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - required: - - disabled - - global-config - - options - type: object - trigger: - description: Trigger holds the customizable option for triggers component - properties: - default-service-account: - type: string - disabled: - description: enable or disable Trigger Component - type: boolean - enable-api-fields: - type: string - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of - side effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - required: - - disabled - - options - type: object - type: object - status: - description: TektonConfigStatus defines the observed state of TektonConfig - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - profile: - description: The profile installed - type: string - tektonInstallerSets: - additionalProperties: - type: string - description: The current installer set name - type: object - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonhubs.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonHub - listKind: TektonHubList - plural: tektonhubs - singular: tektonhub - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - - jsonPath: .status.apiUrl - name: ApiUrl - type: string - - jsonPath: .status.uiUrl - name: UiUrl - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonHub is the Schema for the tektonhub API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - api: - properties: - catalogRefreshInterval: - type: string - hubConfigUrl: - description: Deprecated, will be removed in further release - type: string - routeHostUrl: - type: string - secret: - type: string - type: object - catalogs: - items: - properties: - contextDir: - type: string - name: - type: string - org: - type: string - provider: - type: string - revision: - type: string - sshUrl: - type: string - type: - type: string - url: - type: string - type: object - type: array - categories: - items: - type: string - type: array - customLogo: - description: The Base64 Encode data and mediaType of the Custom Logo - properties: - base64Data: - type: string - mediaType: - type: string - type: object - db: - properties: - secret: - type: string - type: object - default: - properties: - scopes: - items: - type: string - type: array - type: object - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - params: - description: Params is the list of params passed for Hub customization - items: - description: Param declares an string value to use for the parameter - called name. - properties: - name: - type: string - value: - type: string - type: object - type: array - scopes: - items: - properties: - name: - type: string - users: - items: - type: string - type: array - type: object - type: array - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - required: - - options - type: object - status: - description: TektonHubStatus defines the observed state of TektonHub - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - apiUrl: - description: The URL route for API which needs to be exposed - type: string - authUrl: - description: The URL route for Auth server - type: string - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - hubInstallerSets: - additionalProperties: - type: string - description: The current installer set name - type: object - manifests: - description: The url links of the manifests, separated by comma - items: - type: string - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - uiUrl: - description: The URL route for UI which needs to be exposed - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektoninstallersets.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonInstallerSet - listKind: TektonInstallerSetList - plural: tektoninstallersets - singular: tektoninstallerset - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonInstallerSet is the Schema for the TektonInstallerSet API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: TektonInstallerSetSpec defines the desired state of TektonInstallerSet - properties: - manifests: - x-kubernetes-preserve-unknown-fields: true - type: object - status: - description: TektonInstallerSetStatus defines the observed state of TektonInstallerSet - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonpipelines.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonPipeline - listKind: TektonPipelineList - plural: tektonpipelines - singular: tektonpipeline - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonPipeline is the Schema for the tektonpipelines API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: TektonPipelineSpec defines the desired state of TektonPipeline - properties: - await-sidecar-readiness: - type: boolean - bundles-resolver-config: - additionalProperties: - type: string - type: object - cluster-resolver-config: - additionalProperties: - type: string - type: object - config: - description: Config holds the configuration for resources created - by TektonPipeline - properties: - nodeSelector: - additionalProperties: - type: string - type: object - priorityClassName: - description: PriorityClassName holds the priority class to be - set to pod template - type: string - tolerations: - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - coschedule: - type: string - default-affinity-assistant-pod-template: - type: string - default-cloud-events-sink: - type: string - default-forbidden-env: - type: string - default-managed-by-label-value: - type: string - default-max-matrix-combinations-count: - type: string - default-pod-template: - type: string - default-resolver-type: - type: string - default-service-account: - type: string - default-task-run-workspace-binding: - type: string - default-timeout-minutes: - type: integer - disable-affinity-assistant: - description: |- - Deprecated: DisableAffinityAssistant is deprecated and no longer used. - This field is removed from pipeline component. - Keeping here to maintain API compatibility during upgrades. - type: boolean - disable-creds-init: - type: boolean - disable-inline-spec: - type: string - embedded-status: - type: string - enable-api-fields: - type: string - enable-bundles-resolver: - type: boolean - enable-cel-in-whenexpression: - type: boolean - enable-cluster-resolver: - type: boolean - enable-custom-tasks: - type: boolean - enable-git-resolver: - type: boolean - enable-hub-resolver: - type: boolean - enable-param-enum: - type: boolean - enable-provenance-in-status: - type: boolean - enable-step-actions: - type: boolean - enable-tekton-oci-bundles: - description: |- - not in use, see: https://github.com/tektoncd/pipeline/pull/7789 - this field is removed from pipeline component - keeping here to maintain the API compatibility - type: boolean - enforce-nonfalsifiability: - type: string - git-resolver-config: - additionalProperties: - type: string - type: object - hub-resolver-config: - additionalProperties: - type: string - type: object - keep-pod-on-cancel: - type: boolean - max-result-size: - type: integer - metrics.count.enable-reason: - type: boolean - metrics.pipelinerun.duration-type: - type: string - metrics.pipelinerun.level: - type: string - metrics.taskrun.duration-type: - type: string - metrics.taskrun.level: - type: string - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - params: - description: The params to customize different components of Pipelines - items: - description: Param declares an string value to use for the parameter - called name. - properties: - name: - type: string - value: - type: string - type: object - type: array - performance: - description: |- - PerformanceProperties defines the fields which are configurable - to tune the performance of component controller - properties: - buckets: - type: integer - disable-ha: - description: if it is true, disables the HA feature - type: boolean - kube-api-burst: - type: integer - kube-api-qps: - description: |- - queries per second (QPS) and burst to the master from rest API client - actually the number multiplied by 2 - https://github.com/pierretasci/pipeline/blob/05d67e427c722a2a57e58328d7097e21429b7524/cmd/controller/main.go#L85-L87 - defaults: https://github.com/tektoncd/pipeline/blob/34618964300620dca44d10a595e4af84e9903a55/vendor/k8s.io/client-go/rest/config.go#L45-L46 - type: number - replicas: - type: integer - statefulset-ordinals: - description: if is true, enable StatefulsetOrdinals mode - type: boolean - threads-per-controller: - description: The number of workers to use when processing the - component controller's work queue - type: integer - required: - - disable-ha - type: object - require-git-ssh-secret-known-hosts: - type: boolean - results-from: - type: string - running-in-environment-with-injected-sidecars: - type: boolean - scope-when-expressions-to-task: - description: ScopeWhenExpressionsToTask is deprecated and never used. - type: boolean - send-cloudevents-for-runs: - type: boolean - set-security-context: - type: boolean - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - traces.credentialsSecret: - description: CredentialsSecret is the name of the secret containing - credentials for the tracing endpoint - type: string - traces.enabled: - description: Enabled controls whether tracing is enabled or not - type: boolean - traces.endpoint: - description: Endpoint is the URL for the OpenTelemetry trace collector - type: string - trusted-resources-verification-no-match-policy: - type: string - verification-mode: - type: string - required: - - options - type: object - status: - description: TektonPipelineStatus defines the observed state of TektonPipeline - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - extTektonInstallerSets: - additionalProperties: - type: string - description: The installer sets created for extension components - type: object - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - tektonInstallerSet: - description: The current installer set name for TektonPipeline - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonresults.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonResult - listKind: TektonResultList - plural: tektonresults - singular: tektonresult - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonResult is the Schema for the tektonresults API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: TektonResultSpec defines the desired state of TektonResult - properties: - auth_disable: - type: boolean - auth_impersonate: - type: boolean - config: - description: Config holds the configuration for resources created - by TektonResult - properties: - nodeSelector: - additionalProperties: - type: string - type: object - priorityClassName: - description: PriorityClassName holds the priority class to be - set to pod template - type: string - tolerations: - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - db_enable_auto_migration: - type: boolean - db_host: - type: string - db_name: - type: string - db_port: - type: integer - db_secret_name: - type: string - db_secret_password_key: - type: string - db_secret_user_key: - type: string - db_sslmode: - type: string - db_sslrootcert: - type: string - disabled: - description: enable or disable Result Component - type: boolean - gcs_bucket_name: - type: string - gcs_creds_secret_key: - type: string - gcs_creds_secret_name: - type: string - is_external_db: - type: boolean - log_level: - type: string - logging_plugin_api_url: - type: string - logging_plugin_ca_cert: - type: string - logging_plugin_forwarder_delay_duration: - type: integer - logging_plugin_multipart_regex: - type: string - logging_plugin_namespace_key: - type: string - logging_plugin_proxy_path: - type: string - logging_plugin_query_limit: - type: integer - logging_plugin_query_params: - type: string - logging_plugin_static_labels: - type: string - logging_plugin_tls_verification_disable: - type: boolean - logging_plugin_token_path: - type: string - logging_pvc_name: - type: string - logs_api: - type: boolean - logs_buffer_size: - type: integer - logs_path: - type: string - logs_type: - type: string - loki_stack_name: - type: string - loki_stack_namespace: - type: string - options: - description: Options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - performance: - description: |- - PerformanceProperties defines the fields which are configurable - to tune the performance of component controller - properties: - buckets: - type: integer - disable-ha: - description: if it is true, disables the HA feature - type: boolean - kube-api-burst: - type: integer - kube-api-qps: - description: |- - queries per second (QPS) and burst to the master from rest API client - actually the number multiplied by 2 - https://github.com/pierretasci/pipeline/blob/05d67e427c722a2a57e58328d7097e21429b7524/cmd/controller/main.go#L85-L87 - defaults: https://github.com/tektoncd/pipeline/blob/34618964300620dca44d10a595e4af84e9903a55/vendor/k8s.io/client-go/rest/config.go#L45-L46 - type: number - replicas: - type: integer - statefulset-ordinals: - description: if is true, enable StatefulsetOrdinals mode - type: boolean - threads-per-controller: - description: The number of workers to use when processing the - component controller's work queue - type: integer - required: - - disable-ha - type: object - prometheus_histogram: - type: boolean - prometheus_port: - type: integer - route_enabled: - description: Route configuration for Results API service exposure - type: boolean - route_host: - type: string - route_path: - type: string - route_tls_termination: - type: string - secret_name: - description: |- - name of the secret used to get S3 credentials and - pass it as environment variables to the "tekton-results-api" deployment under "api" container - type: string - server_port: - type: integer - storage_emulator_host: - type: string - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - tls_hostname_override: - type: string - required: - - disabled - - is_external_db - - options - type: object - status: - description: TektonResultStatus defines the observed state of TektonResult - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - tektonInstallerSet: - description: The current installer set name for TektonResult - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektontriggers.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonTrigger - listKind: TektonTriggerList - plural: tektontriggers - singular: tektontrigger - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonTrigger is the Schema for the tektontriggers API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: TektonTriggerSpec defines the desired state of TektonTrigger - properties: - config: - description: Config holds the configuration for resources created - by TektonTrigger - properties: - nodeSelector: - additionalProperties: - type: string - type: object - priorityClassName: - description: PriorityClassName holds the priority class to be - set to pod template - type: string - tolerations: - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - default-service-account: - type: string - disabled: - description: enable or disable Trigger Component - type: boolean - enable-api-fields: - type: string - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - required: - - disabled - - options - type: object - status: - description: TektonTriggerStatus defines the observed state of TektonTrigger - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - tektonInstallerSet: - description: The current installer set name - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonpruners.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonPruner - listKind: TektonPrunerList - plural: tektonpruners - singular: tektonpruner - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonPruner is the Schema for the TektonPruner API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - config: - description: Config holds the configuration for resources created - by TektonPruner - properties: - nodeSelector: - additionalProperties: - type: string - type: object - priorityClassName: - description: PriorityClassName holds the priority class to be - set to pod template - type: string - tolerations: - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - disabled: - description: enable or disable TektonPruner Component - type: boolean - global-config: - x-kubernetes-preserve-unknown-fields: true - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - required: - - disabled - - global-config - - options - type: object - status: - description: TektonPrunerStatus defines the observed state of TektonPruner - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - tektonInstallerSet: - description: The current installer set name for TektonPruner - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonschedulers.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonScheduler - listKind: TektonSchedulerList - plural: tektonschedulers - singular: tektonscheduler - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonScheduler is the Schema for the TektonScheduler API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - config.yaml: - description: |- - This hold the config data from tekton-kueue. ConfigMap in tekton kueue is loaded as config.yaml so we need to - match the key here - x-kubernetes-preserve-unknown-fields: true - disabled: - description: enable or disable TektonScheduler Component - type: boolean - multi-cluster-disabled: - type: boolean - multi-cluster-role: - description: |- - MultiClusterRole Define the role of current cluster in multi-cluster environment. The MultiClusterRole - can be one of Hub or Spoke - type: string - options: - description: options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - required: - - config.yaml - - disabled - - multi-cluster-disabled - - multi-cluster-role - - options - type: object - status: - description: TektonSchedulerStatus defines the observed state of TektonScheduler - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - tekton-scheduler: - description: The current installer set name for TektonScheduler - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: tektonmulticlusterproxyaaes.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: TektonMulticlusterProxyAAE - listKind: TektonMulticlusterProxyAAEList - plural: tektonmulticlusterproxyaaes - singular: tektonmulticlusterproxyaae - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TektonMulticlusterProxyAAE is the Schema for the TektonMulticlusterProxyAAE - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - options: - description: options holds additional fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - required: - - options - type: object - status: - description: TektonMulticlusterProxyAAEStatus defines the observed state - of TektonMulticlusterProxyAAE - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - tektonInstallerSet: - description: The current installer set name for TektonMulticlusterProxyAAE - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: syncerservices.operator.tekton.dev - labels: - version: "devel" - operator.tekton.dev/release: "devel" -spec: - group: operator.tekton.dev - names: - kind: SyncerService - listKind: SyncerServiceList - plural: syncerservices - singular: syncerservice - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.version - name: Version - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Reason - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: SyncerService is the Schema for the syncerservices API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SyncerServiceSpec defines the desired state of SyncerService - properties: - config: - description: Config holds the configuration for resources created - by SyncerService - properties: - nodeSelector: - additionalProperties: - type: string - type: object - priorityClassName: - description: PriorityClassName holds the priority class to be - set to pod template - type: string - tolerations: - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - options: - description: Options holds additions fields and these fields will - be updated on the manifests - properties: - configMaps: - x-kubernetes-preserve-unknown-fields: true - deployments: - x-kubernetes-preserve-unknown-fields: true - disabled: - type: boolean - horizontalPodAutoscalers: - x-kubernetes-preserve-unknown-fields: true - statefulSets: - x-kubernetes-preserve-unknown-fields: true - webhookConfigurationOptions: - additionalProperties: - description: WebhookOptions defines options for webhooks - properties: - failurePolicy: - description: FailurePolicyType specifies a failure policy - that defines how unrecognized errors from the admission - endpoint are handled. - type: string - sideEffects: - description: SideEffectClass specifies the types of side - effects a webhook may have. - type: string - timeoutSeconds: - type: integer - type: object - type: object - type: object - targetNamespace: - description: TargetNamespace is where resources will be installed - type: string - type: object - status: - description: SyncerServiceStatus defines the observed state of SyncerService - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is additional Status fields for the Resource to save some - additional State as well as convey more information to the user. This is - roughly akin to Annotations on any k8s resource, just the reconciler conveying - richer information outwards. - type: object - conditions: - description: Conditions the latest available observations of a resource's - current state. - items: - description: |- - Condition defines a readiness condition for a Knative resource. - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the last time the condition transitioned from one status to another. - We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic - differences (all other things held constant). - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - severity: - description: |- - Severity with which to treat failures of this type of condition. - When this is not specified, it defaults to Error. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: |- - ObservedGeneration is the 'Generation' of the Service that - was last processed by the controller. - type: integer - syncerServiceInstallerSet: - description: The current installer set name for SyncerService - type: string - version: - description: The version of the installed release - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end -}} diff --git a/charts/tekton-operator/templates/openshift-rbac.yaml b/charts/tekton-operator/templates/openshift-rbac.yaml index e5636f3c37..56dbeb2647 100644 --- a/charts/tekton-operator/templates/openshift-rbac.yaml +++ b/charts/tekton-operator/templates/openshift-rbac.yaml @@ -98,6 +98,18 @@ rules: - list - update - watch + - apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - delete + - create + - patch + - get + - list + - update + - watch - apiGroups: - "" resources: diff --git a/config/base/generated-crds/operator.tekton.dev_tektonconfigs.yaml b/config/base/generated-crds/operator.tekton.dev_tektonconfigs.yaml index 593e95c10c..8ea3ec1158 100644 --- a/config/base/generated-crds/operator.tekton.dev_tektonconfigs.yaml +++ b/config/base/generated-crds/operator.tekton.dev_tektonconfigs.yaml @@ -570,6 +570,26 @@ spec: type: object type: object type: object + networkPolicy: + description: |- + NetworkPolicy configures NetworkPolicy resources for the operand namespace. + This field is propagated to TektonTrigger, which is the only component with + NetworkPolicy reconciliation implemented. Other components (Pipeline, Chains, + Results, Dashboard) do not yet act on this field. + properties: + disabled: + description: |- + Disabled disables all NetworkPolicy creation for this component. + Existing policies are removed on the next reconcile. + type: boolean + policies: + description: |- + Policies merges with the operator's default NetworkPolicies by name. + A key matching a default policy name replaces that default entirely. + A key not matching any default is added alongside the defaults. + If nil or empty, all operator defaults are applied unchanged. + x-kubernetes-preserve-unknown-fields: true + type: object params: description: Params is the list of params passed for all platforms items: diff --git a/config/base/generated-crds/operator.tekton.dev_tektontriggers.yaml b/config/base/generated-crds/operator.tekton.dev_tektontriggers.yaml index a79d0ddf88..a42e23b976 100644 --- a/config/base/generated-crds/operator.tekton.dev_tektontriggers.yaml +++ b/config/base/generated-crds/operator.tekton.dev_tektontriggers.yaml @@ -108,6 +108,23 @@ spec: type: boolean enable-api-fields: type: string + networkPolicy: + description: NetworkPolicy configures NetworkPolicy creation for TektonTrigger + workloads. + properties: + disabled: + description: |- + Disabled disables all NetworkPolicy creation for this component. + Existing policies are removed on the next reconcile. + type: boolean + policies: + description: |- + Policies merges with the operator's default NetworkPolicies by name. + A key matching a default policy name replaces that default entirely. + A key not matching any default is added alongside the defaults. + If nil or empty, all operator defaults are applied unchanged. + x-kubernetes-preserve-unknown-fields: true + type: object options: description: options holds additions fields and these fields will be updated on the manifests diff --git a/config/base/role.yaml b/config/base/role.yaml index e760a23086..dabb584551 100644 --- a/config/base/role.yaml +++ b/config/base/role.yaml @@ -60,6 +60,18 @@ rules: - list - update - watch +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - delete + - create + - patch + - get + - list + - update + - watch - apiGroups: - "" resources: diff --git a/config/openshift/base/role.yaml b/config/openshift/base/role.yaml index bd5822ab79..85a630da9a 100644 --- a/config/openshift/base/role.yaml +++ b/config/openshift/base/role.yaml @@ -58,6 +58,18 @@ rules: - list - update - watch +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - delete + - create + - patch + - get + - list + - update + - watch - apiGroups: - "" resources: diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_types.go b/pkg/apis/operator/v1alpha1/tektonconfig_types.go index 4b62bb200e..415028dbfe 100644 --- a/pkg/apis/operator/v1alpha1/tektonconfig_types.go +++ b/pkg/apis/operator/v1alpha1/tektonconfig_types.go @@ -134,7 +134,10 @@ type TektonConfigSpec struct { // holds target namespace metadata // +optional TargetNamespaceMetadata *NamespaceMetadata `json:"targetNamespaceMetadata,omitempty"` - // NetworkPolicy configures namespace-wide NetworkPolicies for the operand namespace. + // NetworkPolicy configures NetworkPolicy resources for the operand namespace. + // This field is propagated to TektonTrigger, which is the only component with + // NetworkPolicy reconciliation implemented. Other components (Pipeline, Chains, + // Results, Dashboard) do not yet act on this field. // +optional NetworkPolicy NetworkPolicyConfig `json:"networkPolicy,omitempty"` } @@ -167,27 +170,27 @@ type TektonConfigStatus struct { } func (in *TektonConfigStatus) MarkInstallerSetReady() { - //TODO implement me + // TODO implement me panic("implement me") } func (in *TektonConfigStatus) MarkInstallerSetNotReady(s string) { - //TODO implement me + // TODO implement me panic("implement me") } func (in *TektonConfigStatus) MarkInstallerSetAvailable() { - //TODO implement me + // TODO implement me panic("implement me") } func (in *TektonConfigStatus) MarkPreReconcilerFailed(s string) { - //TODO implement me + // TODO implement me panic("implement me") } func (in *TektonConfigStatus) MarkPostReconcilerFailed(s string) { - //TODO implement me + // TODO implement me panic("implement me") } diff --git a/pkg/reconciler/common/networkpolicy/networkpolicy.go b/pkg/reconciler/common/networkpolicy/networkpolicy.go index 6a1723344f..03dc764ed3 100644 --- a/pkg/reconciler/common/networkpolicy/networkpolicy.go +++ b/pkg/reconciler/common/networkpolicy/networkpolicy.go @@ -83,15 +83,35 @@ func Generate( return mf.ManifestFrom(mf.Slice(resources)) } -// DNSEgressRule allows egress to DNS resolver pods on UDP and TCP port 5353. +// DefaultDenyPolicy returns a default-deny NetworkPolicy scoped to podSelector. +// Pass an empty metav1.LabelSelector{} for a namespace-wide deny (once all +// components implement NetworkPolicy support). Until then, each component passes +// its own selector (e.g. app.kubernetes.io/part-of: tekton-triggers) so only +// its pods are affected. +func DefaultDenyPolicy(name string, podSelector metav1.LabelSelector) networkingv1.NetworkPolicy { + return networkingv1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: name}, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: podSelector, + PolicyTypes: []networkingv1.PolicyType{ + networkingv1.PolicyTypeIngress, + networkingv1.PolicyTypeEgress, + }, + }, + } +} + +// DNSEgressRule allows egress to DNS resolver pods on UDP and TCP using the +// platform-specific DNS port (53 on Kubernetes, 5353 on OpenShift). func DNSEgressRule(p PlatformParams) networkingv1.NetworkPolicyEgressRule { udp := corev1.ProtocolUDP tcp := corev1.ProtocolTCP - dnsPort := intstr.FromInt32(5353) + udpPort := intstr.FromInt32(p.DNSPort) + tcpPort := intstr.FromInt32(p.DNSPort) return networkingv1.NetworkPolicyEgressRule{ Ports: []networkingv1.NetworkPolicyPort{ - {Protocol: &udp, Port: &dnsPort}, - {Protocol: &tcp, Port: &dnsPort}, + {Protocol: &udp, Port: &udpPort}, + {Protocol: &tcp, Port: &tcpPort}, }, To: []networkingv1.NetworkPolicyPeer{ { @@ -106,11 +126,14 @@ func DNSEgressRule(p PlatformParams) networkingv1.NetworkPolicyEgressRule { } } -// APIServerEgressRule allows egress on TCP 6443 to any destination. -// The API server is typically host-networked so no pod/namespace selector is needed. -func APIServerEgressRule() networkingv1.NetworkPolicyEgressRule { +// APIServerEgressRule allows egress to the Kubernetes API server on the platform-specific port. +// Vanilla Kubernetes exposes the API server via kubernetes.default.svc on port 443 (targetPort 6443). +// OpenShift exposes it directly on port 6443. +// No To restriction is set because the API server is typically host-networked or behind a +// ClusterIP service that does not match a pod/namespace selector. +func APIServerEgressRule(p PlatformParams) networkingv1.NetworkPolicyEgressRule { tcp := corev1.ProtocolTCP - apiPort := intstr.FromInt32(6443) + apiPort := intstr.FromInt32(p.APIServerPort) return networkingv1.NetworkPolicyEgressRule{ Ports: []networkingv1.NetworkPolicyPort{ {Protocol: &tcp, Port: &apiPort}, @@ -120,13 +143,14 @@ func APIServerEgressRule() networkingv1.NetworkPolicyEgressRule { // InternetEgressRule allows egress on TCP 80 and 443 to any destination. func InternetEgressRule() networkingv1.NetworkPolicyEgressRule { - tcp := corev1.ProtocolTCP + tcpHTTP := corev1.ProtocolTCP + tcpHTTPS := corev1.ProtocolTCP httpPort := intstr.FromInt32(80) httpsPort := intstr.FromInt32(443) return networkingv1.NetworkPolicyEgressRule{ Ports: []networkingv1.NetworkPolicyPort{ - {Protocol: &tcp, Port: &httpPort}, - {Protocol: &tcp, Port: &httpsPort}, + {Protocol: &tcpHTTP, Port: &httpPort}, + {Protocol: &tcpHTTPS, Port: &httpsPort}, }, } } diff --git a/pkg/reconciler/common/networkpolicy/networkpolicy_test.go b/pkg/reconciler/common/networkpolicy/networkpolicy_test.go index 6683918404..4533e38408 100644 --- a/pkg/reconciler/common/networkpolicy/networkpolicy_test.go +++ b/pkg/reconciler/common/networkpolicy/networkpolicy_test.go @@ -177,10 +177,22 @@ func TestInternetEgressRule(t *testing.T) { } } -func TestAPIServerEgressRule(t *testing.T) { - rule := networkpolicy.APIServerEgressRule() +func TestAPIServerEgressRule_Kubernetes(t *testing.T) { + params := networkpolicy.KubernetesPlatformDefaults() + rule := networkpolicy.APIServerEgressRule(params) + if len(rule.Ports) != 1 || rule.Ports[0].Port.IntVal != 443 { + t.Fatalf("expected port 443 for Kubernetes, got %v", rule.Ports) + } + if len(rule.To) != 0 { + t.Errorf("expected no To restriction for API server egress, got %v", rule.To) + } +} + +func TestAPIServerEgressRule_OpenShift(t *testing.T) { + params := networkpolicy.OpenShiftPlatformDefaults() + rule := networkpolicy.APIServerEgressRule(params) if len(rule.Ports) != 1 || rule.Ports[0].Port.IntVal != 6443 { - t.Fatalf("expected port 6443, got %v", rule.Ports) + t.Fatalf("expected port 6443 for OpenShift, got %v", rule.Ports) } if len(rule.To) != 0 { t.Errorf("expected no To restriction for API server egress, got %v", rule.To) @@ -191,7 +203,12 @@ func TestDNSEgressRule_Kubernetes(t *testing.T) { params := networkpolicy.KubernetesPlatformDefaults() rule := networkpolicy.DNSEgressRule(params) if len(rule.Ports) != 2 { - t.Fatalf("expected 2 ports (UDP+TCP 5353), got %d", len(rule.Ports)) + t.Fatalf("expected 2 ports (UDP+TCP 53), got %d", len(rule.Ports)) + } + for _, p := range rule.Ports { + if p.Port.IntVal != 53 { + t.Errorf("expected DNS port 53 for Kubernetes, got %d", p.Port.IntVal) + } } if len(rule.To) != 1 || rule.To[0].NamespaceSelector == nil { t.Fatalf("expected 1 To with NamespaceSelector, got %v", rule.To) @@ -205,10 +222,18 @@ func TestDNSEgressRule_Kubernetes(t *testing.T) { func TestDNSEgressRule_OpenShift(t *testing.T) { params := networkpolicy.OpenShiftPlatformDefaults() rule := networkpolicy.DNSEgressRule(params) + if len(rule.To) == 0 || rule.To[0].NamespaceSelector == nil { + t.Fatalf("expected 1 To with NamespaceSelector, got %v", rule.To) + } nsLabels := rule.To[0].NamespaceSelector.MatchLabels if nsLabels["kubernetes.io/metadata.name"] != "openshift-dns" { t.Errorf("expected openshift-dns namespace selector, got %v", nsLabels) } + for _, p := range rule.Ports { + if p.Port.IntVal != 5353 { + t.Errorf("expected DNS port 5353 for OpenShift, got %d", p.Port.IntVal) + } + } } func TestPrometheusIngressRule(t *testing.T) { @@ -226,3 +251,19 @@ func TestPrometheusIngressRule(t *testing.T) { t.Errorf("expected port 9000, got %v", rule.Ports) } } + +func TestPrometheusIngressRule_OpenShift(t *testing.T) { + params := networkpolicy.OpenShiftPlatformDefaults() + port := intstr.FromInt32(9000) + rule := networkpolicy.PrometheusIngressRule(params, port) + if len(rule.From) != 1 || rule.From[0].NamespaceSelector == nil { + t.Fatalf("expected 1 From with NamespaceSelector, got %v", rule.From) + } + nsLabels := rule.From[0].NamespaceSelector.MatchLabels + if nsLabels["openshift.io/cluster-monitoring"] != "true" { + t.Errorf("expected openshift.io/cluster-monitoring: true, got %v", nsLabels) + } + if len(rule.Ports) != 1 || rule.Ports[0].Port.IntVal != 9000 { + t.Errorf("expected port 9000, got %v", rule.Ports) + } +} diff --git a/pkg/reconciler/common/networkpolicy/platform.go b/pkg/reconciler/common/networkpolicy/platform.go index 3bf87e2d59..b5c832de43 100644 --- a/pkg/reconciler/common/networkpolicy/platform.go +++ b/pkg/reconciler/common/networkpolicy/platform.go @@ -22,6 +22,16 @@ type PlatformParams struct { DNSResolverNamespace string DNSResolverPodLabel map[string]string PrometheusNamespaceLabel map[string]string + // DNSPort is the port the platform's DNS resolver pods listen on. + // Vanilla Kubernetes CoreDNS pods listen on 53. + // OpenShift DNS pods listen on 5353 (host-networked daemonset); OVN-Kubernetes + // enforces NetworkPolicy after DNAT, so the policy must match the pod port (5353), + // not the dns-default service port (53). + DNSPort int32 + // APIServerPort is the port the Kubernetes API server service exposes to pods. + // Vanilla Kubernetes exposes the api-server via the kubernetes.default.svc service on + // port 443 (targetPort 6443). OpenShift exposes it on port 6443 directly. + APIServerPort int32 } // KubernetesPlatformDefaults returns PlatformParams for vanilla Kubernetes. @@ -30,6 +40,8 @@ func KubernetesPlatformDefaults() PlatformParams { DNSResolverNamespace: "kube-system", DNSResolverPodLabel: map[string]string{"k8s-app": "kube-dns"}, PrometheusNamespaceLabel: map[string]string{"kubernetes.io/metadata.name": "monitoring"}, + DNSPort: 53, + APIServerPort: 443, } } @@ -39,5 +51,7 @@ func OpenShiftPlatformDefaults() PlatformParams { DNSResolverNamespace: "openshift-dns", DNSResolverPodLabel: map[string]string{"dns.operator.openshift.io/daemonset-dns": "default"}, PrometheusNamespaceLabel: map[string]string{"openshift.io/cluster-monitoring": "true"}, + DNSPort: 5353, + APIServerPort: 6443, } } diff --git a/pkg/reconciler/kubernetes/tektontrigger/controller.go b/pkg/reconciler/kubernetes/tektontrigger/controller.go index 3deee451c5..c21ce4a78a 100644 --- a/pkg/reconciler/kubernetes/tektontrigger/controller.go +++ b/pkg/reconciler/kubernetes/tektontrigger/controller.go @@ -30,6 +30,7 @@ import ( tektonTriggerinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektontrigger" tektonTriggerreconciler "github.com/tektoncd/operator/pkg/client/injection/reconciler/operator/v1alpha1/tektontrigger" "github.com/tektoncd/operator/pkg/reconciler/common" + "github.com/tektoncd/operator/pkg/reconciler/common/networkpolicy" "knative.dev/pkg/configmap" "knative.dev/pkg/controller" "knative.dev/pkg/injection" @@ -65,6 +66,11 @@ func NewExtendedController(generator common.ExtensionGenerator) injection.Contro tisClient := operatorclient.Get(ctx).OperatorV1alpha1().TektonInstallerSets() + params := networkpolicy.KubernetesPlatformDefaults() + if v1alpha1.IsOpenShiftPlatform() { + params = networkpolicy.OpenShiftPlatformDefaults() + } + c := &Reconciler{ kubeClientSet: kubeclient.Get(ctx), pipelineInformer: tektonPipelineinformer.Get(ctx), @@ -72,6 +78,7 @@ func NewExtendedController(generator common.ExtensionGenerator) injection.Contro extension: generator(ctx), manifest: manifest, triggersVersion: triggersVer, + platformParams: params, } impl := tektonTriggerreconciler.NewImpl(ctx, c) diff --git a/pkg/reconciler/kubernetes/tektontrigger/finalize.go b/pkg/reconciler/kubernetes/tektontrigger/finalize.go index 60f7c9bc49..b2f59faf8d 100644 --- a/pkg/reconciler/kubernetes/tektontrigger/finalize.go +++ b/pkg/reconciler/kubernetes/tektontrigger/finalize.go @@ -32,9 +32,9 @@ var _ tektontriggerreconciler.Finalizer = (*Reconciler)(nil) func (r *Reconciler) FinalizeKind(ctx context.Context, original *v1alpha1.TektonTrigger) pkgreconciler.Event { logger := logging.FromContext(ctx) - //Delete CRDs before deleting rest of resources so that any instance - //of CRDs which has finalizer set will get deleted before we remove - //the controller;s deployment for it + // Delete CRDs before deleting rest of resources so that any instance + // of CRDs which has finalizer set will get deleted before we remove + // the controller;s deployment for it if err := r.manifest.Filter(mf.CRDs).Delete(); err != nil { logger.Error("Failed to deleted CRDs for TektonTrigger") return err @@ -45,6 +45,11 @@ func (r *Reconciler) FinalizeKind(ctx context.Context, original *v1alpha1.Tekton return err } + if err := r.installerSetClient.CleanupCustomSet(ctx, "triggers-network-policies"); err != nil { + logger.Error("failed to cleanup triggers network policies installerset: ", err) + return err + } + if err := r.extension.Finalize(ctx, original); err != nil { logger.Error("Failed to finalize platform resources", err) } diff --git a/pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go b/pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go new file mode 100644 index 0000000000..1b6cf41379 --- /dev/null +++ b/pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go @@ -0,0 +1,158 @@ +/* +Copyright 2024 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 + + 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 tektontrigger + +import ( + "context" + + mf "github.com/manifestival/manifestival" + "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1" + "github.com/tektoncd/operator/pkg/reconciler/common/networkpolicy" + "github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client" + corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func triggersDefaultPolicies(params networkpolicy.PlatformParams) []networkingv1.NetworkPolicy { + metricsPort := intstr.FromInt32(9000) + webhookPort := intstr.FromInt32(8443) + interceptorPort := intstr.FromInt32(8443) + tcp := corev1.ProtocolTCP + + return []networkingv1.NetworkPolicy{ + { + ObjectMeta: metav1.ObjectMeta{Name: "triggers-controller"}, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "tekton-triggers-controller"}, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress, networkingv1.PolicyTypeEgress}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + networkpolicy.PrometheusIngressRule(params, metricsPort), + }, + Egress: []networkingv1.NetworkPolicyEgressRule{ + networkpolicy.DNSEgressRule(params), + networkpolicy.APIServerEgressRule(params), + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "triggers-webhook"}, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "tekton-triggers-webhook"}, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress, networkingv1.PolicyTypeEgress}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + // cidr="" → allow from any source; operator defaults to permissive. + // Users can restrict to a specific control-plane CIDR via spec.networkPolicy.policies. + networkpolicy.WebhookIngressRule("", webhookPort), + networkpolicy.PrometheusIngressRule(params, metricsPort), + }, + Egress: []networkingv1.NetworkPolicyEgressRule{ + networkpolicy.DNSEgressRule(params), + networkpolicy.APIServerEgressRule(params), + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "triggers-core-interceptors"}, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "tekton-triggers-core-interceptors"}, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress, networkingv1.PolicyTypeEgress}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + // EventListeners live in user-controlled namespaces — allow ingress from all namespaces. + From: []networkingv1.NetworkPolicyPeer{ + {NamespaceSelector: &metav1.LabelSelector{}}, + }, + Ports: []networkingv1.NetworkPolicyPort{ + {Protocol: &tcp, Port: &interceptorPort}, + }, + }, + networkpolicy.PrometheusIngressRule(params, metricsPort), + }, + Egress: []networkingv1.NetworkPolicyEgressRule{ + networkpolicy.DNSEgressRule(params), + networkpolicy.APIServerEgressRule(params), + // Core interceptors may call external APIs (e.g. GitHub) to fetch files, + // verify ownership, or perform other outbound operations. + networkpolicy.InternetEgressRule(), + }, + }, + }, + } +} + +// defaultDenyPolicy returns the default-deny NetworkPolicy for the Tekton namespace. +// +// Naming: the policy is intentionally named "tekton-default-deny" (not +// "tekton-triggers-default-deny"). The long-term design is for a single +// namespace-wide deny to be owned by one component (TektonPipeline), so all +// components converge on the same name. Do NOT rename this to a component-specific +// name — doing so would leave orphaned per-component deny policies once the +// namespace-wide policy takes over, and would break the migration path. +// +// Temporary placement: this lives here because TektonTrigger is the first component +// to implement NetworkPolicy support. TektonConfig cannot own it (no InstallerSetClient), +// so the intended long-term owner is TektonPipeline, which is the foundational component +// that all others depend on and already has an InstallerSetClient. +// +// Migration path: once all components (Pipeline, Chains, Results, Dashboard…) implement +// NetworkPolicy support, this function should move to the TektonPipeline reconciler, +// the pod selector should be widened to an empty metav1.LabelSelector{} (namespace-wide +// deny), and this copy removed. +func defaultDenyPolicy() networkingv1.NetworkPolicy { + return networkpolicy.DefaultDenyPolicy( + "tekton-default-deny", + metav1.LabelSelector{ + MatchLabels: map[string]string{"app.kubernetes.io/part-of": "tekton-triggers"}, + }, + ) +} + +func (r *Reconciler) reconcileNetworkPolicies(ctx context.Context, tt *v1alpha1.TektonTrigger) error { + if tt.Spec.NetworkPolicy.Disabled { + return r.installerSetClient.CleanupCustomSet(ctx, "triggers-network-policies") + } + defaults := append( + []networkingv1.NetworkPolicy{defaultDenyPolicy()}, + triggersDefaultPolicies(r.platformParams)..., + ) + manifest, err := networkpolicy.Generate( + tt.Spec.NetworkPolicy, + tt.Spec.GetTargetNamespace(), + defaults, + ) + if err != nil { + return err + } + return r.installerSetClient.CustomSet(ctx, tt, "triggers-network-policies", &manifest, passthroughTransform, nil) +} + +// passthroughTransform is a no-op FilterAndTransform used for pre-built manifests +// where namespace injection is already handled by Generate. +func passthroughTransform(_ context.Context, m *mf.Manifest, _ v1alpha1.TektonComponent) (*mf.Manifest, error) { + return m, nil +} + +// Ensure passthroughTransform satisfies the FilterAndTransform type. +var _ client.FilterAndTransform = passthroughTransform diff --git a/pkg/reconciler/kubernetes/tektontrigger/reconcile.go b/pkg/reconciler/kubernetes/tektontrigger/reconcile.go index 9808d20026..3e1028fb35 100644 --- a/pkg/reconciler/kubernetes/tektontrigger/reconcile.go +++ b/pkg/reconciler/kubernetes/tektontrigger/reconcile.go @@ -25,6 +25,7 @@ import ( pipelineinformer "github.com/tektoncd/operator/pkg/client/informers/externalversions/operator/v1alpha1" tektontriggerreconciler "github.com/tektoncd/operator/pkg/client/injection/reconciler/operator/v1alpha1/tektontrigger" "github.com/tektoncd/operator/pkg/reconciler/common" + "github.com/tektoncd/operator/pkg/reconciler/common/networkpolicy" "github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +50,8 @@ type Reconciler struct { extension common.Extension // version of triggers which we are installing triggersVersion string + // platformParams holds platform-specific values for building NetworkPolicy rules + platformParams networkpolicy.PlatformParams } // Check that our Reconciler implements controller.Reconciler @@ -81,8 +84,8 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, tt *v1alpha1.TektonTrigg return err } - //Make sure TektonPipeline is installed before proceeding with - //TektonTrigger + // Make sure TektonPipeline is installed before proceeding with + // TektonTrigger logger.Debug("Checking TektonPipeline dependency") if _, err := common.PipelineReady(r.pipelineInformer); err != nil { if err.Error() == common.PipelineNotReady || err == v1alpha1.DEPENDENCY_UPGRADE_PENDING_ERR { @@ -121,7 +124,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, tt *v1alpha1.TektonTrigg return nil } - //Mark PreReconcile Complete + // Mark PreReconcile Complete tt.Status.MarkPreReconcilerComplete() logger.Info("PreReconciliation completed successfully") @@ -139,13 +142,23 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, tt *v1alpha1.TektonTrigg logger.Info("Main reconciliation requested requeue") return err } - msg := fmt.Sprintf("Main Reconcilation failed: %s", err.Error()) + msg := fmt.Sprintf("Main Reconciliation failed: %s", err.Error()) logger.Errorw("Main reconciliation failed", "error", err) tt.Status.MarkInstallerSetNotReady(msg) return nil } logger.Info("Main reconciliation completed successfully") + if err := r.reconcileNetworkPolicies(ctx, tt); err != nil { + if err == v1alpha1.REQUEUE_EVENT_AFTER { + return err + } + msg := fmt.Sprintf("NetworkPolicy reconciliation failed: %s", err.Error()) + logger.Errorw("NetworkPolicy reconciliation failed", "error", err) + tt.Status.MarkInstallerSetNotReady(msg) + return nil + } + logger.Debug("Running post-reconciliation steps") if err := r.extension.PostReconcile(ctx, tt); err != nil { if err == v1alpha1.REQUEUE_EVENT_AFTER { diff --git a/pkg/reconciler/shared/tektonconfig/trigger/trigger.go b/pkg/reconciler/shared/tektonconfig/trigger/trigger.go index 01525ddb1a..b877a36a77 100644 --- a/pkg/reconciler/shared/tektonconfig/trigger/trigger.go +++ b/pkg/reconciler/shared/tektonconfig/trigger/trigger.go @@ -75,8 +75,9 @@ func GetTektonTriggerCR(config *v1alpha1.TektonConfig, operatorVersion string) * CommonSpec: v1alpha1.CommonSpec{ TargetNamespace: config.Spec.TargetNamespace, }, - Config: config.Spec.Config, - Trigger: config.Spec.Trigger, + Config: config.Spec.Config, + Trigger: config.Spec.Trigger, + NetworkPolicy: config.Spec.NetworkPolicy, }, } } @@ -115,6 +116,11 @@ func UpdateTrigger(ctx context.Context, old *v1alpha1.TektonTrigger, new *v1alph updated = true } + if !reflect.DeepEqual(old.Spec.NetworkPolicy, new.Spec.NetworkPolicy) { + old.Spec.NetworkPolicy = new.Spec.NetworkPolicy + updated = true + } + if old.ObjectMeta.OwnerReferences == nil { old.ObjectMeta.OwnerReferences = new.ObjectMeta.OwnerReferences updated = true From 6387f82f94b1288b64c43fcfc91ac287100397fc Mon Sep 17 00:00:00 2001 From: Khurram Baig Date: Thu, 2 Jul 2026 15:09:32 +0530 Subject: [PATCH 3/3] test(triggers): add e2e tests for NetworkPolicy support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add TestTektonTriggerNetworkPolicy covering: - Default NetworkPolicies created when TektonTrigger is Ready - Triggers functional end-to-end with policies in place: - CEL interceptor matching event (action=push) → PipelineRun created, exercising interceptors ingress from all namespaces on port 8443 and interceptors → API server egress - CEL interceptor non-matching event (action=open) → blocked by interceptor, no new PipelineRun created - spec.networkPolicy.disabled=true removes all policies - Re-enabling restores all policies Add helper functions in test/resources/networkpolicies.go: AssertNetworkPoliciesExist, AssertNetworkPoliciesAbsent, AssertEventListenerReady, AssertPipelineRunCreated, AssertPipelineRunCountUnchanged. Add testdata/triggers/ with Pipeline, TriggerBinding, TriggerTemplate, and EventListener (with CEL interceptor) YAML fixtures. Signed-off-by: Khurram Baig Assisted-by: Claude Sonnet 4.6 --- docs/NetworkPolicy.md | 82 ++++++++ .../operator/v1alpha1/networkpolicy_config.go | 16 +- .../v1alpha1/tektontrigger_validation.go | 3 +- .../common/networkpolicy/networkpolicy.go | 19 +- .../common/networkpolicy/platform.go | 11 +- .../tektontrigger/networkpolicies.go | 28 +-- .../03_tektontrigger_networkpolicy_test.go | 192 ++++++++++++++++++ .../testdata/triggers/eventlistener.yaml | 16 ++ .../common/testdata/triggers/pipeline.yaml | 12 ++ test/e2e/common/testdata/triggers/rbac.yaml | 33 +++ .../testdata/triggers/triggertemplate.yaml | 13 ++ test/resources/networkpolicies.go | 123 +++++++++++ 12 files changed, 503 insertions(+), 45 deletions(-) create mode 100644 docs/NetworkPolicy.md create mode 100644 test/e2e/common/03_tektontrigger_networkpolicy_test.go create mode 100644 test/e2e/common/testdata/triggers/eventlistener.yaml create mode 100644 test/e2e/common/testdata/triggers/pipeline.yaml create mode 100644 test/e2e/common/testdata/triggers/rbac.yaml create mode 100644 test/e2e/common/testdata/triggers/triggertemplate.yaml create mode 100644 test/resources/networkpolicies.go diff --git a/docs/NetworkPolicy.md b/docs/NetworkPolicy.md new file mode 100644 index 0000000000..2bb28e97cf --- /dev/null +++ b/docs/NetworkPolicy.md @@ -0,0 +1,82 @@ + +# NetworkPolicy + +The operator can manage [NetworkPolicy][np] resources for Tekton component workloads. +Currently only TektonTrigger is supported; other components will be added later. + +Configuration is available via `TektonConfig`: + +```yaml +apiVersion: operator.tekton.dev/v1alpha1 +kind: TektonConfig +metadata: + name: config +spec: + networkPolicy: + disabled: false # set to true to remove all managed NetworkPolicies + policies: # override or add policies by name + triggers-controller: # replaces the default triggers-controller policy + podSelector: + matchLabels: + app: tekton-triggers-controller + policyTypes: [Ingress] + ingress: + - ports: + - port: 9000 +``` + +The `networkPolicy` field is propagated from `TektonConfig` to `TektonTrigger`. +Users can also configure it directly on the `TektonTrigger` CR. + +## Default Policies + +When NetworkPolicy is enabled (the default), the following policies are applied +to the operand namespace (e.g. `tekton-pipelines` or `openshift-pipelines`): + +| Policy | Direction | Port | Source / Destination | +|---|---|---|---| +| `tekton-default-deny` | deny all | — | All pods with `app.kubernetes.io/part-of: tekton-triggers` | +| `triggers-controller` | ingress | TCP/9000 | Prometheus namespace | +| | egress | UDP+TCP/53 (K8s) or 5353 (OpenShift) | DNS resolver pods | +| | egress | TCP/443 (K8s) or 6443 (OpenShift) | API server | +| `triggers-webhook` | ingress | TCP/8443 | Any (admission webhook) | +| | ingress | TCP/9000 | Prometheus namespace | +| | egress | UDP+TCP/53 or 5353 | DNS resolver pods | +| | egress | TCP/443 or 6443 | API server | +| `triggers-core-interceptors` | ingress | TCP/8443 | All namespaces (EventListeners) | +| | ingress | TCP/9000 | Prometheus namespace | +| | egress | UDP+TCP/53 or 5353 | DNS resolver pods | +| | egress | TCP/443 or 6443 | API server | +| | egress | TCP/80, 443 | Any (external APIs e.g. GitHub) | + +### Platform differences + +| Parameter | Kubernetes | OpenShift | +|---|---|---| +| DNS port | 53 | 5353 | +| DNS namespace | `kube-system` | `openshift-dns` | +| API server port | 443 | 6443 | +| Prometheus namespace label | `kubernetes.io/metadata.name: monitoring` | `openshift.io/cluster-monitoring: "true"` | + +## Disabling + +```yaml +spec: + networkPolicy: + disabled: true +``` + +This removes all managed NetworkPolicies from the operand namespace. + +## Overriding a policy + +Entries in `spec.networkPolicy.policies` replace or add policies by name. +To override a default policy, use the same name (e.g. `triggers-controller`). +New names add additional policies alongside the defaults. + +[np]: https://kubernetes.io/docs/concepts/services-networking/network-policies/ diff --git a/pkg/apis/operator/v1alpha1/networkpolicy_config.go b/pkg/apis/operator/v1alpha1/networkpolicy_config.go index 952f6b7c06..e02e111ada 100644 --- a/pkg/apis/operator/v1alpha1/networkpolicy_config.go +++ b/pkg/apis/operator/v1alpha1/networkpolicy_config.go @@ -16,7 +16,12 @@ limitations under the License. package v1alpha1 -import networkingv1 "k8s.io/api/networking/v1" +import ( + "k8s.io/apimachinery/pkg/util/validation" + "knative.dev/pkg/apis" + + networkingv1 "k8s.io/api/networking/v1" +) // NetworkPolicyConfig configures NetworkPolicy creation for a Tekton component. type NetworkPolicyConfig struct { @@ -34,3 +39,12 @@ type NetworkPolicyConfig struct { // +kubebuilder:validation:Schemaless Policies map[string]networkingv1.NetworkPolicySpec `json:"policies,omitempty"` } + +func (c NetworkPolicyConfig) validate(path string) (errs *apis.FieldError) { + for name := range c.Policies { + if msgs := validation.IsDNS1123Subdomain(name); len(msgs) > 0 { + errs = errs.Also(apis.ErrInvalidKeyName(name, path+".policies", msgs...)) + } + } + return errs +} diff --git a/pkg/apis/operator/v1alpha1/tektontrigger_validation.go b/pkg/apis/operator/v1alpha1/tektontrigger_validation.go index 2a23b23a80..9c353c878c 100644 --- a/pkg/apis/operator/v1alpha1/tektontrigger_validation.go +++ b/pkg/apis/operator/v1alpha1/tektontrigger_validation.go @@ -25,7 +25,6 @@ import ( ) func (tr *TektonTrigger) Validate(ctx context.Context) (errs *apis.FieldError) { - if apis.IsInDelete(ctx) { return nil } @@ -37,12 +36,12 @@ func (tr *TektonTrigger) Validate(ctx context.Context) (errs *apis.FieldError) { // execute common spec validations errs = errs.Also(tr.Spec.CommonSpec.validate("spec")) + errs = errs.Also(tr.Spec.NetworkPolicy.validate("spec.networkPolicy")) return errs.Also(tr.Spec.TriggersProperties.validate("spec")) } func (tr *TriggersProperties) validate(path string) (errs *apis.FieldError) { - if tr.EnableApiFields != "" { if tr.EnableApiFields != config.StableAPIFieldValue && tr.EnableApiFields != config.AlphaAPIFieldValue { errs = errs.Also(apis.ErrInvalidValue(tr.EnableApiFields, path+".enable-api-fields")) diff --git a/pkg/reconciler/common/networkpolicy/networkpolicy.go b/pkg/reconciler/common/networkpolicy/networkpolicy.go index 03dc764ed3..3a0115a4d4 100644 --- a/pkg/reconciler/common/networkpolicy/networkpolicy.go +++ b/pkg/reconciler/common/networkpolicy/networkpolicy.go @@ -84,10 +84,7 @@ func Generate( } // DefaultDenyPolicy returns a default-deny NetworkPolicy scoped to podSelector. -// Pass an empty metav1.LabelSelector{} for a namespace-wide deny (once all -// components implement NetworkPolicy support). Until then, each component passes -// its own selector (e.g. app.kubernetes.io/part-of: tekton-triggers) so only -// its pods are affected. +// Use an empty LabelSelector{} for a namespace-wide deny once all components support NetworkPolicy. func DefaultDenyPolicy(name string, podSelector metav1.LabelSelector) networkingv1.NetworkPolicy { return networkingv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{Name: name}, @@ -126,11 +123,8 @@ func DNSEgressRule(p PlatformParams) networkingv1.NetworkPolicyEgressRule { } } -// APIServerEgressRule allows egress to the Kubernetes API server on the platform-specific port. -// Vanilla Kubernetes exposes the API server via kubernetes.default.svc on port 443 (targetPort 6443). -// OpenShift exposes it directly on port 6443. -// No To restriction is set because the API server is typically host-networked or behind a -// ClusterIP service that does not match a pod/namespace selector. +// APIServerEgressRule allows egress to the API server on the platform-specific port (443 on +// Kubernetes, 6443 on OpenShift). No To restriction — API server is behind a ClusterIP service. func APIServerEgressRule(p PlatformParams) networkingv1.NetworkPolicyEgressRule { tcp := corev1.ProtocolTCP apiPort := intstr.FromInt32(p.APIServerPort) @@ -143,14 +137,13 @@ func APIServerEgressRule(p PlatformParams) networkingv1.NetworkPolicyEgressRule // InternetEgressRule allows egress on TCP 80 and 443 to any destination. func InternetEgressRule() networkingv1.NetworkPolicyEgressRule { - tcpHTTP := corev1.ProtocolTCP - tcpHTTPS := corev1.ProtocolTCP + tcp := corev1.ProtocolTCP httpPort := intstr.FromInt32(80) httpsPort := intstr.FromInt32(443) return networkingv1.NetworkPolicyEgressRule{ Ports: []networkingv1.NetworkPolicyPort{ - {Protocol: &tcpHTTP, Port: &httpPort}, - {Protocol: &tcpHTTPS, Port: &httpsPort}, + {Protocol: &tcp, Port: &httpPort}, + {Protocol: &tcp, Port: &httpsPort}, }, } } diff --git a/pkg/reconciler/common/networkpolicy/platform.go b/pkg/reconciler/common/networkpolicy/platform.go index b5c832de43..7dd5cf484c 100644 --- a/pkg/reconciler/common/networkpolicy/platform.go +++ b/pkg/reconciler/common/networkpolicy/platform.go @@ -22,15 +22,10 @@ type PlatformParams struct { DNSResolverNamespace string DNSResolverPodLabel map[string]string PrometheusNamespaceLabel map[string]string - // DNSPort is the port the platform's DNS resolver pods listen on. - // Vanilla Kubernetes CoreDNS pods listen on 53. - // OpenShift DNS pods listen on 5353 (host-networked daemonset); OVN-Kubernetes - // enforces NetworkPolicy after DNAT, so the policy must match the pod port (5353), - // not the dns-default service port (53). + // DNSPort is the DNS resolver pod port. Kubernetes CoreDNS uses 53; OpenShift DNS + // uses 5353 (OVN-K8s enforces NetworkPolicy after DNAT, so pod port applies). DNSPort int32 - // APIServerPort is the port the Kubernetes API server service exposes to pods. - // Vanilla Kubernetes exposes the api-server via the kubernetes.default.svc service on - // port 443 (targetPort 6443). OpenShift exposes it on port 6443 directly. + // APIServerPort is the kubernetes.default.svc port: 443 on Kubernetes, 6443 on OpenShift. APIServerPort int32 } diff --git a/pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go b/pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go index 1b6cf41379..ca7fcb78c9 100644 --- a/pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go +++ b/pkg/reconciler/kubernetes/tektontrigger/networkpolicies.go @@ -60,8 +60,7 @@ func triggersDefaultPolicies(params networkpolicy.PlatformParams) []networkingv1 }, PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress, networkingv1.PolicyTypeEgress}, Ingress: []networkingv1.NetworkPolicyIngressRule{ - // cidr="" → allow from any source; operator defaults to permissive. - // Users can restrict to a specific control-plane CIDR via spec.networkPolicy.policies. + // cidr="" → permissive; restrict via spec.networkPolicy.policies if needed. networkpolicy.WebhookIngressRule("", webhookPort), networkpolicy.PrometheusIngressRule(params, metricsPort), }, @@ -93,8 +92,7 @@ func triggersDefaultPolicies(params networkpolicy.PlatformParams) []networkingv1 Egress: []networkingv1.NetworkPolicyEgressRule{ networkpolicy.DNSEgressRule(params), networkpolicy.APIServerEgressRule(params), - // Core interceptors may call external APIs (e.g. GitHub) to fetch files, - // verify ownership, or perform other outbound operations. + // Allow egress to external APIs (e.g. GitHub) for file fetching and validation. networkpolicy.InternetEgressRule(), }, }, @@ -102,24 +100,12 @@ func triggersDefaultPolicies(params networkpolicy.PlatformParams) []networkingv1 } } -// defaultDenyPolicy returns the default-deny NetworkPolicy for the Tekton namespace. +// defaultDenyPolicy returns the scoped default-deny for Triggers pods. // -// Naming: the policy is intentionally named "tekton-default-deny" (not -// "tekton-triggers-default-deny"). The long-term design is for a single -// namespace-wide deny to be owned by one component (TektonPipeline), so all -// components converge on the same name. Do NOT rename this to a component-specific -// name — doing so would leave orphaned per-component deny policies once the -// namespace-wide policy takes over, and would break the migration path. -// -// Temporary placement: this lives here because TektonTrigger is the first component -// to implement NetworkPolicy support. TektonConfig cannot own it (no InstallerSetClient), -// so the intended long-term owner is TektonPipeline, which is the foundational component -// that all others depend on and already has an InstallerSetClient. -// -// Migration path: once all components (Pipeline, Chains, Results, Dashboard…) implement -// NetworkPolicy support, this function should move to the TektonPipeline reconciler, -// the pod selector should be widened to an empty metav1.LabelSelector{} (namespace-wide -// deny), and this copy removed. +// Name is "tekton-default-deny" (not component-specific) because the long-term +// owner is TektonPipeline, which will replace this with a namespace-wide deny +// (empty podSelector) once all components implement NetworkPolicy support. +// Do NOT rename — orphaned policies would result on migration. func defaultDenyPolicy() networkingv1.NetworkPolicy { return networkpolicy.DefaultDenyPolicy( "tekton-default-deny", diff --git a/test/e2e/common/03_tektontrigger_networkpolicy_test.go b/test/e2e/common/03_tektontrigger_networkpolicy_test.go new file mode 100644 index 0000000000..fa45470742 --- /dev/null +++ b/test/e2e/common/03_tektontrigger_networkpolicy_test.go @@ -0,0 +1,192 @@ +//go:build e2e +// +build e2e + +/* +Copyright 2026 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 + + 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 common + +import ( + "bytes" + "context" + "fmt" + "os/exec" + "path/filepath" + "runtime" + "testing" + + "github.com/tektoncd/operator/test/client" + "github.com/tektoncd/operator/test/resources" + "github.com/tektoncd/operator/test/utils" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + npTestNamespace = "tekton-np-e2e" + npEventListenerName = "np-test-listener" +) + +// TestTektonTriggerNetworkPolicy verifies NetworkPolicies are created by default, +// that Triggers resources work correctly under those policies (EventListener +// receives events and creates PipelineRuns), and that toggling +// spec.networkPolicy.disabled correctly adds and removes the policies. +func TestTektonTriggerNetworkPolicy(t *testing.T) { + crNames := utils.GetResourceNames() + clients := client.Setup(t, crNames.TargetNamespace) + + utils.CleanupOnInterrupt(func() { utils.TearDownPipeline(clients, crNames.TektonPipeline) }) + utils.CleanupOnInterrupt(func() { utils.TearDownTrigger(clients, crNames.TektonTrigger) }) + utils.CleanupOnInterrupt(func() { utils.TearDownNamespace(clients, npTestNamespace) }) + utils.CleanupOnInterrupt(func() { deleteNPTestClusterRoleBinding(t) }) + defer utils.TearDownNamespace(clients, npTestNamespace) + defer deleteNPTestClusterRoleBinding(t) + defer utils.TearDownPipeline(clients, crNames.TektonPipeline) + defer utils.TearDownTrigger(clients, crNames.TektonTrigger) + + resources.EnsureNoTektonConfigInstance(t, clients, crNames) + + if _, err := resources.EnsureTektonPipelineExists(clients.TektonPipeline(), crNames); err != nil { + t.Fatalf("TektonPipeline %q failed to create: %v", crNames.TektonPipeline, err) + } + resources.AssertTektonPipelineCRReadyStatus(t, clients, crNames) + + if _, err := resources.EnsureTektonTriggerExists(clients.TektonTrigger(), crNames); err != nil { + t.Fatalf("TektonTrigger %q failed to create: %v", crNames.TektonTrigger, err) + } + resources.AssertTektonTriggerCRReadyStatus(t, clients, crNames) + + expectedPolicies := []string{ + "tekton-default-deny", + "triggers-controller", + "triggers-webhook", + "triggers-core-interceptors", + } + + t.Run("default-policies-created", func(t *testing.T) { + resources.AssertNetworkPoliciesExist(t, clients, crNames.TargetNamespace, expectedPolicies) + }) + + t.Run("triggers-functional-with-networkpolicies", func(t *testing.T) { + if err := resources.CreateNamespace(clients.KubeClient, npTestNamespace); err != nil { + t.Fatalf("failed to create test namespace %q: %v", npTestNamespace, err) + } + if err := applyTriggersTestdata(t, npTestNamespace); err != nil { + t.Fatalf("failed to apply Triggers testdata: %v", err) + } + + // EventListener Ready proves controller reached the API server. + resources.AssertEventListenerReady(t, clients, npTestNamespace, npEventListenerName) + + // action=push matches the CEL filter; exercises interceptors ingress + API server egress. + t.Run("cel-interceptor-matching-event-creates-pipelinerun", func(t *testing.T) { + if err := sendEventToListener(t, npTestNamespace, npEventListenerName, `{"action":"push"}`); err != nil { + t.Fatalf("matching event failed: %v", err) + } + resources.AssertPipelineRunCreated(t, clients, npTestNamespace) + }) + + // action=open does not match; interceptor blocks it, no new PipelineRun. + t.Run("cel-interceptor-non-matching-event-blocked", func(t *testing.T) { + prsBefore, err := clients.TektonClient.PipelineRuns(npTestNamespace).List(context.TODO(), metav1.ListOptions{}) + if err != nil { + t.Fatalf("failed to list PipelineRuns: %v", err) + } + _ = sendEventToListener(t, npTestNamespace, npEventListenerName, `{"action":"open"}`) + resources.AssertPipelineRunCountUnchanged(t, clients, npTestNamespace, len(prsBefore.Items)) + }) + }) + + t.Run("disable-removes-policies", func(t *testing.T) { + tt, err := clients.TektonTrigger().Get(context.TODO(), crNames.TektonTrigger, metav1.GetOptions{}) + if err != nil { + t.Fatalf("failed to get TektonTrigger: %v", err) + } + tt.Spec.NetworkPolicy.Disabled = true + if _, err := clients.TektonTrigger().Update(context.TODO(), tt, metav1.UpdateOptions{}); err != nil { + t.Fatalf("failed to disable NetworkPolicy on TektonTrigger: %v", err) + } + resources.AssertTektonTriggerCRReadyStatus(t, clients, crNames) + resources.AssertNetworkPoliciesAbsent(t, clients, crNames.TargetNamespace, expectedPolicies) + }) + + t.Run("reenable-restores-policies", func(t *testing.T) { + tt, err := clients.TektonTrigger().Get(context.TODO(), crNames.TektonTrigger, metav1.GetOptions{}) + if err != nil { + t.Fatalf("failed to get TektonTrigger: %v", err) + } + tt.Spec.NetworkPolicy.Disabled = false + if _, err := clients.TektonTrigger().Update(context.TODO(), tt, metav1.UpdateOptions{}); err != nil { + t.Fatalf("failed to re-enable NetworkPolicy on TektonTrigger: %v", err) + } + resources.AssertTektonTriggerCRReadyStatus(t, clients, crNames) + resources.AssertNetworkPoliciesExist(t, clients, crNames.TargetNamespace, expectedPolicies) + }) +} + +// deleteNPTestClusterRoleBinding removes the cluster-scoped binding created by rbac.yaml. +func deleteNPTestClusterRoleBinding(t *testing.T) { + t.Helper() + cmd := exec.Command("kubectl", "delete", "clusterrolebinding", "np-test-el-clusterrolebinding", "--ignore-not-found") + _ = cmd.Run() +} + +// applyTriggersTestdata applies testdata/triggers/ YAML into namespace. +func applyTriggersTestdata(t *testing.T, namespace string) error { + t.Helper() + _, file, _, ok := runtime.Caller(0) + if !ok { + return fmt.Errorf("failed to get caller information") + } + testdataDir := filepath.Join(filepath.Dir(file), "testdata", "triggers") + + var stderr bytes.Buffer + cmd := exec.Command("kubectl", "apply", "-f", testdataDir, "-n", namespace) + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("kubectl apply failed: %v\n%s", err, stderr.String()) + } + return nil +} + +// sendEventToListener POSTs payload to the EventListener from a temporary in-cluster pod. +func sendEventToListener(t *testing.T, namespace, listenerName, payload string) error { + t.Helper() + svcURL := fmt.Sprintf("http://el-%s.%s.svc.cluster.local:8080", listenerName, namespace) + + var stderr bytes.Buffer + cmd := exec.Command( + "kubectl", "run", "np-e2e-curl", "--restart=Never", "--rm", "-i", + "--image=curlimages/curl:latest", + "-n", namespace, + "--", + "curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", + "-X", "POST", svcURL, + "-H", "Content-Type: application/json", + "-d", payload, + ) + cmd.Stderr = &stderr + out, err := cmd.Output() + if err != nil { + return fmt.Errorf("curl pod failed: %v\nstderr: %s", err, stderr.String()) + } + // kubectl --rm appends the pod deletion message to stdout; take only the first + // 3 bytes which are the curl %{http_code} output. + raw := string(bytes.TrimSpace(out)) + if len(raw) < 3 || (raw[:3] != "200" && raw[:3] != "202") { + return fmt.Errorf("EventListener returned unexpected HTTP status %q (want 200/202)", raw) + } + return nil +} diff --git a/test/e2e/common/testdata/triggers/eventlistener.yaml b/test/e2e/common/testdata/triggers/eventlistener.yaml new file mode 100644 index 0000000000..de3879374a --- /dev/null +++ b/test/e2e/common/testdata/triggers/eventlistener.yaml @@ -0,0 +1,16 @@ +apiVersion: triggers.tekton.dev/v1beta1 +kind: EventListener +metadata: + name: np-test-listener +spec: + serviceAccountName: np-test-el-sa + triggers: + - name: np-test-trigger + interceptors: + - ref: + name: cel + params: + - name: filter + value: "body.action == 'push'" + template: + ref: np-test-template diff --git a/test/e2e/common/testdata/triggers/pipeline.yaml b/test/e2e/common/testdata/triggers/pipeline.yaml new file mode 100644 index 0000000000..673d97072a --- /dev/null +++ b/test/e2e/common/testdata/triggers/pipeline.yaml @@ -0,0 +1,12 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: np-test-pipeline +spec: + tasks: + - name: echo + taskSpec: + steps: + - name: echo + image: alpine + script: echo "NetworkPolicy e2e test passed" diff --git a/test/e2e/common/testdata/triggers/rbac.yaml b/test/e2e/common/testdata/triggers/rbac.yaml new file mode 100644 index 0000000000..e604117c41 --- /dev/null +++ b/test/e2e/common/testdata/triggers/rbac.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: np-test-el-sa +--- +# Binds the EventListener SA to the namespaced Triggers ClusterRole so it can +# read TriggerTemplates and create PipelineRuns in the test namespace. +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: np-test-el-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-triggers-eventlistener-roles +subjects: +- kind: ServiceAccount + name: np-test-el-sa +--- +# Binds the EventListener SA to the cluster-scoped Triggers ClusterRole so it +# can read ClusterInterceptors (e.g. cel). Named uniquely to avoid conflicts. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: np-test-el-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-triggers-eventlistener-clusterroles +subjects: +- kind: ServiceAccount + name: np-test-el-sa + namespace: tekton-np-e2e diff --git a/test/e2e/common/testdata/triggers/triggertemplate.yaml b/test/e2e/common/testdata/triggers/triggertemplate.yaml new file mode 100644 index 0000000000..6cb8834fd6 --- /dev/null +++ b/test/e2e/common/testdata/triggers/triggertemplate.yaml @@ -0,0 +1,13 @@ +apiVersion: triggers.tekton.dev/v1beta1 +kind: TriggerTemplate +metadata: + name: np-test-template +spec: + resourcetemplates: + - apiVersion: tekton.dev/v1 + kind: PipelineRun + metadata: + generateName: np-test-run- + spec: + pipelineRef: + name: np-test-pipeline diff --git a/test/resources/networkpolicies.go b/test/resources/networkpolicies.go new file mode 100644 index 0000000000..1c14230b1b --- /dev/null +++ b/test/resources/networkpolicies.go @@ -0,0 +1,123 @@ +/* +Copyright 2026 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 + + 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 resources + +import ( + "context" + "fmt" + "testing" + + "github.com/tektoncd/operator/test/utils" + apierrs "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +// AssertNetworkPoliciesExist polls until all named NetworkPolicies exist in namespace. +func AssertNetworkPoliciesExist(t *testing.T, clients *utils.Clients, namespace string, names []string) { + t.Helper() + for _, name := range names { + np := name + if err := wait.PollUntilContextTimeout(context.TODO(), utils.Interval, utils.Timeout, true, func(ctx context.Context) (bool, error) { + _, err := clients.KubeClient.NetworkingV1().NetworkPolicies(namespace).Get(ctx, np, metav1.GetOptions{}) + if apierrs.IsNotFound(err) { + return false, nil + } + return err == nil, err + }); err != nil { + t.Errorf("NetworkPolicy %q not found in namespace %q: %v", np, namespace, err) + } + } +} + +// AssertNetworkPoliciesAbsent polls until all named NetworkPolicies are gone from namespace. +func AssertNetworkPoliciesAbsent(t *testing.T, clients *utils.Clients, namespace string, names []string) { + t.Helper() + for _, name := range names { + np := name + if err := wait.PollUntilContextTimeout(context.TODO(), utils.Interval, utils.Timeout, true, func(ctx context.Context) (bool, error) { + _, err := clients.KubeClient.NetworkingV1().NetworkPolicies(namespace).Get(ctx, np, metav1.GetOptions{}) + if apierrs.IsNotFound(err) { + return true, nil + } + if err != nil { + return false, err + } + return false, nil + }); err != nil { + t.Errorf("NetworkPolicy %q still present in namespace %q after timeout: %v", np, namespace, err) + } + } +} + +// AssertEventListenerReady polls until the EventListener deployment is available. +func AssertEventListenerReady(t *testing.T, clients *utils.Clients, namespace, name string) { + t.Helper() + deploymentName := fmt.Sprintf("el-%s", name) + if err := wait.PollUntilContextTimeout(context.TODO(), utils.Interval, utils.Timeout, true, func(ctx context.Context) (bool, error) { + d, err := clients.KubeClient.AppsV1().Deployments(namespace).Get(ctx, deploymentName, metav1.GetOptions{}) + if apierrs.IsNotFound(err) { + return false, nil + } + if err != nil { + return false, err + } + return d.Status.ReadyReplicas >= 1, nil + }); err != nil { + t.Fatalf("EventListener deployment %q in namespace %q not ready: %v", deploymentName, namespace, err) + } +} + +// AssertPipelineRunCreated polls until at least one PipelineRun exists in namespace. +func AssertPipelineRunCreated(t *testing.T, clients *utils.Clients, namespace string) { + t.Helper() + if err := wait.PollUntilContextTimeout(context.TODO(), utils.Interval, utils.Timeout, true, func(ctx context.Context) (bool, error) { + prs, err := clients.TektonClient.PipelineRuns(namespace).List(ctx, metav1.ListOptions{}) + if err != nil { + return false, err + } + return len(prs.Items) > 0, nil + }); err != nil { + t.Fatalf("no PipelineRun created in namespace %q: %v", namespace, err) + } +} + +// AssertPipelineRunCountUnchanged waits briefly and then asserts the PipelineRun +// count in namespace has not grown beyond countBefore. Used to verify that a +// non-matching interceptor event did not trigger a PipelineRun. +func AssertPipelineRunCountUnchanged(t *testing.T, clients *utils.Clients, namespace string, countBefore int) { + t.Helper() + // Wait a short period to give the system time to process the event if it + // were going to create a PipelineRun (uses a fraction of the normal timeout). + shortTimeout := utils.Timeout / 10 + _ = wait.PollUntilContextTimeout(context.TODO(), utils.Interval, shortTimeout, true, func(ctx context.Context) (bool, error) { + prs, err := clients.TektonClient.PipelineRuns(namespace).List(ctx, metav1.ListOptions{}) + if err != nil { + return false, err + } + // Keep polling until we see a change (so we fail fast) or time out. + return len(prs.Items) > countBefore, nil + }) + + prs, err := clients.TektonClient.PipelineRuns(namespace).List(context.TODO(), metav1.ListOptions{}) + if err != nil { + t.Fatalf("failed to list PipelineRuns: %v", err) + } + if got := len(prs.Items); got > countBefore { + t.Errorf("expected no new PipelineRun after non-matching event, got %d (was %d)", got, countBefore) + } +}