Add pod security admission controller labels
Pod security admission controller labels on namespaces are needed for pod security admission controller to know how restrictive each namespace is. This commit adds labels for pod security admission controller to our namespaces. Pod security admission controller is enabled by default on kubernetes 1.23. These labels do nothing harmful or beneficial on the lower versions of kubernetes. Test Plan: PASS: Bootstrap system and ensure the pod security admission controller labels are present on our namespaces (kube-system, armada, deployment, and any namespaces created by applications such as cert-manager) PASS: Upgrade an old system and ensure the labels are added after the upgrade is finished PASS: Try to bring up privileged pods in a baseline namespace, ensure it fails. This was done on a developer iso, since we do not have kubernetes 1.23 ready yet. The same labels were applied to the developer iso's namespaces. PASS: Deploy a privileged pod in a baseline namespace in the current kubernetes version. Ensure it is NOT rejected Change-Id: Ib909eaacb6bba3b5c3327e2f9998a5ecdcb70e9b Story: 2009833 Task: 44764 Signed-off-by: Jerry Sun <jerry.sun@windriver.com>
This commit is contained in:
parent
f9dc544340
commit
aa93e03b10
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script adds pod security admission controller labels to a system
|
||||
# after upgrades. These are applied by ansible and sysinv when a new
|
||||
# namespace is created during application deployment. Upgrades needs
|
||||
# to apply these labels to existing namespaces
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from controllerconfig.common import log
|
||||
from sysinv.helm import common
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
log.configure()
|
||||
if from_release == '21.12' and action == 'activate':
|
||||
LOG.info("%s invoked from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
add_pod_security_admission_controller_labels()
|
||||
|
||||
|
||||
def add_pod_security_admission_controller_labels():
|
||||
try:
|
||||
cmd = ["kubectl", "--kubeconfig=/etc/kubernetes/admin.conf",
|
||||
"get", "namespaces", "-o=name"]
|
||||
|
||||
namespaces_output = subprocess.check_output(cmd)
|
||||
|
||||
except Exception as exc:
|
||||
LOG.error('Command failed:\n %s' % (cmd))
|
||||
raise Exception('Cannot get namespaces for pod security labels')
|
||||
|
||||
for line in namespaces_output.splitlines():
|
||||
# we add pod security admission controller labels to namespaces that
|
||||
# we create
|
||||
namespace = line.replace("namespace/", "")
|
||||
if namespace not in common.PRIVILEGED_NS \
|
||||
and namespace not in common.BASELINE_NS:
|
||||
continue
|
||||
|
||||
security_version = 'v1.23'
|
||||
security_level = 'baseline'
|
||||
if namespace in common.PRIVILEGED_NS:
|
||||
security_level = 'privileged'
|
||||
|
||||
try:
|
||||
cmd = ["kubectl", "--kubeconfig=/etc/kubernetes/admin.conf",
|
||||
"label", "--overwrite", "namespaces", namespace,
|
||||
"pod-security.kubernetes.io/enforce=%s"
|
||||
% (security_level),
|
||||
"pod-security.kubernetes.io/warn=%s"
|
||||
% (security_level),
|
||||
"pod-security.kubernetes.io/audit=%s"
|
||||
% (security_level),
|
||||
"pod-security.kubernetes.io/enforce-version=%s"
|
||||
% (security_version),
|
||||
"pod-security.kubernetes.io/warn-version=%s"
|
||||
% (security_version),
|
||||
"pod-security.kubernetes.io/audit-version=%s"
|
||||
% (security_version)]
|
||||
subprocess.call(cmd)
|
||||
except Exception as exc:
|
||||
LOG.error('Command failed:\n %s\n%s' % (cmd, exc))
|
||||
raise Exception('Cannot assign pod security label')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
|
@ -448,6 +448,15 @@ class KubeOperator(object):
|
|||
LOG.error("Kubernetes exception in kube_get_secret: %s" % e)
|
||||
raise
|
||||
|
||||
def kube_patch_namespace(self, namespace, body):
|
||||
c = self._get_kubernetesclient_core()
|
||||
try:
|
||||
c.patch_namespace(namespace, body)
|
||||
except Exception as e:
|
||||
LOG.error("Failed to patch namespace %s with patch %s: %s"
|
||||
% (namespace, body, e))
|
||||
raise
|
||||
|
||||
def kube_create_secret(self, namespace, body):
|
||||
c = self._get_kubernetesclient_core()
|
||||
try:
|
||||
|
|
|
@ -38,6 +38,16 @@ HELM_NS_STORAGE_PROVISIONER = HELM_NS_KUBE_SYSTEM
|
|||
HELM_NS_CERT_MANAGER = 'cert-manager'
|
||||
HELM_NS_VAULT = 'vault'
|
||||
HELM_NS_NOTIFICATION = 'notification'
|
||||
HELM_NS_DEPLOYMENT = 'deployment'
|
||||
HELM_NS_ARMADA = 'armada'
|
||||
|
||||
# namespace groups for pod security admission controller
|
||||
PRIVILEGED_NS = [HELM_NS_KUBE_SYSTEM]
|
||||
BASELINE_NS = [HELM_NS_CEPH, HELM_NS_NFS, HELM_NS_OPENSTACK, HELM_NS_HELM_TOOLKIT,
|
||||
HELM_NS_MONITOR, HELM_NS_RBD_PROVISIONER, HELM_NS_STORAGE_PROVISIONER,
|
||||
HELM_NS_CERT_MANAGER, HELM_NS_VAULT, HELM_NS_NOTIFICATION,
|
||||
HELM_NS_DEPLOYMENT, HELM_NS_ARMADA]
|
||||
POD_SECURITY_VERSION = 'v1.23'
|
||||
|
||||
# Services
|
||||
# Matches configassistant.py value => Should change to STARLINGX
|
||||
|
|
|
@ -81,6 +81,7 @@ class AppLifecycleOperator(object):
|
|||
if hook_info.operation == constants.APP_APPLY_OP and \
|
||||
hook_info.relative_timing == constants.APP_LIFECYCLE_TIMING_PRE:
|
||||
lifecycle_utils.create_local_registry_secrets(app_op, app, hook_info)
|
||||
lifecycle_utils.add_pod_security_admission_controller_labels(app_op, app, hook_info)
|
||||
elif hook_info.operation == constants.APP_REMOVE_OP and \
|
||||
hook_info.relative_timing == constants.APP_LIFECYCLE_TIMING_POST:
|
||||
lifecycle_utils.delete_local_registry_secrets(app_op, app, hook_info)
|
||||
|
|
|
@ -199,6 +199,49 @@ def delete_configmap(app_op, namespace, configmap):
|
|||
raise
|
||||
|
||||
|
||||
def add_pod_security_admission_controller_labels(app_op, app, hook_info):
|
||||
""" adds labels to newly created namespaces
|
||||
|
||||
Pod security admission controllers uses labels to enforce policies
|
||||
this method adds labels used by pod security admission controller
|
||||
this is needed because new applications can create new namespaces
|
||||
as they are deployed.
|
||||
|
||||
:param app_op: AppOperator object
|
||||
:param app: AppOperator.Application object
|
||||
:param hook_info: LifecycleHookInfo object
|
||||
|
||||
"""
|
||||
app_ns = app_op._helm.get_helm_application_namespaces(app.name)
|
||||
|
||||
namespaces = \
|
||||
list(set([ns for ns_list in app_ns.values() for ns in ns_list]))
|
||||
|
||||
for ns in namespaces:
|
||||
|
||||
security_level = 'baseline'
|
||||
if ns in common.PRIVILEGED_NS:
|
||||
security_level = 'privileged'
|
||||
|
||||
body = {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"pod-security.kubernetes.io/enforce": security_level,
|
||||
"pod-security.kubernetes.io/warn": security_level,
|
||||
"pod-security.kubernetes.io/audit": security_level,
|
||||
"pod-security.kubernetes.io/enforce-version": common.POD_SECURITY_VERSION,
|
||||
"pod-security.kubernetes.io/warn-version": common.POD_SECURITY_VERSION,
|
||||
"pod-security.kubernetes.io/audit-version": common.POD_SECURITY_VERSION}
|
||||
}
|
||||
}
|
||||
|
||||
try:
|
||||
app_op._kube.kube_patch_namespace(ns, body)
|
||||
except Exception as e:
|
||||
LOG.error(e)
|
||||
raise
|
||||
|
||||
|
||||
def create_local_registry_secrets(app_op, app, hook_info):
|
||||
# Temporary function to create default registry secret
|
||||
# which would be used by kubernetes to pull images from
|
||||
|
|
Loading…
Reference in New Issue