From 1cbed2a0d83c23fc67d48af7bc92e205f7b79948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20PEREZ?= Date: Mon, 8 Jan 2024 14:46:30 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Mise=20en=20place=20des=20PodSecuri?= =?UTF-8?q?tyAdmission=20sur=20les=20namespaces=20clients?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dans l'objectif de remplacer les podSecurityPolicy en prévision du passage en Kubernetes 1.26, il est nécessaire de mettre en place les nouvelles règles de sécurité. A ce jour, en lien avec cette documentation : URL://pages/viewpage.action?pageId=228069521 Nous mettons en place par défaut un enforce sur la policy "baseline", avec un warning emis dès lors que l'applicatif ne respecte pas la policy "restricted" et réalisons par défaut l'émission d'un event d'audit lorsque la policy ne respecte pas le niveau "restricted". L'objectif est d'effectuer une bascule en souplesse des projets clients ne respectant pas en totalité la règle restricted (en rapport avec la manière dont son run les applications sur les clusters). Dans un premier temps, les projets pourront se voir autoriser des droits plus importants, mais l'objectif est de les prévenir que ces actions ne respectent pas les best-practices. + ✨ Permet d'autoriser certains namespaces clients à être en "privileged" Sans cette modification tous namespaces clients sont considérés comme héritant de la politique par défaut. --- Readme.md | 5 +++- internal/services/provisionner.go | 11 +++++---- internal/utils/config.go | 40 ++++++++++++++++++------------- internal/utils/constants.go | 7 +++++- internal/utils/helpers.go | 15 +++++++++++- pkg/types/types.go | 36 +++++++++++++++------------- 6 files changed, 75 insertions(+), 39 deletions(-) diff --git a/Readme.md b/Readme.md index c2437c17..8b0dad7e 100755 --- a/Readme.md +++ b/Readme.md @@ -105,7 +105,10 @@ For specific exceptions, add another network policy. | **CUSTOM_LABELS** | *Add custom labels to namespaces* | `quota=managed,monitoring=true` | `no ` | - | | **DEFAULT_PERMISSION** | *ClusterRole associated with default service account* | `view` | `no ` | - | | **BLACKLIST** | *Ignore Project* | `my-project-dev` | `no ` | - | - +| **PODSECURITYADMISSION_ENFORCEMENT** | *PodSecurityAdmission Enforcement* | `restricted` | `no ` | `baseline ` | +| **PODSECURITYADMISSION_WARNING** | *PodSecurityAdmission Warning* | `restricted` | `no ` | `restricted ` | +| **PODSECURITYADMISSION_AUDIT** | *PodSecurityAdmission Audit* | `restricted` | `no ` | `restricted ` | +| **PRIVILEGED_NAMESPACES** | *Namespaces allowed to use privileged annotation* | `native-development` | `no ` | - | ## Versioning Since version v1.24.0, we have decided to modify the naming of versions for ease of reading and understanding. diff --git a/internal/services/provisionner.go b/internal/services/provisionner.go index 1cdcec9a..df99985e 100644 --- a/internal/services/provisionner.go +++ b/internal/services/provisionner.go @@ -481,10 +481,13 @@ func updateExistingNamespace(project *v12.Project, api v13.CoreV1Interface) erro func generateNamespaceLabels(project *v12.Project) (labels map[string]string) { defaultLabels := map[string]string{ - "name": project.Name, - "type": "customer", - "creator": "kubi", - "environment": project.Spec.Environment, + "name": project.Name, + "type": "customer", + "creator": "kubi", + "environment": project.Spec.Environment, + "pod-security.kubernetes.io/enforce": utils.IsInPrivilegedNamespacesList(project.Name), + "pod-security.kubernetes.io/warn": utils.Config.PodSecurityAdmissionWarning, + "pod-security.kubernetes.io/audit": utils.Config.PodSecurityAdmissionAudit, } return utils.Union(defaultLabels, utils.Config.CustomLabels) diff --git a/internal/utils/config.go b/internal/utils/config.go index 6925ba6d..0079881c 100644 --- a/internal/utils/config.go +++ b/internal/utils/config.go @@ -99,6 +99,10 @@ func MakeConfig() (*types.Config, error) { ldapUserFilter := getEnv("LDAP_USERFILTER", "(cn=%s)") tenant := strings.ToLower(getEnv("TENANT", KubiTenantUndeterminable)) + podSecurityAdmissionEnforcement := strings.ToLower(getEnv("PODSECURITYADMISSION_ENFORCEMENT", PodSecurityAdmissionEnforcement)) + podSecurityAdmissionWarning := strings.ToLower(getEnv("PODSECURITYADMISSION_WARNING", PodSecurityAdmissionWarning)) + podSecurityAdmissionAudit := strings.ToLower(getEnv("PODSECURITYADMISSION_AUDIT", PodSecurityAdmissionAudit)) + ldapConfig := types.LdapConfig{ UserBase: os.Getenv("LDAP_USERBASE"), GroupBase: os.Getenv("LDAP_GROUPBASE"), @@ -122,22 +126,26 @@ func MakeConfig() (*types.Config, error) { Attributes: []string{"givenName", "sn", "mail", "uid", "cn", "userPrincipalName"}, } config := &types.Config{ - Tenant: tenant, - Ldap: ldapConfig, - KubeCa: caEncoded, - KubeCaText: string(kubeCA), - KubeToken: string(kubeToken), - PublicApiServerURL: getEnv("PUBLIC_APISERVER_URL", ""), - ApiServerTLSConfig: *tlsConfig, - TokenLifeTime: getEnv("TOKEN_LIFETIME", "4h"), - ExtraTokenLifeTime: getEnv("EXTRA_TOKEN_LIFETIME", "720h"), - Locator: getEnv("LOCATOR", KubiLocatorIntranet), - NetworkPolicy: networkpolicyEnabled, - CustomLabels: customLabels, - DefaultPermission: getEnv("DEFAULT_PERMISSION", ""), - Blacklist: strings.Split(getEnv("BLACKLIST", ""), ","), - Whitelist: whitelist, - BlackWhitelistNamespace: getEnv("BLACK_WHITELIST_NAMESPACE", "default"), + Tenant: tenant, + PodSecurityAdmissionEnforcement: podSecurityAdmissionEnforcement, + PodSecurityAdmissionWarning: podSecurityAdmissionWarning, + PodSecurityAdmissionAudit: podSecurityAdmissionAudit, + Ldap: ldapConfig, + KubeCa: caEncoded, + KubeCaText: string(kubeCA), + KubeToken: string(kubeToken), + PublicApiServerURL: getEnv("PUBLIC_APISERVER_URL", ""), + ApiServerTLSConfig: *tlsConfig, + TokenLifeTime: getEnv("TOKEN_LIFETIME", "4h"), + ExtraTokenLifeTime: getEnv("EXTRA_TOKEN_LIFETIME", "720h"), + Locator: getEnv("LOCATOR", KubiLocatorIntranet), + NetworkPolicy: networkpolicyEnabled, + CustomLabels: customLabels, + DefaultPermission: getEnv("DEFAULT_PERMISSION", ""), + PrivilegedNamespaces: strings.Split(getEnv("PRIVILEGED_NAMESPACES", ""), ","), + Blacklist: strings.Split(getEnv("BLACKLIST", ""), ","), + Whitelist: whitelist, + BlackWhitelistNamespace: getEnv("BLACK_WHITELIST_NAMESPACE", "default"), } err := validation.ValidateStruct(config, diff --git a/internal/utils/constants.go b/internal/utils/constants.go index d354af9a..1bdb74fe 100644 --- a/internal/utils/constants.go +++ b/internal/utils/constants.go @@ -51,7 +51,12 @@ const ( KubiEnvironmentDevelopment = "development" KubiEnvironmentShortDevelopment = "dev" - KubiTenantUndeterminable = "undeterminable" + KubiTenantUndeterminable = "undeterminable" + PodSecurityAdmissionEnforcement = "baseline" + PodSecurityAdmissionWarning = "restricted" + PodSecurityAdmissionAudit = "restricted" + + PodSecurityPrivileged = "privileged" ) var BlacklistedNamespaces = []string{ diff --git a/internal/utils/helpers.go b/internal/utils/helpers.go index 405d5674..cfb86c42 100644 --- a/internal/utils/helpers.go +++ b/internal/utils/helpers.go @@ -1,6 +1,9 @@ package utils -import "os" +import ( + "os" + "strings" +) func IsEmpty(value string) bool { return len(value) == 0 @@ -46,3 +49,13 @@ func Union(a map[string]string, b map[string]string) map[string]string { } return a } + +func IsInPrivilegedNamespacesList(namespace string) string { + for _, nsItem := range Config.PrivilegedNamespaces { + if strings.Contains(nsItem, namespace) { + Log.Warn().Msgf("Namespace %v is labeled as privileged", namespace) + return PodSecurityPrivileged + } + } + return Config.PodSecurityAdmissionEnforcement +} diff --git a/pkg/types/types.go b/pkg/types/types.go index 37ca8ba6..d7f1490e 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -32,22 +32,26 @@ type LdapConfig struct { } type Config struct { - Tenant string - Ldap LdapConfig - PublicApiServerURL string - KubeCa string - KubeCaText string - KubeToken string - ApiServerTLSConfig tls.Config - TokenLifeTime string - ExtraTokenLifeTime string - Locator string - NetworkPolicy bool - CustomLabels map[string]string - DefaultPermission string - Blacklist []string - BlackWhitelistNamespace string - Whitelist bool + PodSecurityAdmissionEnforcement string + PodSecurityAdmissionWarning string + PodSecurityAdmissionAudit string + Tenant string + Ldap LdapConfig + PublicApiServerURL string + KubeCa string + KubeCaText string + KubeToken string + ApiServerTLSConfig tls.Config + TokenLifeTime string + ExtraTokenLifeTime string + Locator string + NetworkPolicy bool + CustomLabels map[string]string + DefaultPermission string + PrivilegedNamespaces []string + Blacklist []string + BlackWhitelistNamespace string + Whitelist bool } // Note: struct fields must be public in order for unmarshal to