Skip to content

Commit

Permalink
UPSTREAM: <carry>: make the PSA workload admission warnings honor the…
Browse files Browse the repository at this point in the history
… changes that SCC will eventually make to the pod
  • Loading branch information
deads2k committed Dec 1, 2022
1 parent 761cfe9 commit 6fe5c8f
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
7 changes: 7 additions & 0 deletions openshift-kube-apiserver/enablement/intialization.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"io/ioutil"
"path"

"k8s.io/kubernetes/plugin/pkg/admission/security/podsecurity"

configv1 "github.com/openshift/api/config/v1"
kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1"
osinv1 "github.com/openshift/api/osin/v1"
"github.com/openshift/apiserver-library-go/pkg/securitycontextconstraints/sccadmission"
"github.com/openshift/library-go/pkg/config/helpers"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand Down Expand Up @@ -74,6 +77,8 @@ func ForceGlobalInitializationForOpenShift() {
},
})

podsecurity.SCCMutatingPodSpecExtractorInstance.SetSCCAdmission(SCCAdmissionPlugin)

// add permissions we require on our kube-apiserver
// TODO, we should scrub these out
bootstrappolicy.ClusterRoles = bootstrappolicy.OpenshiftClusterRoles
Expand All @@ -83,3 +88,5 @@ func ForceGlobalInitializationForOpenShift() {
// SkipSystemMastersAuthorizer disable implicitly added system/master authz, and turn it into another authz mode "SystemMasters", to be added via authorization-mode
server.SkipSystemMastersAuthorizer()
}

var SCCAdmissionPlugin = sccadmission.NewConstraint()
6 changes: 6 additions & 0 deletions openshift-kube-apiserver/openshiftkubeapiserver/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ func OpenShiftKubeAPIServerConfigPatch(genericConfig *genericapiserver.Config, k
admissionrestconfig.NewInitializer(*rest.CopyConfig(genericConfig.LoopbackClientConfig)),
managementcpusoverride.NewInitializer(openshiftInformers.getOpenshiftInfraInformers().Config().V1().Infrastructures()),
)

// This is needed in order to have the correct initializers for the SCC admission plugin which is used to mutate
// PodSpecs for PodSpec-y workload objects in the pod security admission plugin.
enablement.SCCAdmissionPlugin.SetAuthorizer(genericConfig.Authorization.Authorizer)
enablement.SCCAdmissionPlugin.SetSecurityInformers(openshiftInformers.getOpenshiftSecurityInformers().Security().V1().SecurityContextConstraints())
enablement.SCCAdmissionPlugin.SetExternalKubeInformerFactory(kubeInformers)
// END ADMISSION

// HANDLER CHAIN (with oauth server and web console)
Expand Down
2 changes: 1 addition & 1 deletion plugin/pkg/admission/security/podsecurity/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func newPlugin(reader io.Reader) (*Plugin, error) {
Configuration: config,
Evaluator: evaluator,
Metrics: getDefaultRecorder(),
PodSpecExtractor: podsecurityadmission.DefaultPodSpecExtractor{},
PodSpecExtractor: SCCMutatingPodSpecExtractorInstance,
},
}, nil
}
Expand Down
107 changes: 107 additions & 0 deletions plugin/pkg/admission/security/podsecurity/patch_podspecextractor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package podsecurity

import (
"context"
"fmt"

utilruntime "k8s.io/apimachinery/pkg/util/runtime"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authentication/serviceaccount"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/apis/core"
v1 "k8s.io/kubernetes/pkg/apis/core/v1"
podsecurityadmission "k8s.io/pod-security-admission/admission"
)

type SCCMutatingPodSpecExtractor struct {
sccAdmission admission.MutationInterface
delegate podsecurityadmission.PodSpecExtractor
}

var SCCMutatingPodSpecExtractorInstance = &SCCMutatingPodSpecExtractor{
delegate: podsecurityadmission.DefaultPodSpecExtractor{},
}

func (s *SCCMutatingPodSpecExtractor) SetSCCAdmission(sccAdmission admission.MutationInterface) {
s.sccAdmission = sccAdmission
}

func (s *SCCMutatingPodSpecExtractor) HasPodSpec(gr schema.GroupResource) bool {
return s.delegate.HasPodSpec(gr)
}

func (s *SCCMutatingPodSpecExtractor) ExtractPodSpec(obj runtime.Object) (*metav1.ObjectMeta, *corev1.PodSpec, error) {
if s.sccAdmission == nil {
return s.delegate.ExtractPodSpec(obj)
}

switch obj := obj.(type) {
case *corev1.Pod:
return s.delegate.ExtractPodSpec(obj)
}

podTemplateMeta, originalPodSpec, err := s.delegate.ExtractPodSpec(obj)
if err != nil {
return podTemplateMeta, originalPodSpec, err
}
if originalPodSpec == nil {
return nil, nil, nil
}
objectMeta, err := meta.Accessor(obj)
if err != nil {
return podTemplateMeta, originalPodSpec, fmt.Errorf("unable to get metadata for SCC mutation: %w", err)
}

pod := &corev1.Pod{
ObjectMeta: *podTemplateMeta.DeepCopy(),
Spec: *originalPodSpec.DeepCopy(),
}
if len(pod.Namespace) == 0 {
pod.Namespace = objectMeta.GetNamespace()
}
if len(pod.Name) == 0 {
pod.Name = "pod-for-container-named-" + objectMeta.GetName()
}
internalPod := &core.Pod{}
if err := v1.Convert_v1_Pod_To_core_Pod(pod, internalPod, nil); err != nil {
return nil, nil, err
}

admissionAttributes := admission.NewAttributesRecord(
internalPod,
nil,
corev1.SchemeGroupVersion.WithKind("Pod"),
pod.Namespace,
pod.Name,
corev1.SchemeGroupVersion.WithResource("pods"),
"",
admission.Create,
nil,
false,
&user.DefaultInfo{
Name: serviceaccount.MakeUsername(pod.Namespace, pod.Spec.ServiceAccountName),
UID: "",
Groups: append([]string{user.AllAuthenticated}, serviceaccount.MakeGroupNames(pod.Namespace)...),
Extra: nil,
})
if err := s.sccAdmission.Admit(context.Background(), admissionAttributes, nil); err != nil {
// don't fail the request, just warn if SCC will fail
klog.ErrorS(err, "failed to mutate object for PSA using SCC")
utilruntime.HandleError(fmt.Errorf("failed to mutate object for PSA using SCC: %w", err))
// TODO remove this failure we're causing when SCC fails, but for now we actually need to see our test fail because that was almost really bad.
return podTemplateMeta, originalPodSpec, err
}

if err := v1.Convert_core_Pod_To_v1_Pod(internalPod, pod, nil); err != nil {
return nil, nil, err
}

return podTemplateMeta, &pod.Spec, nil
}

0 comments on commit 6fe5c8f

Please sign in to comment.