Skip to content

Commit 6fe5c8f

Browse files
committed
UPSTREAM: <carry>: make the PSA workload admission warnings honor the changes that SCC will eventually make to the pod
1 parent 761cfe9 commit 6fe5c8f

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

Diff for: openshift-kube-apiserver/enablement/intialization.go

+7
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import (
44
"io/ioutil"
55
"path"
66

7+
"k8s.io/kubernetes/plugin/pkg/admission/security/podsecurity"
8+
79
configv1 "github.com/openshift/api/config/v1"
810
kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1"
911
osinv1 "github.com/openshift/api/osin/v1"
12+
"github.com/openshift/apiserver-library-go/pkg/securitycontextconstraints/sccadmission"
1013
"github.com/openshift/library-go/pkg/config/helpers"
1114
"k8s.io/apimachinery/pkg/runtime"
1215
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -74,6 +77,8 @@ func ForceGlobalInitializationForOpenShift() {
7477
},
7578
})
7679

80+
podsecurity.SCCMutatingPodSpecExtractorInstance.SetSCCAdmission(SCCAdmissionPlugin)
81+
7782
// add permissions we require on our kube-apiserver
7883
// TODO, we should scrub these out
7984
bootstrappolicy.ClusterRoles = bootstrappolicy.OpenshiftClusterRoles
@@ -83,3 +88,5 @@ func ForceGlobalInitializationForOpenShift() {
8388
// SkipSystemMastersAuthorizer disable implicitly added system/master authz, and turn it into another authz mode "SystemMasters", to be added via authorization-mode
8489
server.SkipSystemMastersAuthorizer()
8590
}
91+
92+
var SCCAdmissionPlugin = sccadmission.NewConstraint()

Diff for: openshift-kube-apiserver/openshiftkubeapiserver/patch.go

+6
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ func OpenShiftKubeAPIServerConfigPatch(genericConfig *genericapiserver.Config, k
7878
admissionrestconfig.NewInitializer(*rest.CopyConfig(genericConfig.LoopbackClientConfig)),
7979
managementcpusoverride.NewInitializer(openshiftInformers.getOpenshiftInfraInformers().Config().V1().Infrastructures()),
8080
)
81+
82+
// This is needed in order to have the correct initializers for the SCC admission plugin which is used to mutate
83+
// PodSpecs for PodSpec-y workload objects in the pod security admission plugin.
84+
enablement.SCCAdmissionPlugin.SetAuthorizer(genericConfig.Authorization.Authorizer)
85+
enablement.SCCAdmissionPlugin.SetSecurityInformers(openshiftInformers.getOpenshiftSecurityInformers().Security().V1().SecurityContextConstraints())
86+
enablement.SCCAdmissionPlugin.SetExternalKubeInformerFactory(kubeInformers)
8187
// END ADMISSION
8288

8389
// HANDLER CHAIN (with oauth server and web console)

Diff for: plugin/pkg/admission/security/podsecurity/admission.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func newPlugin(reader io.Reader) (*Plugin, error) {
114114
Configuration: config,
115115
Evaluator: evaluator,
116116
Metrics: getDefaultRecorder(),
117-
PodSpecExtractor: podsecurityadmission.DefaultPodSpecExtractor{},
117+
PodSpecExtractor: SCCMutatingPodSpecExtractorInstance,
118118
},
119119
}, nil
120120
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package podsecurity
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
8+
9+
corev1 "k8s.io/api/core/v1"
10+
"k8s.io/apimachinery/pkg/api/meta"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"k8s.io/apimachinery/pkg/runtime"
13+
"k8s.io/apimachinery/pkg/runtime/schema"
14+
"k8s.io/apiserver/pkg/admission"
15+
"k8s.io/apiserver/pkg/authentication/serviceaccount"
16+
"k8s.io/apiserver/pkg/authentication/user"
17+
"k8s.io/klog/v2"
18+
"k8s.io/kubernetes/pkg/apis/core"
19+
v1 "k8s.io/kubernetes/pkg/apis/core/v1"
20+
podsecurityadmission "k8s.io/pod-security-admission/admission"
21+
)
22+
23+
type SCCMutatingPodSpecExtractor struct {
24+
sccAdmission admission.MutationInterface
25+
delegate podsecurityadmission.PodSpecExtractor
26+
}
27+
28+
var SCCMutatingPodSpecExtractorInstance = &SCCMutatingPodSpecExtractor{
29+
delegate: podsecurityadmission.DefaultPodSpecExtractor{},
30+
}
31+
32+
func (s *SCCMutatingPodSpecExtractor) SetSCCAdmission(sccAdmission admission.MutationInterface) {
33+
s.sccAdmission = sccAdmission
34+
}
35+
36+
func (s *SCCMutatingPodSpecExtractor) HasPodSpec(gr schema.GroupResource) bool {
37+
return s.delegate.HasPodSpec(gr)
38+
}
39+
40+
func (s *SCCMutatingPodSpecExtractor) ExtractPodSpec(obj runtime.Object) (*metav1.ObjectMeta, *corev1.PodSpec, error) {
41+
if s.sccAdmission == nil {
42+
return s.delegate.ExtractPodSpec(obj)
43+
}
44+
45+
switch obj := obj.(type) {
46+
case *corev1.Pod:
47+
return s.delegate.ExtractPodSpec(obj)
48+
}
49+
50+
podTemplateMeta, originalPodSpec, err := s.delegate.ExtractPodSpec(obj)
51+
if err != nil {
52+
return podTemplateMeta, originalPodSpec, err
53+
}
54+
if originalPodSpec == nil {
55+
return nil, nil, nil
56+
}
57+
objectMeta, err := meta.Accessor(obj)
58+
if err != nil {
59+
return podTemplateMeta, originalPodSpec, fmt.Errorf("unable to get metadata for SCC mutation: %w", err)
60+
}
61+
62+
pod := &corev1.Pod{
63+
ObjectMeta: *podTemplateMeta.DeepCopy(),
64+
Spec: *originalPodSpec.DeepCopy(),
65+
}
66+
if len(pod.Namespace) == 0 {
67+
pod.Namespace = objectMeta.GetNamespace()
68+
}
69+
if len(pod.Name) == 0 {
70+
pod.Name = "pod-for-container-named-" + objectMeta.GetName()
71+
}
72+
internalPod := &core.Pod{}
73+
if err := v1.Convert_v1_Pod_To_core_Pod(pod, internalPod, nil); err != nil {
74+
return nil, nil, err
75+
}
76+
77+
admissionAttributes := admission.NewAttributesRecord(
78+
internalPod,
79+
nil,
80+
corev1.SchemeGroupVersion.WithKind("Pod"),
81+
pod.Namespace,
82+
pod.Name,
83+
corev1.SchemeGroupVersion.WithResource("pods"),
84+
"",
85+
admission.Create,
86+
nil,
87+
false,
88+
&user.DefaultInfo{
89+
Name: serviceaccount.MakeUsername(pod.Namespace, pod.Spec.ServiceAccountName),
90+
UID: "",
91+
Groups: append([]string{user.AllAuthenticated}, serviceaccount.MakeGroupNames(pod.Namespace)...),
92+
Extra: nil,
93+
})
94+
if err := s.sccAdmission.Admit(context.Background(), admissionAttributes, nil); err != nil {
95+
// don't fail the request, just warn if SCC will fail
96+
klog.ErrorS(err, "failed to mutate object for PSA using SCC")
97+
utilruntime.HandleError(fmt.Errorf("failed to mutate object for PSA using SCC: %w", err))
98+
// 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.
99+
return podTemplateMeta, originalPodSpec, err
100+
}
101+
102+
if err := v1.Convert_core_Pod_To_v1_Pod(internalPod, pod, nil); err != nil {
103+
return nil, nil, err
104+
}
105+
106+
return podTemplateMeta, &pod.Spec, nil
107+
}

0 commit comments

Comments
 (0)