mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-30 19:35:06 +00:00
feat: add kyverno managed resources protection (#4414)
* feat: add kyverno managed resources protection Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> * add toggle Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
This commit is contained in:
parent
1947dafed6
commit
317a3ae0bf
5 changed files with 51 additions and 7 deletions
|
@ -131,6 +131,8 @@ spec:
|
|||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: KYVERNO_SERVICEACCOUNT_NAME
|
||||
value: {{ template "kyverno.serviceAccountName" . }}
|
||||
- name: KYVERNO_SVC
|
||||
value: {{ template "kyverno.serviceName" . }}
|
||||
- name: TUF_ROOT
|
||||
|
|
|
@ -111,6 +111,7 @@ func main() {
|
|||
flag.DurationVar(&webhookRegistrationTimeout, "webhookRegistrationTimeout", 120*time.Second, "Timeout for webhook registration, e.g., 30s, 1m, 5m.")
|
||||
flag.IntVar(&changeRequestLimit, "maxReportChangeRequests", 1000, "Maximum pending report change requests per namespace or for the cluster-wide policy report.")
|
||||
flag.Func(toggle.SplitPolicyReportFlagName, toggle.SplitPolicyReportDescription, toggle.SplitPolicyReport.Parse)
|
||||
flag.Func(toggle.ProtectManagedResourcesFlagName, toggle.ProtectManagedResourcesDescription, toggle.ProtectManagedResources.Parse)
|
||||
if err := flag.Set("v", "2"); err != nil {
|
||||
setupLog.Error(err, "failed to set log level")
|
||||
os.Exit(1)
|
||||
|
|
|
@ -72,6 +72,8 @@ const (
|
|||
var (
|
||||
// kyvernoNamespace is the Kyverno namespace
|
||||
kyvernoNamespace = osutils.GetEnvWithFallback("KYVERNO_NAMESPACE", "kyverno")
|
||||
// kyvernoServiceAccountName is the Kyverno service account name
|
||||
kyvernoServiceAccountName = osutils.GetEnvWithFallback("KYVERNO_SERVICEACCOUNT_NAME", "kyverno")
|
||||
// kyvernoDeploymentName is the Kyverno deployment name
|
||||
kyvernoDeploymentName = osutils.GetEnvWithFallback("KYVERNO_DEPLOYMENT", "kyverno")
|
||||
// kyvernoServiceName is the Kyverno service name
|
||||
|
@ -88,6 +90,10 @@ func KyvernoNamespace() string {
|
|||
return kyvernoNamespace
|
||||
}
|
||||
|
||||
func KyvernoServiceAccountName() string {
|
||||
return kyvernoServiceAccountName
|
||||
}
|
||||
|
||||
func KyvernoDeploymentName() string {
|
||||
return kyvernoDeploymentName
|
||||
}
|
||||
|
|
|
@ -6,19 +6,27 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
AutogenInternalsFlagName = "autogenInternals"
|
||||
AutogenInternalsDescription = "Enables autogen internal policies. When this is 'true' policy rules should not be mutated."
|
||||
autogenInternalsEnvVar = "FLAG_AUTOGEN_INTERNALS"
|
||||
defaultAutogenInternals = true
|
||||
// autogen
|
||||
AutogenInternalsFlagName = "autogenInternals"
|
||||
AutogenInternalsDescription = "Enables autogen internal policies. When this is 'true' policy rules should not be mutated."
|
||||
autogenInternalsEnvVar = "FLAG_AUTOGEN_INTERNALS"
|
||||
defaultAutogenInternals = true
|
||||
// split resource
|
||||
SplitPolicyReportFlagName = "splitPolicyReport"
|
||||
SplitPolicyReportDescription = "Set the flag to 'true', to enable the split-up PolicyReports per policy."
|
||||
splitPolicyReportEnvVar = "FLAG_SPLIT_POLICY_REPORT"
|
||||
defaultSplitPolicyReport = false
|
||||
// protect managed resource
|
||||
ProtectManagedResourcesFlagName = "protectManagedResources"
|
||||
ProtectManagedResourcesDescription = "Set the flag to 'true', to enable managed resources protection."
|
||||
protectManagedResourcesEnvVar = "FLAG_PROTECT_MANAGED_RESOURCES"
|
||||
defaultProtectManagedResources = false
|
||||
)
|
||||
|
||||
var (
|
||||
AutogenInternals = newToggle(defaultAutogenInternals, autogenInternalsEnvVar)
|
||||
SplitPolicyReport = newToggle(defaultSplitPolicyReport, splitPolicyReportEnvVar)
|
||||
AutogenInternals = newToggle(defaultAutogenInternals, autogenInternalsEnvVar)
|
||||
SplitPolicyReport = newToggle(defaultSplitPolicyReport, splitPolicyReportEnvVar)
|
||||
ProtectManagedResources = newToggle(defaultProtectManagedResources, protectManagedResourcesEnvVar)
|
||||
)
|
||||
|
||||
type Toggle interface {
|
||||
|
|
|
@ -3,6 +3,7 @@ package webhooks
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -10,9 +11,13 @@ import (
|
|||
"github.com/go-logr/logr"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/toggle"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||
"github.com/kyverno/kyverno/pkg/webhookconfig"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
type Server interface {
|
||||
|
@ -118,10 +123,32 @@ func (s *server) cleanup(ctx context.Context) {
|
|||
close(s.cleanUp)
|
||||
}
|
||||
|
||||
func protect(inner handlers.AdmissionHandler) handlers.AdmissionHandler {
|
||||
return func(logger logr.Logger, request *admissionv1.AdmissionRequest) *admissionv1.AdmissionResponse {
|
||||
if toggle.ProtectManagedResources.Enabled() {
|
||||
newResource, oldResource, err := utils.ExtractResources(nil, request)
|
||||
if err != nil {
|
||||
logger.Error(err, "Failed to extract resources")
|
||||
return admissionutils.ResponseFailure(err.Error())
|
||||
}
|
||||
for _, resource := range []unstructured.Unstructured{newResource, oldResource} {
|
||||
resLabels := resource.GetLabels()
|
||||
if resLabels["app.kubernetes.io/managed-by"] == "kyverno" {
|
||||
if request.UserInfo.Username != fmt.Sprintf("system:serviceaccount:%s:%s", config.KyvernoNamespace(), config.KyvernoServiceAccountName()) {
|
||||
logger.Info("Access to the resource not authorized, this is a kyverno managed resource and should be altered only by kyverno")
|
||||
return admissionutils.ResponseFailure("A kyverno managed resource can only be modified by kyverno")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return inner(logger, request)
|
||||
}
|
||||
}
|
||||
|
||||
func filter(configuration config.Configuration, inner handlers.AdmissionHandler) handlers.AdmissionHandler {
|
||||
return handlers.Filter(configuration, inner)
|
||||
}
|
||||
|
||||
func admission(logger logr.Logger, monitor *webhookconfig.Monitor, inner handlers.AdmissionHandler) http.HandlerFunc {
|
||||
return handlers.Monitor(monitor, handlers.Admission(logger, inner))
|
||||
return handlers.Monitor(monitor, handlers.Admission(logger, protect(inner)))
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue