mirror of
https://github.com/cozystack/cozystack.git
synced 2026-03-04 14:08:52 +00:00
Compare commits
14 Commits
refactor-e
...
v0.37.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9506c58926 | ||
|
|
ffcc55c588 | ||
|
|
cbf67cd30e | ||
|
|
1b46ff3f6b | ||
|
|
674b3963a7 | ||
|
|
f71f914fe6 | ||
|
|
a09ed799e9 | ||
|
|
8e35d6ae4e | ||
|
|
2f8c6b72fe | ||
|
|
5a679e12ad | ||
|
|
0176ba5e95 | ||
|
|
b474c07c80 | ||
|
|
5dbdd0eafa | ||
|
|
21715c02bc |
1
Makefile
1
Makefile
@@ -15,6 +15,7 @@ build: build-deps
|
||||
make -C packages/extra/monitoring image
|
||||
make -C packages/system/cozystack-api image
|
||||
make -C packages/system/cozystack-controller image
|
||||
make -C packages/system/lineage-controller-webhook image
|
||||
make -C packages/system/cilium image
|
||||
make -C packages/system/kubeovn image
|
||||
make -C packages/system/kubeovn-webhook image
|
||||
|
||||
@@ -39,7 +39,6 @@ import (
|
||||
cozystackiov1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
"github.com/cozystack/cozystack/internal/controller"
|
||||
"github.com/cozystack/cozystack/internal/controller/dashboard"
|
||||
lcw "github.com/cozystack/cozystack/internal/lineagecontrollerwebhook"
|
||||
"github.com/cozystack/cozystack/internal/telemetry"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2"
|
||||
@@ -222,20 +221,6 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// special one that's both a webhook and a reconciler
|
||||
lineageControllerWebhook := &lcw.LineageControllerWebhook{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsController(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup controller", "controller", "LineageController")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsWebhook(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup webhook", "webhook", "LineageWebhook")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// +kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
|
||||
179
cmd/lineage-controller-webhook/main.go
Normal file
179
cmd/lineage-controller-webhook/main.go
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
Copyright 2025.
|
||||
|
||||
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 main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
||||
// to ensure that exec-entrypoint and run can make use of them.
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
|
||||
cozystackiov1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
lcw "github.com/cozystack/cozystack/internal/lineagecontrollerwebhook"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
var (
|
||||
scheme = runtime.NewScheme()
|
||||
setupLog = ctrl.Log.WithName("setup")
|
||||
)
|
||||
|
||||
func init() {
|
||||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
|
||||
utilruntime.Must(cozystackiov1alpha1.AddToScheme(scheme))
|
||||
// +kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
func main() {
|
||||
var metricsAddr string
|
||||
var enableLeaderElection bool
|
||||
var probeAddr string
|
||||
var secureMetrics bool
|
||||
var enableHTTP2 bool
|
||||
var tlsOpts []func(*tls.Config)
|
||||
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
|
||||
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
|
||||
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
|
||||
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
|
||||
"Enable leader election for controller manager. "+
|
||||
"Enabling this will ensure there is only one active controller manager.")
|
||||
flag.BoolVar(&secureMetrics, "metrics-secure", true,
|
||||
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
|
||||
flag.BoolVar(&enableHTTP2, "enable-http2", false,
|
||||
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
|
||||
opts := zap.Options{
|
||||
Development: false,
|
||||
}
|
||||
opts.BindFlags(flag.CommandLine)
|
||||
flag.Parse()
|
||||
|
||||
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
|
||||
|
||||
// if the enable-http2 flag is false (the default), http/2 should be disabled
|
||||
// due to its vulnerabilities. More specifically, disabling http/2 will
|
||||
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
|
||||
// Rapid Reset CVEs. For more information see:
|
||||
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
|
||||
// - https://github.com/advisories/GHSA-4374-p667-p6c8
|
||||
disableHTTP2 := func(c *tls.Config) {
|
||||
setupLog.Info("disabling http/2")
|
||||
c.NextProtos = []string{"http/1.1"}
|
||||
}
|
||||
|
||||
if !enableHTTP2 {
|
||||
tlsOpts = append(tlsOpts, disableHTTP2)
|
||||
}
|
||||
|
||||
webhookServer := webhook.NewServer(webhook.Options{
|
||||
TLSOpts: tlsOpts,
|
||||
})
|
||||
|
||||
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
|
||||
// More info:
|
||||
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/server
|
||||
// - https://book.kubebuilder.io/reference/metrics.html
|
||||
metricsServerOptions := metricsserver.Options{
|
||||
BindAddress: metricsAddr,
|
||||
SecureServing: secureMetrics,
|
||||
TLSOpts: tlsOpts,
|
||||
}
|
||||
|
||||
if secureMetrics {
|
||||
// FilterProvider is used to protect the metrics endpoint with authn/authz.
|
||||
// These configurations ensure that only authorized users and service accounts
|
||||
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
|
||||
// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/filters#WithAuthenticationAndAuthorization
|
||||
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
|
||||
|
||||
// TODO(user): If CertDir, CertName, and KeyName are not specified, controller-runtime will automatically
|
||||
// generate self-signed certificates for the metrics server. While convenient for development and testing,
|
||||
// this setup is not recommended for production.
|
||||
}
|
||||
|
||||
// Configure rate limiting for the Kubernetes client
|
||||
config := ctrl.GetConfigOrDie()
|
||||
config.QPS = 50.0 // Increased from default 5.0
|
||||
config.Burst = 100 // Increased from default 10
|
||||
|
||||
mgr, err := ctrl.NewManager(config, ctrl.Options{
|
||||
Scheme: scheme,
|
||||
Metrics: metricsServerOptions,
|
||||
WebhookServer: webhookServer,
|
||||
HealthProbeBindAddress: probeAddr,
|
||||
LeaderElection: enableLeaderElection,
|
||||
LeaderElectionID: "8796f12d.cozystack.io",
|
||||
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
|
||||
// when the Manager ends. This requires the binary to immediately end when the
|
||||
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
|
||||
// speeds up voluntary leader transitions as the new leader don't have to wait
|
||||
// LeaseDuration time first.
|
||||
//
|
||||
// In the default scaffold provided, the program ends immediately after
|
||||
// the manager stops, so would be fine to enable this option. However,
|
||||
// if you are doing or is intended to do any operation such as perform cleanups
|
||||
// after the manager stops then its usage might be unsafe.
|
||||
// LeaderElectionReleaseOnCancel: true,
|
||||
})
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to start manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lineageControllerWebhook := &lcw.LineageControllerWebhook{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsController(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup controller", "controller", "LineageController")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsWebhook(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup webhook", "webhook", "LineageWebhook")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// +kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up health check")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up ready check")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
setupLog.Info("starting manager")
|
||||
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||
setupLog.Error(err, "problem running manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
3
docs/changelogs/unreleased.md
Normal file
3
docs/changelogs/unreleased.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Changes after v0.37.0
|
||||
|
||||
* [lineage] Break webhook out into a separate daemonset. Reduce unnecessary webhook calls by marking handled resources and excluding them from consideration by the webhook's object selector (@lllamnyp in #1515).
|
||||
@@ -64,19 +64,19 @@ spec:
|
||||
EOF
|
||||
# Wait for the tenant-test namespace to be active
|
||||
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
|
||||
|
||||
|
||||
# Wait for the Kamaji control plane to be created (retry for up to 10 seconds)
|
||||
timeout 10 sh -ec 'until kubectl get kamajicontrolplane -n tenant-test kubernetes-'"${test_name}"'; do sleep 1; done'
|
||||
|
||||
# Wait for the tenant control plane to be fully created (timeout after 4 minutes)
|
||||
kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-${test_name} --timeout=4m
|
||||
|
||||
|
||||
# Wait for Kubernetes resources to be ready (timeout after 2 minutes)
|
||||
kubectl wait tcp -n tenant-test kubernetes-${test_name} --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
|
||||
|
||||
|
||||
# Wait for all required deployments to be available (timeout after 4 minutes)
|
||||
kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-${test_name} kubernetes-${test_name}-cluster-autoscaler kubernetes-${test_name}-kccm kubernetes-${test_name}-kcsi-controller
|
||||
|
||||
|
||||
# Wait for the machine deployment to scale to 2 replicas (timeout after 1 minute)
|
||||
kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2
|
||||
# Get the admin kubeconfig and save it to a file
|
||||
@@ -105,9 +105,11 @@ EOF
|
||||
versions=$(kubectl --kubeconfig tenantkubeconfig get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}')
|
||||
node_ok=true
|
||||
|
||||
if [[ "$k8s_version" == v1.32* ]]; then
|
||||
echo "⚠️ TODO: Temporary stub — allowing nodes with v1.33 while k8s_version is v1.32"
|
||||
fi
|
||||
case "$k8s_version" in
|
||||
v1.32*)
|
||||
echo "⚠️ TODO: Temporary stub — allowing nodes with v1.33 while k8s_version is v1.32"
|
||||
;;
|
||||
esac
|
||||
|
||||
for v in $versions; do
|
||||
case "$k8s_version" in
|
||||
@@ -134,7 +136,7 @@ EOF
|
||||
esac
|
||||
done
|
||||
|
||||
if ! $node_ok; then
|
||||
if [ "$node_ok" != true ]; then
|
||||
echo "Kubelet versions did not match expected ${k8s_version}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -26,6 +26,13 @@ var (
|
||||
AncestryAmbiguous = fmt.Errorf("object ancestry is ambiguous")
|
||||
)
|
||||
|
||||
const (
|
||||
ManagedObjectKey = "internal.cozystack.io/managed-by-cozystack"
|
||||
ManagerGroupKey = "apps.cozystack.io/application.group"
|
||||
ManagerKindKey = "apps.cozystack.io/application.kind"
|
||||
ManagerNameKey = "apps.cozystack.io/application.name"
|
||||
)
|
||||
|
||||
// getResourceSelectors returns the appropriate CozystackResourceDefinitionResources for a given GroupKind
|
||||
func (h *LineageControllerWebhook) getResourceSelectors(gk schema.GroupKind, crd *cozyv1alpha1.CozystackResourceDefinition) *cozyv1alpha1.CozystackResourceDefinitionResources {
|
||||
switch {
|
||||
@@ -91,7 +98,7 @@ func (h *LineageControllerWebhook) Handle(ctx context.Context, req admission.Req
|
||||
labels, err := h.computeLabels(ctx, obj)
|
||||
for {
|
||||
if err != nil && errors.Is(err, NoAncestors) {
|
||||
return admission.Allowed("object not managed by app")
|
||||
break // not a problem, mark object as unmanaged
|
||||
}
|
||||
if err != nil && errors.Is(err, AncestryAmbiguous) {
|
||||
warn = append(warn, "object ancestry ambiguous, using first ancestor found")
|
||||
@@ -119,7 +126,7 @@ func (h *LineageControllerWebhook) Handle(ctx context.Context, req admission.Req
|
||||
func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstructured.Unstructured) (map[string]string, error) {
|
||||
owners := lineage.WalkOwnershipGraph(ctx, h.dynClient, h.mapper, h, o)
|
||||
if len(owners) == 0 {
|
||||
return nil, NoAncestors
|
||||
return map[string]string{ManagedObjectKey: "false"}, NoAncestors
|
||||
}
|
||||
obj, err := owners[0].GetUnstructured(ctx, h.dynClient, h.mapper)
|
||||
if err != nil {
|
||||
@@ -135,7 +142,8 @@ func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstruc
|
||||
}
|
||||
labels := map[string]string{
|
||||
// truncate apigroup to first 63 chars
|
||||
"apps.cozystack.io/application.group": func(s string) string {
|
||||
ManagedObjectKey: "true",
|
||||
ManagerGroupKey: func(s string) string {
|
||||
if len(s) < 63 {
|
||||
return s
|
||||
}
|
||||
@@ -145,8 +153,8 @@ func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstruc
|
||||
}
|
||||
return s
|
||||
}(gv.Group),
|
||||
"apps.cozystack.io/application.kind": obj.GetKind(),
|
||||
"apps.cozystack.io/application.name": obj.GetName(),
|
||||
ManagerKindKey: obj.GetKind(),
|
||||
ManagerNameKey: obj.GetName(),
|
||||
}
|
||||
templateLabels := map[string]string{
|
||||
"kind": strings.ToLower(obj.GetKind()),
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:50ac1581e3100bd6c477a71161cb455a341ffaf9e5e2f6086802e4e25271e8af
|
||||
ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:e0a07082bb6fc6aeaae2315f335386f1705a646c72f9e0af512aebbca5cb2b15
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:c8b08084a86251cdd18e237de89b695bca0e4f7eb1f1f6ddc2b903b4d74ea5ff
|
||||
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:01667d56186c33c0de75be6da82d0f1164a4592bfec86639cf571457b212075e
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
cozystack:
|
||||
image: ghcr.io/cozystack/cozystack/installer:v0.37.0@sha256:256c5a0f0ae2fc3ad6865b9fda74c42945b38a5384240fa29554617185b60556
|
||||
image: ghcr.io/cozystack/cozystack/installer:v0.37.2@sha256:c7c2ed6f16c6db1797650b7a53b65c9db8d4f10cf0917f5ad4389b054ea25cba
|
||||
|
||||
@@ -68,6 +68,12 @@ releases:
|
||||
disableTelemetry: true
|
||||
{{- end }}
|
||||
|
||||
- name: lineage-controller-webhook
|
||||
releaseName: lineage-controller-webhook
|
||||
chart: cozy-lineage-controller-webhook
|
||||
namespace: cozy-system
|
||||
dependsOn: [cozystack-controller,cilium,cert-manager]
|
||||
|
||||
- name: cert-manager
|
||||
releaseName: cert-manager
|
||||
chart: cozy-cert-manager
|
||||
|
||||
@@ -36,6 +36,12 @@ releases:
|
||||
disableTelemetry: true
|
||||
{{- end }}
|
||||
|
||||
- name: lineage-controller-webhook
|
||||
releaseName: lineage-controller-webhook
|
||||
chart: cozy-lineage-controller-webhook
|
||||
namespace: cozy-system
|
||||
dependsOn: [cozystack-controller,cert-manager]
|
||||
|
||||
- name: cert-manager
|
||||
releaseName: cert-manager
|
||||
chart: cozy-cert-manager
|
||||
|
||||
@@ -105,6 +105,12 @@ releases:
|
||||
disableTelemetry: true
|
||||
{{- end }}
|
||||
|
||||
- name: lineage-controller-webhook
|
||||
releaseName: lineage-controller-webhook
|
||||
chart: cozy-lineage-controller-webhook
|
||||
namespace: cozy-system
|
||||
dependsOn: [cozystack-controller,cilium,kubeovn,cert-manager]
|
||||
|
||||
- name: cozystack-resource-definition-crd
|
||||
releaseName: cozystack-resource-definition-crd
|
||||
chart: cozystack-resource-definition-crd
|
||||
|
||||
@@ -52,6 +52,12 @@ releases:
|
||||
disableTelemetry: true
|
||||
{{- end }}
|
||||
|
||||
- name: lineage-controller-webhook
|
||||
releaseName: lineage-controller-webhook
|
||||
chart: cozy-lineage-controller-webhook
|
||||
namespace: cozy-system
|
||||
dependsOn: [cozystack-controller,cert-manager]
|
||||
|
||||
- name: cozystack-resource-definition-crd
|
||||
releaseName: cozystack-resource-definition-crd
|
||||
chart: cozystack-resource-definition-crd
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
e2e:
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.37.0@sha256:10afd0a6c39248ec41d0e59ff1bc6c29bd0075b7cc9a512b01cf603ef39c33ea
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.37.2@sha256:2071441e9dbca15bd8fe4029d2e41be8fea6066f127969bd74b41a1c3d4ca3ef
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/matchbox:v0.37.0@sha256:5cca5f56b755285aefa11b1052fe55e1aa83b25bae34aef80cdb77ff63091044
|
||||
ghcr.io/cozystack/cozystack/matchbox:v0.37.2@sha256:dcd27eaff34a2b2425d34137d088d1b8d55e58b192ecb0d2dabde7e6a88d3fbf
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.0@sha256:f166f09cdc9cdbb758209883819ab8261a3793bc1d7a6b6685efd5a2b2930847
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.2@sha256:1a739164b518dc395375ce9057bb582b5c539555f0ee2f2df7f931b23a1c4a48
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:7348bec610f08bd902c88c9a9f28fdd644727e2728a1e4103f88f0c99febd5e7
|
||||
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:2ac8139c13d5a9816e5ea7c78da30777f7119ea0cd4f18f44048fa121f977902
|
||||
|
||||
@@ -6,6 +6,9 @@ rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces", "secrets"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["rolebindings"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["create", "update", "patch", "delete"]
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
cozystackAPI:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v0.37.0@sha256:19d89e8afb90ce38ab7e42ecedfc28402f7c0b56f30957db957c5415132ff6ca
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v0.37.2@sha256:1ce7d2658a4b705ef0a1c09b53d8708c78874775722558ae05aa77ed76cbe7ec
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: cozystack-controller-webhook-selfsigned
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
selfSigned: {}
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: cozystack-controller-webhook-ca
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
secretName: cozystack-controller-webhook-ca
|
||||
duration: 43800h # 5 years
|
||||
commonName: cozystack-controller-webhook-ca
|
||||
issuerRef:
|
||||
name: cozystack-controller-webhook-selfsigned
|
||||
isCA: true
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: cozystack-controller-webhook-ca
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
ca:
|
||||
secretName: cozystack-controller-webhook-ca
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: cozystack-controller-webhook
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
secretName: cozystack-controller-webhook-cert
|
||||
duration: 8760h
|
||||
renewBefore: 720h
|
||||
issuerRef:
|
||||
name: cozystack-controller-webhook-ca
|
||||
commonName: cozystack-controller
|
||||
dnsNames:
|
||||
- cozystack-controller
|
||||
- cozystack-controller.{{ .Release.Namespace }}.svc
|
||||
@@ -28,15 +28,3 @@ spec:
|
||||
{{- if .Values.cozystackController.disableTelemetry }}
|
||||
- --disable-telemetry
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: webhook
|
||||
containerPort: 9443
|
||||
volumeMounts:
|
||||
- name: webhook-certs
|
||||
mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: webhook-certs
|
||||
secret:
|
||||
secretName: cozystack-controller-webhook-cert
|
||||
defaultMode: 0400
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cozystackController:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.37.0@sha256:845b8e68cbc277c2303080bcd55597e4334610d396dad258ad56fd906530acc3
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.37.2@sha256:26adefda0a0c23e6e2edd9fec681ec313b75436ec5ccfede88d772298fce3aa1
|
||||
debug: false
|
||||
disableTelemetry: false
|
||||
cozystackVersion: "v0.37.0"
|
||||
cozystackVersion: "v0.37.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{{- $brandingConfig:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }}
|
||||
|
||||
{{- $tenantText := "v0.37.0" }}
|
||||
{{- $tenantText := "v0.37.2" }}
|
||||
{{- $footerText := "Cozystack" }}
|
||||
{{- $titleText := "Cozystack Dashboard" }}
|
||||
{{- $logoText := "false" }}
|
||||
|
||||
@@ -55,6 +55,8 @@ spec:
|
||||
- --http-address=0.0.0.0:8000
|
||||
- --redirect-url=https://dashboard.{{ $host }}/oauth2/callback
|
||||
- --oidc-issuer-url=https://keycloak.{{ $host }}/realms/cozy
|
||||
- --backend-logout-url=https://keycloak.{{ $host }}/realms/cozy/protocol/openid-connect/logout?id_token_hint={id_token}
|
||||
- --whitelist-domain=keycloak.{{ $host }}
|
||||
- --email-domain=*
|
||||
- --pass-access-token=true
|
||||
- --pass-authorization-header=true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
openapiUI:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v0.37.0@sha256:13f38cf56830e899eb5e3d9dc8184965dd8dba9f8cd3c5ca10df0970355842d6
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v0.37.2@sha256:ea6f5c1632ad424b31ce329c20426bd04d520aa769aa0c78b35d730605564a60
|
||||
openapiUIK8sBff:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v0.37.0@sha256:2b626dbbf87241e8621ac5b0285f402edbc2c2069ba254ca2ace2dd5c9248ac8
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v0.37.2@sha256:995bb28ee4fb0263c70267f63b20581b64666522f931333df90a58d4c327a19c
|
||||
tokenProxy:
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v0.37.0@sha256:fad27112617bb17816702571e1f39d0ac3fe5283468d25eb12f79906cdab566b
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v0.37.2@sha256:fad27112617bb17816702571e1f39d0ac3fe5283468d25eb12f79906cdab566b
|
||||
|
||||
@@ -3,7 +3,7 @@ kamaji:
|
||||
deploy: false
|
||||
image:
|
||||
pullPolicy: IfNotPresent
|
||||
tag: v0.37.0@sha256:9f4fd5045ede2909fbaf2572e4138fcbd8921071ecf8f08446257fddd0e6f655
|
||||
tag: v0.37.2@sha256:ceefafb628e0500deccb5af7a3303e0b6348ac1bbdffaa6de7fd5ec004caadc6
|
||||
repository: ghcr.io/cozystack/cozystack/kamaji
|
||||
resources:
|
||||
limits:
|
||||
@@ -13,4 +13,4 @@ kamaji:
|
||||
cpu: 100m
|
||||
memory: 100Mi
|
||||
extraArgs:
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v0.37.0@sha256:9f4fd5045ede2909fbaf2572e4138fcbd8921071ecf8f08446257fddd0e6f655
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v0.37.2@sha256:ceefafb628e0500deccb5af7a3303e0b6348ac1bbdffaa6de7fd5ec004caadc6
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v0.37.0@sha256:9950614571ea77a55925eba0839b6b12c8e5a7a30b8858031a8c6050f261af1a
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v0.37.2@sha256:781e06992871a7e6e6522ecf68b1e2806c710821f85949c9141872cb92312208
|
||||
ovnCentralName: ovn-central
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.37.0@sha256:7e63205708e607ce2cedfe2a2cafd323ca51e3ebc71244a21ff6f9016c6c87bc
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.37.2@sha256:a2e6c6619270769d56beb1166d09fdc541a7754757d567ede558e8ebdeae397a
|
||||
|
||||
@@ -64,4 +64,4 @@ global:
|
||||
images:
|
||||
kubeovn:
|
||||
repository: kubeovn
|
||||
tag: v1.14.5@sha256:af10da442a0c6dc7df47a0ef752e2eb5c247bb0b43069fdfcb2aa51511185ea2
|
||||
tag: v1.14.5@sha256:0b98310bbe8c8f49f4b45d4cb12a52daa5f3e451ea9533db8d55c5d02434b31e
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
storageClass: replicated
|
||||
csiDriver:
|
||||
image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:c8b08084a86251cdd18e237de89b695bca0e4f7eb1f1f6ddc2b903b4d74ea5ff
|
||||
image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:01667d56186c33c0de75be6da82d0f1164a4592bfec86639cf571457b212075e
|
||||
|
||||
27
packages/system/lineage-controller-webhook/.gitignore
vendored
Normal file
27
packages/system/lineage-controller-webhook/.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
bin/*
|
||||
Dockerfile.cross
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# Kubernetes Generated files - skip generated files, except for vendored files
|
||||
!vendor/**/zz_generated.*
|
||||
|
||||
# editor and IDE paraphernalia
|
||||
.idea
|
||||
.vscode
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
3
packages/system/lineage-controller-webhook/Chart.yaml
Normal file
3
packages/system/lineage-controller-webhook/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
name: cozy-lineage-controller-webhook
|
||||
version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process
|
||||
18
packages/system/lineage-controller-webhook/Makefile
Normal file
18
packages/system/lineage-controller-webhook/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
NAME=lineage-controller-webhook
|
||||
NAMESPACE=cozy-system
|
||||
|
||||
include ../../../scripts/common-envs.mk
|
||||
include ../../../scripts/package.mk
|
||||
|
||||
image: image-lineage-controller-webhook
|
||||
|
||||
image-lineage-controller-webhook:
|
||||
docker buildx build -f images/lineage-controller-webhook/Dockerfile ../../.. \
|
||||
--tag $(REGISTRY)/lineage-controller-webhook:$(call settag,$(TAG)) \
|
||||
--cache-from type=registry,ref=$(REGISTRY)/lineage-controller-webhook:latest \
|
||||
--cache-to type=inline \
|
||||
--metadata-file images/lineage-controller-webhook.json \
|
||||
$(BUILDX_ARGS)
|
||||
IMAGE="$(REGISTRY)/lineage-controller-webhook:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/lineage-controller-webhook.json -o json -r)" \
|
||||
yq -i '.lineageControllerWebhook.image = strenv(IMAGE)' values.yaml
|
||||
rm -f images/lineage-controller-webhook.json
|
||||
@@ -0,0 +1,23 @@
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go mod download
|
||||
|
||||
COPY api api/
|
||||
COPY pkg pkg/
|
||||
COPY cmd cmd/
|
||||
COPY internal internal/
|
||||
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o /lineage-controller-webhook cmd/lineage-controller-webhook/main.go
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=builder /lineage-controller-webhook /lineage-controller-webhook
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
ENTRYPOINT ["/lineage-controller-webhook"]
|
||||
@@ -0,0 +1,45 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: lineage-controller-webhook-selfsigned
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
selfSigned: {}
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: lineage-controller-webhook-ca
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
secretName: lineage-controller-webhook-ca
|
||||
duration: 43800h # 5 years
|
||||
commonName: lineage-controller-webhook-ca
|
||||
issuerRef:
|
||||
name: lineage-controller-webhook-selfsigned
|
||||
isCA: true
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: lineage-controller-webhook-ca
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
ca:
|
||||
secretName: lineage-controller-webhook-ca
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: lineage-controller-webhook
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
secretName: lineage-controller-webhook-cert
|
||||
duration: 8760h
|
||||
renewBefore: 720h
|
||||
issuerRef:
|
||||
name: lineage-controller-webhook-ca
|
||||
commonName: lineage-controller-webhook
|
||||
dnsNames:
|
||||
- lineage-controller-webhook
|
||||
- lineage-controller-webhook.{{ .Release.Namespace }}.svc
|
||||
@@ -0,0 +1,46 @@
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: lineage-controller-webhook
|
||||
labels:
|
||||
app: lineage-controller-webhook
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: lineage-controller-webhook
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: lineage-controller-webhook
|
||||
spec:
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/control-plane: ""
|
||||
tolerations:
|
||||
- key: "node-role.kubernetes.io/control-plane"
|
||||
operator: "Exists"
|
||||
effect: "NoSchedule"
|
||||
- key: "node-role.kubernetes.io/master"
|
||||
operator: "Exists"
|
||||
effect: "NoSchedule"
|
||||
serviceAccountName: lineage-controller-webhook
|
||||
containers:
|
||||
- name: lineage-controller-webhook
|
||||
image: "{{ .Values.lineageControllerWebhook.image }}"
|
||||
args:
|
||||
{{- if .Values.lineageControllerWebhook.debug }}
|
||||
- --zap-log-level=debug
|
||||
{{- else }}
|
||||
- --zap-log-level=info
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: webhook
|
||||
containerPort: 9443
|
||||
volumeMounts:
|
||||
- name: webhook-certs
|
||||
mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: webhook-certs
|
||||
secret:
|
||||
secretName: lineage-controller-webhook-cert
|
||||
defaultMode: 0400
|
||||
@@ -3,7 +3,7 @@ kind: MutatingWebhookConfiguration
|
||||
metadata:
|
||||
name: lineage
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/cozystack-controller-webhook
|
||||
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/lineage-controller-webhook
|
||||
labels:
|
||||
app: cozystack-controller
|
||||
webhooks:
|
||||
@@ -12,7 +12,7 @@ webhooks:
|
||||
sideEffects: None
|
||||
clientConfig:
|
||||
service:
|
||||
name: cozystack-controller
|
||||
name: lineage-controller-webhook
|
||||
namespace: {{ .Release.Namespace }}
|
||||
path: /mutate-lineage
|
||||
rules:
|
||||
@@ -40,3 +40,7 @@ webhooks:
|
||||
values:
|
||||
- kube-system
|
||||
- default
|
||||
objectSelector:
|
||||
matchExpressions:
|
||||
- key: internal.cozystack.io/managed-by-cozystack
|
||||
operator: DoesNotExist
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: lineage-controller-webhook
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: lineage-controller-webhook
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: lineage-controller-webhook
|
||||
namespace: {{ .Release.Namespace }}
|
||||
@@ -0,0 +1,8 @@
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: lineage-controller-webhook
|
||||
rules:
|
||||
- apiGroups: ['*']
|
||||
resources: ['*']
|
||||
verbs: ["get", "list", "watch"]
|
||||
@@ -0,0 +1,4 @@
|
||||
kind: ServiceAccount
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: lineage-controller-webhook
|
||||
@@ -1,10 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: cozystack-controller
|
||||
name: lineage-controller-webhook
|
||||
labels:
|
||||
app: cozystack-controller
|
||||
app: lineage-controller-webhook
|
||||
spec:
|
||||
internalTrafficPolicy: Local
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 443
|
||||
@@ -12,4 +13,4 @@ spec:
|
||||
protocol: TCP
|
||||
name: webhook
|
||||
selector:
|
||||
app: cozystack-controller
|
||||
app: lineage-controller-webhook
|
||||
3
packages/system/lineage-controller-webhook/values.yaml
Normal file
3
packages/system/lineage-controller-webhook/values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
lineageControllerWebhook:
|
||||
image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v0.37.2@sha256:b5f88cafe82809aeb06d92bb4127efa322aa666a56c22a4b664091160166cf55
|
||||
debug: false
|
||||
@@ -1,3 +1,3 @@
|
||||
objectstorage:
|
||||
controller:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v0.37.0@sha256:5f2eed05d19ba971806374834cb16ca49282aac76130194c00b213c79ce3e10d"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v0.37.2@sha256:6d0ca2d95a9bfd29fb2f0e8b2b8a84b16c270830933457ed8c5c27ae3c6d2de7"
|
||||
|
||||
@@ -120,7 +120,7 @@ seaweedfs:
|
||||
bucketClassName: "seaweedfs"
|
||||
region: ""
|
||||
sidecar:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.0@sha256:f166f09cdc9cdbb758209883819ab8261a3793bc1d7a6b6685efd5a2b2930847"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.2@sha256:1a739164b518dc395375ce9057bb582b5c539555f0ee2f2df7f931b23a1c4a48"
|
||||
certificates:
|
||||
commonName: "SeaweedFS CA"
|
||||
ipAddresses: []
|
||||
|
||||
@@ -138,8 +138,7 @@ func (c completedConfig) New() (*CozyServer, error) {
|
||||
coreV1alpha1Storage["tenantnamespaces"] = cozyregistry.RESTInPeace(
|
||||
tenantnamespacestorage.NewREST(
|
||||
clientset.CoreV1(),
|
||||
clientset.AuthorizationV1(),
|
||||
20,
|
||||
clientset.RbacV1(),
|
||||
),
|
||||
)
|
||||
coreV1alpha1Storage["tenantsecrets"] = cozyregistry.RESTInPeace(
|
||||
|
||||
@@ -7,13 +7,10 @@ package tenantnamespace
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
authorizationv1 "k8s.io/api/authorization/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
@@ -24,9 +21,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
authorizationv1client "k8s.io/client-go/kubernetes/typed/authorization/v1"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/klog/v2"
|
||||
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||
|
||||
corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1"
|
||||
)
|
||||
@@ -50,21 +46,18 @@ var (
|
||||
)
|
||||
|
||||
type REST struct {
|
||||
core corev1client.CoreV1Interface
|
||||
authClient authorizationv1client.AuthorizationV1Interface
|
||||
maxWorkers int
|
||||
gvr schema.GroupVersionResource
|
||||
core corev1client.CoreV1Interface
|
||||
rbac rbacv1client.RbacV1Interface
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
func NewREST(
|
||||
coreCli corev1client.CoreV1Interface,
|
||||
authCli authorizationv1client.AuthorizationV1Interface,
|
||||
maxWorkers int,
|
||||
rbacCli rbacv1client.RbacV1Interface,
|
||||
) *REST {
|
||||
return &REST{
|
||||
core: coreCli,
|
||||
authClient: authCli,
|
||||
maxWorkers: maxWorkers,
|
||||
core: coreCli,
|
||||
rbac: rbacCli,
|
||||
gvr: schema.GroupVersionResource{
|
||||
Group: corev1alpha1.GroupName,
|
||||
Version: "v1alpha1",
|
||||
@@ -271,76 +264,65 @@ func (r *REST) filterAccessible(
|
||||
ctx context.Context,
|
||||
names []string,
|
||||
) ([]string, error) {
|
||||
workers := int(math.Min(float64(r.maxWorkers), float64(len(names))))
|
||||
type job struct{ name string }
|
||||
type res struct {
|
||||
name string
|
||||
allowed bool
|
||||
err error
|
||||
u, ok := request.UserFrom(ctx)
|
||||
if !ok {
|
||||
return []string{}, fmt.Errorf("user missing in context")
|
||||
}
|
||||
jobs := make(chan job, workers)
|
||||
out := make(chan res, workers)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < workers; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for j := range jobs {
|
||||
ok, err := r.sar(ctx, j.name)
|
||||
out <- res{j.name, ok, err}
|
||||
}
|
||||
}()
|
||||
groups := make(map[string]struct{})
|
||||
for _, group := range u.GetGroups() {
|
||||
groups[group] = struct{}{}
|
||||
}
|
||||
go func() { wg.Wait(); close(out) }()
|
||||
|
||||
go func() {
|
||||
for _, n := range names {
|
||||
jobs <- job{n}
|
||||
}
|
||||
close(jobs)
|
||||
}()
|
||||
|
||||
var allowed []string
|
||||
for r := range out {
|
||||
if r.err != nil {
|
||||
klog.Errorf("SAR failed for %s: %v", r.name, r.err)
|
||||
if _, ok = groups["system:masters"]; ok {
|
||||
return names, nil
|
||||
}
|
||||
if _, ok = groups["cozystack-cluster-admin"]; ok {
|
||||
return names, nil
|
||||
}
|
||||
nameSet := make(map[string]struct{})
|
||||
for _, name := range names {
|
||||
nameSet[name] = struct{}{}
|
||||
}
|
||||
rbs, err := r.rbac.RoleBindings("").List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("failed to list rolebindings")
|
||||
}
|
||||
allowedNameSet := make(map[string]struct{})
|
||||
for i := range rbs.Items {
|
||||
if _, ok := allowedNameSet[rbs.Items[i].Namespace]; ok {
|
||||
continue
|
||||
}
|
||||
if r.allowed {
|
||||
allowed = append(allowed, r.name)
|
||||
if _, ok := nameSet[rbs.Items[i].Namespace]; !ok {
|
||||
continue
|
||||
}
|
||||
subjectLoop:
|
||||
for j := range rbs.Items[i].Subjects {
|
||||
subj := rbs.Items[i].Subjects[j]
|
||||
switch subj.Kind {
|
||||
case "Group":
|
||||
if _, ok = groups[subj.Name]; ok {
|
||||
allowedNameSet[rbs.Items[i].Namespace] = struct{}{}
|
||||
break subjectLoop
|
||||
}
|
||||
case "User":
|
||||
if subj.Name == u.GetName() {
|
||||
allowedNameSet[rbs.Items[i].Namespace] = struct{}{}
|
||||
break subjectLoop
|
||||
}
|
||||
case "ServiceAccount":
|
||||
if u.GetName() == fmt.Sprintf("system:serviceaccount:%s:%s", subj.Namespace, subj.Name) {
|
||||
allowedNameSet[rbs.Items[i].Namespace] = struct{}{}
|
||||
break subjectLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
allowed := make([]string, 0, len(allowedNameSet))
|
||||
for name := range allowedNameSet {
|
||||
allowed = append(allowed, name)
|
||||
}
|
||||
return allowed, nil
|
||||
}
|
||||
|
||||
func (r *REST) sar(ctx context.Context, ns string) (bool, error) {
|
||||
u, ok := request.UserFrom(ctx)
|
||||
if !ok || u == nil {
|
||||
return false, fmt.Errorf("user missing in context")
|
||||
}
|
||||
|
||||
sar := &authorizationv1.SubjectAccessReview{
|
||||
Spec: authorizationv1.SubjectAccessReviewSpec{
|
||||
User: u.GetName(),
|
||||
Groups: u.GetGroups(),
|
||||
ResourceAttributes: &authorizationv1.ResourceAttributes{
|
||||
Group: "cozystack.io",
|
||||
Resource: "workloadmonitors",
|
||||
Verb: "get",
|
||||
Namespace: ns,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rsp, err := r.authClient.SubjectAccessReviews().
|
||||
Create(ctx, sar, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return rsp.Status.Allowed, nil
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Boiler-plate
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -26,8 +26,17 @@ cozypkg -n cozy-system -C packages/system/cozystack-resource-definition-crd appl
|
||||
cozypkg -n cozy-system -C packages/system/cozystack-resource-definitions apply cozystack-resource-definitions --plain
|
||||
cozypkg -n cozy-system -C packages/system/cozystack-api apply cozystack-api --plain
|
||||
helm upgrade --install -n cozy-system cozystack-controller ./packages/system/cozystack-controller/ --take-ownership
|
||||
helm upgrade --install -n cozy-system lineage-controller-webhook ./packages/system/lineage-controller-webhook/ --take-ownership
|
||||
|
||||
sleep 5
|
||||
kubectl delete ns cozy-lineage-webhook-test --ignore-not-found && kubectl create ns cozy-lineage-webhook-test
|
||||
cleanup_test_ns() {
|
||||
kubectl delete ns cozy-lineage-webhook-test --ignore-not-found
|
||||
}
|
||||
trap cleanup_test_ns ERR
|
||||
timeout 60 sh -c 'until kubectl -n cozy-lineage-webhook-test create service clusterip lineage-webhook-test --clusterip="None" --dry-run=server; do sleep 1; done'
|
||||
cleanup_test_ns
|
||||
|
||||
kubectl wait deployment/cozystack-api -n cozy-system --timeout=4m --for=condition=available || exit 1
|
||||
kubectl wait deployment/cozystack-controller -n cozy-system --timeout=4m --for=condition=available || exit 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user