provider_test.go 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package podsecuritypolicy
  14. import (
  15. "fmt"
  16. "reflect"
  17. "strconv"
  18. "testing"
  19. "github.com/stretchr/testify/assert"
  20. "github.com/stretchr/testify/require"
  21. v1 "k8s.io/api/core/v1"
  22. policy "k8s.io/api/policy/v1beta1"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "k8s.io/apimachinery/pkg/util/diff"
  25. utilfeature "k8s.io/apiserver/pkg/util/feature"
  26. featuregatetesting "k8s.io/component-base/featuregate/testing"
  27. api "k8s.io/kubernetes/pkg/apis/core"
  28. k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
  29. "k8s.io/kubernetes/pkg/features"
  30. "k8s.io/kubernetes/pkg/security/apparmor"
  31. "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
  32. psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
  33. "k8s.io/utils/pointer"
  34. )
  35. const defaultContainerName = "test-c"
  36. func TestMutatePodNonmutating(t *testing.T) {
  37. // Create a pod with a security context that needs filling in
  38. createPod := func() *api.Pod {
  39. return &api.Pod{
  40. Spec: api.PodSpec{
  41. SecurityContext: &api.PodSecurityContext{},
  42. },
  43. }
  44. }
  45. // Create a PSP with strategies that will populate a blank psc
  46. allowPrivilegeEscalation := true
  47. createPSP := func() *policy.PodSecurityPolicy {
  48. return &policy.PodSecurityPolicy{
  49. ObjectMeta: metav1.ObjectMeta{
  50. Name: "psp-sa",
  51. Annotations: map[string]string{
  52. seccomp.AllowedProfilesAnnotationKey: "*",
  53. },
  54. },
  55. Spec: policy.PodSecurityPolicySpec{
  56. AllowPrivilegeEscalation: &allowPrivilegeEscalation,
  57. RunAsUser: policy.RunAsUserStrategyOptions{
  58. Rule: policy.RunAsUserStrategyRunAsAny,
  59. },
  60. RunAsGroup: &policy.RunAsGroupStrategyOptions{
  61. Rule: policy.RunAsGroupStrategyRunAsAny,
  62. },
  63. SELinux: policy.SELinuxStrategyOptions{
  64. Rule: policy.SELinuxStrategyRunAsAny,
  65. },
  66. FSGroup: policy.FSGroupStrategyOptions{
  67. Rule: policy.FSGroupStrategyRunAsAny,
  68. },
  69. SupplementalGroups: policy.SupplementalGroupsStrategyOptions{
  70. Rule: policy.SupplementalGroupsStrategyRunAsAny,
  71. },
  72. },
  73. }
  74. }
  75. pod := createPod()
  76. psp := createPSP()
  77. provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory())
  78. require.NoError(t, err, "unable to create provider")
  79. err = provider.MutatePod(pod)
  80. require.NoError(t, err, "unable to modify pod")
  81. // Creating the provider or the security context should not have mutated the psp or pod
  82. // since all the strategies were permissive
  83. if !reflect.DeepEqual(createPod(), pod) {
  84. diffs := diff.ObjectDiff(createPod(), pod)
  85. t.Errorf("pod was mutated by MutatePod. diff:\n%s", diffs)
  86. }
  87. if !reflect.DeepEqual(createPSP(), psp) {
  88. t.Error("psp was mutated by MutatePod")
  89. }
  90. }
  91. func TestMutateContainerNonmutating(t *testing.T) {
  92. untrue := false
  93. tests := []struct {
  94. security *api.SecurityContext
  95. }{
  96. {nil},
  97. {&api.SecurityContext{RunAsNonRoot: &untrue}},
  98. }
  99. for _, tc := range tests {
  100. // Create a pod with a security context that needs filling in
  101. createPod := func() *api.Pod {
  102. return &api.Pod{
  103. Spec: api.PodSpec{
  104. Containers: []api.Container{{
  105. SecurityContext: tc.security,
  106. }},
  107. },
  108. }
  109. }
  110. // Create a PSP with strategies that will populate a blank security context
  111. allowPrivilegeEscalation := true
  112. createPSP := func() *policy.PodSecurityPolicy {
  113. return &policy.PodSecurityPolicy{
  114. ObjectMeta: metav1.ObjectMeta{
  115. Name: "psp-sa",
  116. Annotations: map[string]string{
  117. seccomp.AllowedProfilesAnnotationKey: "*",
  118. },
  119. },
  120. Spec: policy.PodSecurityPolicySpec{
  121. AllowPrivilegeEscalation: &allowPrivilegeEscalation,
  122. RunAsUser: policy.RunAsUserStrategyOptions{
  123. Rule: policy.RunAsUserStrategyRunAsAny,
  124. },
  125. RunAsGroup: &policy.RunAsGroupStrategyOptions{
  126. Rule: policy.RunAsGroupStrategyRunAsAny,
  127. },
  128. SELinux: policy.SELinuxStrategyOptions{
  129. Rule: policy.SELinuxStrategyRunAsAny,
  130. },
  131. FSGroup: policy.FSGroupStrategyOptions{
  132. Rule: policy.FSGroupStrategyRunAsAny,
  133. },
  134. SupplementalGroups: policy.SupplementalGroupsStrategyOptions{
  135. Rule: policy.SupplementalGroupsStrategyRunAsAny,
  136. },
  137. },
  138. }
  139. }
  140. pod := createPod()
  141. psp := createPSP()
  142. provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory())
  143. require.NoError(t, err, "unable to create provider")
  144. err = provider.MutatePod(pod)
  145. require.NoError(t, err, "unable to modify pod")
  146. // Creating the provider or the security context should not have mutated the psp or pod
  147. // since all the strategies were permissive
  148. if !reflect.DeepEqual(createPod(), pod) {
  149. diffs := diff.ObjectDiff(createPod(), pod)
  150. t.Errorf("pod was mutated. diff:\n%s", diffs)
  151. }
  152. if !reflect.DeepEqual(createPSP(), psp) {
  153. t.Error("psp was mutated")
  154. }
  155. }
  156. }
  157. func TestValidatePodFailures(t *testing.T) {
  158. defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
  159. failHostNetworkPod := defaultPod()
  160. failHostNetworkPod.Spec.SecurityContext.HostNetwork = true
  161. failHostPIDPod := defaultPod()
  162. failHostPIDPod.Spec.SecurityContext.HostPID = true
  163. failHostIPCPod := defaultPod()
  164. failHostIPCPod.Spec.SecurityContext.HostIPC = true
  165. failSupplementalGroupPod := defaultPod()
  166. failSupplementalGroupPod.Spec.SecurityContext.SupplementalGroups = []int64{999}
  167. failSupplementalGroupMustPSP := defaultPSP()
  168. failSupplementalGroupMustPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{
  169. Rule: policy.SupplementalGroupsStrategyMustRunAs,
  170. Ranges: []policy.IDRange{
  171. {Min: 1, Max: 1},
  172. },
  173. }
  174. failSupplementalGroupMayPSP := defaultPSP()
  175. failSupplementalGroupMayPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{
  176. Rule: policy.SupplementalGroupsStrategyMayRunAs,
  177. Ranges: []policy.IDRange{
  178. {Min: 50, Max: 50},
  179. {Min: 55, Max: 998},
  180. {Min: 1000, Max: 1000},
  181. },
  182. }
  183. failFSGroupPod := defaultPod()
  184. fsGroup := int64(999)
  185. failFSGroupPod.Spec.SecurityContext.FSGroup = &fsGroup
  186. failFSGroupMustPSP := defaultPSP()
  187. failFSGroupMustPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{
  188. Rule: policy.FSGroupStrategyMustRunAs,
  189. Ranges: []policy.IDRange{
  190. {Min: 1, Max: 1},
  191. },
  192. }
  193. failFSGroupMayPSP := defaultPSP()
  194. failFSGroupMayPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{
  195. Rule: policy.FSGroupStrategyMayRunAs,
  196. Ranges: []policy.IDRange{
  197. {Min: 10, Max: 20},
  198. {Min: 1000, Max: 1001},
  199. },
  200. }
  201. failNilSELinuxPod := defaultPod()
  202. failSELinuxPSP := defaultPSP()
  203. failSELinuxPSP.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs
  204. failSELinuxPSP.Spec.SELinux.SELinuxOptions = &v1.SELinuxOptions{
  205. Level: "foo",
  206. }
  207. failInvalidSELinuxPod := defaultPod()
  208. failInvalidSELinuxPod.Spec.SecurityContext.SELinuxOptions = &api.SELinuxOptions{
  209. Level: "bar",
  210. }
  211. failHostDirPod := defaultPod()
  212. failHostDirPod.Spec.Volumes = []api.Volume{
  213. {
  214. Name: "bad volume",
  215. VolumeSource: api.VolumeSource{
  216. HostPath: &api.HostPathVolumeSource{},
  217. },
  218. },
  219. }
  220. failHostPathDirPod := defaultPod()
  221. failHostPathDirPod.Spec.Volumes = []api.Volume{
  222. {
  223. Name: "bad volume",
  224. VolumeSource: api.VolumeSource{
  225. HostPath: &api.HostPathVolumeSource{
  226. Path: "/fail",
  227. },
  228. },
  229. },
  230. }
  231. failHostPathDirPSP := defaultPSP()
  232. failHostPathDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath}
  233. failHostPathDirPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{
  234. {PathPrefix: "/foo/bar"},
  235. }
  236. failHostPathReadOnlyPod := defaultPod()
  237. failHostPathReadOnlyPod.Spec.Containers[0].VolumeMounts = []api.VolumeMount{
  238. {
  239. Name: "bad volume",
  240. ReadOnly: false,
  241. },
  242. }
  243. failHostPathReadOnlyPod.Spec.Volumes = []api.Volume{
  244. {
  245. Name: "bad volume",
  246. VolumeSource: api.VolumeSource{
  247. HostPath: &api.HostPathVolumeSource{
  248. Path: "/foo",
  249. },
  250. },
  251. },
  252. }
  253. failHostPathReadOnlyPSP := defaultPSP()
  254. failHostPathReadOnlyPSP.Spec.Volumes = []policy.FSType{policy.HostPath}
  255. failHostPathReadOnlyPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{
  256. {
  257. PathPrefix: "/foo",
  258. ReadOnly: true,
  259. },
  260. }
  261. failSysctlDisallowedPSP := defaultPSP()
  262. failSysctlDisallowedPSP.Spec.ForbiddenSysctls = []string{"kernel.shm_rmid_forced"}
  263. failNoSafeSysctlAllowedPSP := defaultPSP()
  264. failNoSafeSysctlAllowedPSP.Spec.ForbiddenSysctls = []string{"*"}
  265. failAllUnsafeSysctlsPSP := defaultPSP()
  266. failAllUnsafeSysctlsPSP.Spec.AllowedUnsafeSysctls = []string{}
  267. failSafeSysctlKernelPod := defaultPod()
  268. failSafeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{
  269. Sysctls: []api.Sysctl{
  270. {
  271. Name: "kernel.shm_rmid_forced",
  272. Value: "1",
  273. },
  274. },
  275. }
  276. failUnsafeSysctlPod := defaultPod()
  277. failUnsafeSysctlPod.Spec.SecurityContext = &api.PodSecurityContext{
  278. Sysctls: []api.Sysctl{
  279. {
  280. Name: "kernel.sem",
  281. Value: "32000",
  282. },
  283. },
  284. }
  285. failSeccompProfilePod := defaultPod()
  286. failSeccompProfilePod.Annotations = map[string]string{api.SeccompPodAnnotationKey: "foo"}
  287. podWithInvalidFlexVolumeDriver := defaultPod()
  288. podWithInvalidFlexVolumeDriver.Spec.Volumes = []api.Volume{
  289. {
  290. Name: "flex-volume",
  291. VolumeSource: api.VolumeSource{
  292. FlexVolume: &api.FlexVolumeSource{
  293. Driver: "example/unknown",
  294. },
  295. },
  296. },
  297. }
  298. failCSIDriverPod := defaultPod()
  299. failCSIDriverPod.Spec.Volumes = []api.Volume{
  300. {
  301. Name: "csi volume pod",
  302. VolumeSource: api.VolumeSource{
  303. CSI: &api.CSIVolumeSource{
  304. Driver: "csi.driver.foo",
  305. },
  306. },
  307. },
  308. }
  309. errorCases := map[string]struct {
  310. pod *api.Pod
  311. psp *policy.PodSecurityPolicy
  312. expectedError string
  313. }{
  314. "failHostNetwork": {
  315. pod: failHostNetworkPod,
  316. psp: defaultPSP(),
  317. expectedError: "Host network is not allowed to be used",
  318. },
  319. "failHostPID": {
  320. pod: failHostPIDPod,
  321. psp: defaultPSP(),
  322. expectedError: "Host PID is not allowed to be used",
  323. },
  324. "failHostIPC": {
  325. pod: failHostIPCPod,
  326. psp: defaultPSP(),
  327. expectedError: "Host IPC is not allowed to be used",
  328. },
  329. "failSupplementalGroupOutOfMustRange": {
  330. pod: failSupplementalGroupPod,
  331. psp: failSupplementalGroupMustPSP,
  332. expectedError: "group 999 must be in the ranges: [{1 1}]",
  333. },
  334. "failSupplementalGroupOutOfMayRange": {
  335. pod: failSupplementalGroupPod,
  336. psp: failSupplementalGroupMayPSP,
  337. expectedError: "group 999 must be in the ranges: [{50 50} {55 998} {1000 1000}]",
  338. },
  339. "failSupplementalGroupMustEmpty": {
  340. pod: defaultPod(),
  341. psp: failSupplementalGroupMustPSP,
  342. expectedError: "unable to validate empty groups against required ranges",
  343. },
  344. "failFSGroupOutOfMustRange": {
  345. pod: failFSGroupPod,
  346. psp: failFSGroupMustPSP,
  347. expectedError: "group 999 must be in the ranges: [{1 1}]",
  348. },
  349. "failFSGroupOutOfMayRange": {
  350. pod: failFSGroupPod,
  351. psp: failFSGroupMayPSP,
  352. expectedError: "group 999 must be in the ranges: [{10 20} {1000 1001}]",
  353. },
  354. "failFSGroupMustEmpty": {
  355. pod: defaultPod(),
  356. psp: failFSGroupMustPSP,
  357. expectedError: "unable to validate empty groups against required ranges",
  358. },
  359. "failNilSELinux": {
  360. pod: failNilSELinuxPod,
  361. psp: failSELinuxPSP,
  362. expectedError: "seLinuxOptions: Required",
  363. },
  364. "failInvalidSELinux": {
  365. pod: failInvalidSELinuxPod,
  366. psp: failSELinuxPSP,
  367. expectedError: "seLinuxOptions.level: Invalid value",
  368. },
  369. "failHostDirPSP": {
  370. pod: failHostDirPod,
  371. psp: defaultPSP(),
  372. expectedError: "hostPath volumes are not allowed to be used",
  373. },
  374. "failHostPathDirPSP": {
  375. pod: failHostPathDirPod,
  376. psp: failHostPathDirPSP,
  377. expectedError: "is not allowed to be used",
  378. },
  379. "failHostPathReadOnlyPSP": {
  380. pod: failHostPathReadOnlyPod,
  381. psp: failHostPathReadOnlyPSP,
  382. expectedError: "must be read-only",
  383. },
  384. "failSafeSysctlKernelPod with failNoSafeSysctlAllowedPSP": {
  385. pod: failSafeSysctlKernelPod,
  386. psp: failNoSafeSysctlAllowedPSP,
  387. expectedError: "sysctl \"kernel.shm_rmid_forced\" is not allowed",
  388. },
  389. "failSafeSysctlKernelPod with failSysctlDisallowedPSP": {
  390. pod: failSafeSysctlKernelPod,
  391. psp: failSysctlDisallowedPSP,
  392. expectedError: "sysctl \"kernel.shm_rmid_forced\" is not allowed",
  393. },
  394. "failUnsafeSysctlPod with failAllUnsafeSysctlsPSP": {
  395. pod: failUnsafeSysctlPod,
  396. psp: failAllUnsafeSysctlsPSP,
  397. expectedError: "unsafe sysctl \"kernel.sem\" is not allowed",
  398. },
  399. "failInvalidSeccomp": {
  400. pod: failSeccompProfilePod,
  401. psp: defaultPSP(),
  402. expectedError: "Forbidden: seccomp may not be set",
  403. },
  404. "fail pod with disallowed flexVolume when flex volumes are allowed": {
  405. pod: podWithInvalidFlexVolumeDriver,
  406. psp: allowFlexVolumesPSP(false, false),
  407. expectedError: "Flexvolume driver is not allowed to be used",
  408. },
  409. "fail pod with disallowed flexVolume when all volumes are allowed": {
  410. pod: podWithInvalidFlexVolumeDriver,
  411. psp: allowFlexVolumesPSP(false, true),
  412. expectedError: "Flexvolume driver is not allowed to be used",
  413. },
  414. "CSI policy using disallowed CDI driver": {
  415. pod: failCSIDriverPod,
  416. psp: func() *policy.PodSecurityPolicy {
  417. psp := defaultPSP()
  418. psp.Spec.Volumes = []policy.FSType{policy.CSI}
  419. psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "csi.driver.disallowed"}}
  420. return psp
  421. }(),
  422. expectedError: "Inline CSI driver is not allowed to be used",
  423. },
  424. "Using inline CSI driver with no policy specified": {
  425. pod: failCSIDriverPod,
  426. psp: func() *policy.PodSecurityPolicy {
  427. psp := defaultPSP()
  428. psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "csi.driver.foo"}}
  429. return psp
  430. }(),
  431. expectedError: "csi volumes are not allowed to be used",
  432. },
  433. "policy.All using disallowed CDI driver": {
  434. pod: failCSIDriverPod,
  435. psp: func() *policy.PodSecurityPolicy {
  436. psp := defaultPSP()
  437. psp.Spec.Volumes = []policy.FSType{policy.All}
  438. psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "csi.driver.disallowed"}}
  439. return psp
  440. }(),
  441. expectedError: "Inline CSI driver is not allowed to be used",
  442. },
  443. "CSI inline volumes without proper policy set": {
  444. pod: failCSIDriverPod,
  445. psp: defaultPSP(),
  446. expectedError: "csi volumes are not allowed to be used",
  447. },
  448. }
  449. for name, test := range errorCases {
  450. t.Run(name, func(t *testing.T) {
  451. provider, err := NewSimpleProvider(test.psp, "namespace", NewSimpleStrategyFactory())
  452. require.NoError(t, err, "unable to create provider")
  453. errs := provider.ValidatePod(test.pod)
  454. require.NotEmpty(t, errs, "expected validation failure but did not receive errors")
  455. assert.Contains(t, errs[0].Error(), test.expectedError, "received unexpected error")
  456. })
  457. }
  458. }
  459. func allowFlexVolumesPSP(allowAllFlexVolumes, allowAllVolumes bool) *policy.PodSecurityPolicy {
  460. psp := defaultPSP()
  461. allowedVolumes := []policy.AllowedFlexVolume{
  462. {Driver: "example/foo"},
  463. {Driver: "example/bar"},
  464. }
  465. if allowAllFlexVolumes {
  466. allowedVolumes = []policy.AllowedFlexVolume{}
  467. }
  468. allowedVolumeType := policy.FlexVolume
  469. if allowAllVolumes {
  470. allowedVolumeType = policy.All
  471. }
  472. psp.Spec.AllowedFlexVolumes = allowedVolumes
  473. psp.Spec.Volumes = []policy.FSType{allowedVolumeType}
  474. return psp
  475. }
  476. func TestValidateContainerFailures(t *testing.T) {
  477. // fail user strategy
  478. failUserPSP := defaultPSP()
  479. uid := int64(999)
  480. badUID := int64(1)
  481. failUserPSP.Spec.RunAsUser = policy.RunAsUserStrategyOptions{
  482. Rule: policy.RunAsUserStrategyMustRunAs,
  483. Ranges: []policy.IDRange{{Min: uid, Max: uid}},
  484. }
  485. failUserPod := defaultPod()
  486. failUserPod.Spec.Containers[0].SecurityContext.RunAsUser = &badUID
  487. // fail selinux strategy
  488. failSELinuxPSP := defaultPSP()
  489. failSELinuxPSP.Spec.SELinux = policy.SELinuxStrategyOptions{
  490. Rule: policy.SELinuxStrategyMustRunAs,
  491. SELinuxOptions: &v1.SELinuxOptions{
  492. Level: "foo",
  493. },
  494. }
  495. failSELinuxPod := defaultPod()
  496. failSELinuxPod.Spec.SecurityContext.SELinuxOptions = &api.SELinuxOptions{Level: "foo"}
  497. failSELinuxPod.Spec.Containers[0].SecurityContext.SELinuxOptions = &api.SELinuxOptions{
  498. Level: "bar",
  499. }
  500. failNilAppArmorPod := defaultPod()
  501. v1FailInvalidAppArmorPod := defaultV1Pod()
  502. apparmor.SetProfileName(v1FailInvalidAppArmorPod, defaultContainerName, apparmor.ProfileNamePrefix+"foo")
  503. failInvalidAppArmorPod := &api.Pod{}
  504. k8s_api_v1.Convert_v1_Pod_To_core_Pod(v1FailInvalidAppArmorPod, failInvalidAppArmorPod, nil)
  505. failAppArmorPSP := defaultPSP()
  506. failAppArmorPSP.Annotations = map[string]string{
  507. apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
  508. }
  509. failPrivPod := defaultPod()
  510. var priv bool = true
  511. failPrivPod.Spec.Containers[0].SecurityContext.Privileged = &priv
  512. failProcMountPod := defaultPod()
  513. failProcMountPod.Spec.Containers[0].SecurityContext.ProcMount = new(api.ProcMountType)
  514. *failProcMountPod.Spec.Containers[0].SecurityContext.ProcMount = api.UnmaskedProcMount
  515. failCapsPod := defaultPod()
  516. failCapsPod.Spec.Containers[0].SecurityContext.Capabilities = &api.Capabilities{
  517. Add: []api.Capability{"foo"},
  518. }
  519. failHostPortPod := defaultPod()
  520. failHostPortPod.Spec.Containers[0].Ports = []api.ContainerPort{{HostPort: 1}}
  521. readOnlyRootFSPSP := defaultPSP()
  522. readOnlyRootFSPSP.Spec.ReadOnlyRootFilesystem = true
  523. readOnlyRootFSPodFalse := defaultPod()
  524. readOnlyRootFS := false
  525. readOnlyRootFSPodFalse.Spec.Containers[0].SecurityContext.ReadOnlyRootFilesystem = &readOnlyRootFS
  526. failSeccompPod := defaultPod()
  527. failSeccompPod.Annotations = map[string]string{
  528. api.SeccompContainerAnnotationKeyPrefix + failSeccompPod.Spec.Containers[0].Name: "foo",
  529. }
  530. failSeccompPodInheritPodAnnotation := defaultPod()
  531. failSeccompPodInheritPodAnnotation.Annotations = map[string]string{
  532. api.SeccompPodAnnotationKey: "foo",
  533. }
  534. errorCases := map[string]struct {
  535. pod *api.Pod
  536. psp *policy.PodSecurityPolicy
  537. expectedError string
  538. }{
  539. "failUserPSP": {
  540. pod: failUserPod,
  541. psp: failUserPSP,
  542. expectedError: "runAsUser: Invalid value",
  543. },
  544. "failSELinuxPSP": {
  545. pod: failSELinuxPod,
  546. psp: failSELinuxPSP,
  547. expectedError: "seLinuxOptions.level: Invalid value",
  548. },
  549. "failNilAppArmor": {
  550. pod: failNilAppArmorPod,
  551. psp: failAppArmorPSP,
  552. expectedError: "AppArmor profile must be set",
  553. },
  554. "failInvalidAppArmor": {
  555. pod: failInvalidAppArmorPod,
  556. psp: failAppArmorPSP,
  557. expectedError: "localhost/foo is not an allowed profile. Allowed values: \"runtime/default\"",
  558. },
  559. "failPrivPSP": {
  560. pod: failPrivPod,
  561. psp: defaultPSP(),
  562. expectedError: "Privileged containers are not allowed",
  563. },
  564. "failProcMountPSP": {
  565. pod: failProcMountPod,
  566. psp: defaultPSP(),
  567. expectedError: "ProcMountType is not allowed",
  568. },
  569. "failCapsPSP": {
  570. pod: failCapsPod,
  571. psp: defaultPSP(),
  572. expectedError: "capability may not be added",
  573. },
  574. "failHostPortPSP": {
  575. pod: failHostPortPod,
  576. psp: defaultPSP(),
  577. expectedError: "Host port 1 is not allowed to be used. Allowed ports: []",
  578. },
  579. "failReadOnlyRootFS - nil": {
  580. pod: defaultPod(),
  581. psp: readOnlyRootFSPSP,
  582. expectedError: "ReadOnlyRootFilesystem may not be nil and must be set to true",
  583. },
  584. "failReadOnlyRootFS - false": {
  585. pod: readOnlyRootFSPodFalse,
  586. psp: readOnlyRootFSPSP,
  587. expectedError: "ReadOnlyRootFilesystem must be set to true",
  588. },
  589. "failSeccompContainerAnnotation": {
  590. pod: failSeccompPod,
  591. psp: defaultPSP(),
  592. expectedError: "Forbidden: seccomp may not be set",
  593. },
  594. "failSeccompContainerPodAnnotation": {
  595. pod: failSeccompPodInheritPodAnnotation,
  596. psp: defaultPSP(),
  597. expectedError: "Forbidden: seccomp may not be set",
  598. },
  599. }
  600. for name, test := range errorCases {
  601. t.Run(name, func(t *testing.T) {
  602. provider, err := NewSimpleProvider(test.psp, "namespace", NewSimpleStrategyFactory())
  603. require.NoError(t, err, "unable to create provider")
  604. errs := provider.ValidatePod(test.pod)
  605. require.NotEmpty(t, errs, "expected validation failure but did not receive errors")
  606. assert.Contains(t, errs[0].Error(), test.expectedError, "unexpected error")
  607. })
  608. }
  609. }
  610. func TestValidatePodSuccess(t *testing.T) {
  611. defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
  612. hostNetworkPSP := defaultPSP()
  613. hostNetworkPSP.Spec.HostNetwork = true
  614. hostNetworkPod := defaultPod()
  615. hostNetworkPod.Spec.SecurityContext.HostNetwork = true
  616. hostPIDPSP := defaultPSP()
  617. hostPIDPSP.Spec.HostPID = true
  618. hostPIDPod := defaultPod()
  619. hostPIDPod.Spec.SecurityContext.HostPID = true
  620. hostIPCPSP := defaultPSP()
  621. hostIPCPSP.Spec.HostIPC = true
  622. hostIPCPod := defaultPod()
  623. hostIPCPod.Spec.SecurityContext.HostIPC = true
  624. supGroupMustPSP := defaultPSP()
  625. supGroupMustPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{
  626. Rule: policy.SupplementalGroupsStrategyMustRunAs,
  627. Ranges: []policy.IDRange{
  628. {Min: 1, Max: 5},
  629. },
  630. }
  631. supGroupMayPSP := defaultPSP()
  632. supGroupMayPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{
  633. Rule: policy.SupplementalGroupsStrategyMayRunAs,
  634. Ranges: []policy.IDRange{
  635. {Min: 1, Max: 5},
  636. },
  637. }
  638. supGroupPod := defaultPod()
  639. supGroupPod.Spec.SecurityContext.SupplementalGroups = []int64{3}
  640. fsGroupMustPSP := defaultPSP()
  641. fsGroupMustPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{
  642. Rule: policy.FSGroupStrategyMustRunAs,
  643. Ranges: []policy.IDRange{
  644. {Min: 1, Max: 5},
  645. },
  646. }
  647. fsGroupMayPSP := defaultPSP()
  648. fsGroupMayPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{
  649. Rule: policy.FSGroupStrategyMayRunAs,
  650. Ranges: []policy.IDRange{
  651. {Min: 1, Max: 5},
  652. },
  653. }
  654. fsGroupPod := defaultPod()
  655. fsGroup := int64(3)
  656. fsGroupPod.Spec.SecurityContext.FSGroup = &fsGroup
  657. seLinuxPod := defaultPod()
  658. seLinuxPod.Spec.SecurityContext.SELinuxOptions = &api.SELinuxOptions{
  659. User: "user",
  660. Role: "role",
  661. Type: "type",
  662. Level: "level",
  663. }
  664. seLinuxPSP := defaultPSP()
  665. seLinuxPSP.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs
  666. seLinuxPSP.Spec.SELinux.SELinuxOptions = &v1.SELinuxOptions{
  667. User: "user",
  668. Role: "role",
  669. Type: "type",
  670. Level: "level",
  671. }
  672. hostPathDirPodVolumeMounts := []api.VolumeMount{
  673. {
  674. Name: "writeable /foo/bar",
  675. ReadOnly: false,
  676. },
  677. {
  678. Name: "read only /foo/bar/baz",
  679. ReadOnly: true,
  680. },
  681. {
  682. Name: "parent read only volume",
  683. ReadOnly: true,
  684. },
  685. {
  686. Name: "read only child volume",
  687. ReadOnly: true,
  688. },
  689. }
  690. hostPathDirPod := defaultPod()
  691. hostPathDirPod.Spec.InitContainers = []api.Container{
  692. {
  693. Name: defaultContainerName,
  694. VolumeMounts: hostPathDirPodVolumeMounts,
  695. },
  696. }
  697. hostPathDirPod.Spec.Containers[0].VolumeMounts = hostPathDirPodVolumeMounts
  698. hostPathDirPod.Spec.Volumes = []api.Volume{
  699. {
  700. Name: "writeable /foo/bar",
  701. VolumeSource: api.VolumeSource{
  702. HostPath: &api.HostPathVolumeSource{
  703. Path: "/foo/bar",
  704. },
  705. },
  706. },
  707. {
  708. Name: "read only /foo/bar/baz",
  709. VolumeSource: api.VolumeSource{
  710. HostPath: &api.HostPathVolumeSource{
  711. Path: "/foo/bar/baz",
  712. },
  713. },
  714. },
  715. {
  716. Name: "parent read only volume",
  717. VolumeSource: api.VolumeSource{
  718. HostPath: &api.HostPathVolumeSource{
  719. Path: "/foo/",
  720. },
  721. },
  722. },
  723. {
  724. Name: "read only child volume",
  725. VolumeSource: api.VolumeSource{
  726. HostPath: &api.HostPathVolumeSource{
  727. Path: "/foo/readonly/child",
  728. },
  729. },
  730. },
  731. }
  732. hostPathDirPSP := defaultPSP()
  733. hostPathDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath}
  734. hostPathDirPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{
  735. // overlapping test case where child is different than parent directory.
  736. {PathPrefix: "/foo/bar/baz", ReadOnly: true},
  737. {PathPrefix: "/foo", ReadOnly: true},
  738. {PathPrefix: "/foo/bar", ReadOnly: false},
  739. }
  740. hostPathDirAsterisksPSP := defaultPSP()
  741. hostPathDirAsterisksPSP.Spec.Volumes = []policy.FSType{policy.All}
  742. hostPathDirAsterisksPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{
  743. {PathPrefix: "/foo"},
  744. }
  745. sysctlAllowAllPSP := defaultPSP()
  746. sysctlAllowAllPSP.Spec.ForbiddenSysctls = []string{}
  747. sysctlAllowAllPSP.Spec.AllowedUnsafeSysctls = []string{"*"}
  748. safeSysctlKernelPod := defaultPod()
  749. safeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{
  750. Sysctls: []api.Sysctl{
  751. {
  752. Name: "kernel.shm_rmid_forced",
  753. Value: "1",
  754. },
  755. },
  756. }
  757. unsafeSysctlKernelPod := defaultPod()
  758. unsafeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{
  759. Sysctls: []api.Sysctl{
  760. {
  761. Name: "kernel.sem",
  762. Value: "32000",
  763. },
  764. },
  765. }
  766. seccompPSP := defaultPSP()
  767. seccompPSP.Annotations = map[string]string{
  768. seccomp.AllowedProfilesAnnotationKey: "foo",
  769. }
  770. seccompPod := defaultPod()
  771. seccompPod.Annotations = map[string]string{
  772. api.SeccompPodAnnotationKey: "foo",
  773. }
  774. flexVolumePod := defaultPod()
  775. flexVolumePod.Spec.Volumes = []api.Volume{
  776. {
  777. Name: "flex-volume",
  778. VolumeSource: api.VolumeSource{
  779. FlexVolume: &api.FlexVolumeSource{
  780. Driver: "example/bar",
  781. },
  782. },
  783. },
  784. }
  785. csiDriverPod := defaultPod()
  786. csiDriverPod.Spec.Volumes = []api.Volume{
  787. {
  788. Name: "csi inline driver",
  789. VolumeSource: api.VolumeSource{
  790. CSI: &api.CSIVolumeSource{
  791. Driver: "foo",
  792. },
  793. },
  794. },
  795. {
  796. Name: "csi inline driver 2",
  797. VolumeSource: api.VolumeSource{
  798. CSI: &api.CSIVolumeSource{
  799. Driver: "bar",
  800. },
  801. },
  802. },
  803. {
  804. Name: "csi inline driver 3",
  805. VolumeSource: api.VolumeSource{
  806. CSI: &api.CSIVolumeSource{
  807. Driver: "baz",
  808. },
  809. },
  810. },
  811. }
  812. successCases := map[string]struct {
  813. pod *api.Pod
  814. psp *policy.PodSecurityPolicy
  815. }{
  816. "pass hostNetwork validating PSP": {
  817. pod: hostNetworkPod,
  818. psp: hostNetworkPSP,
  819. },
  820. "pass hostPID validating PSP": {
  821. pod: hostPIDPod,
  822. psp: hostPIDPSP,
  823. },
  824. "pass hostIPC validating PSP": {
  825. pod: hostIPCPod,
  826. psp: hostIPCPSP,
  827. },
  828. "pass required supplemental group validating PSP": {
  829. pod: supGroupPod,
  830. psp: supGroupMustPSP,
  831. },
  832. "pass optional supplemental group validation PSP": {
  833. pod: supGroupPod,
  834. psp: supGroupMayPSP,
  835. },
  836. "pass optional supplemental group validation PSP - no pod group specified": {
  837. pod: defaultPod(),
  838. psp: supGroupMayPSP,
  839. },
  840. "pass required fs group validating PSP": {
  841. pod: fsGroupPod,
  842. psp: fsGroupMustPSP,
  843. },
  844. "pass optional fs group validating PSP": {
  845. pod: fsGroupPod,
  846. psp: fsGroupMayPSP,
  847. },
  848. "pass optional fs group validating PSP - no pod group specified": {
  849. pod: defaultPod(),
  850. psp: fsGroupMayPSP,
  851. },
  852. "pass selinux validating PSP": {
  853. pod: seLinuxPod,
  854. psp: seLinuxPSP,
  855. },
  856. "pass sysctl specific profile with safe kernel sysctl": {
  857. pod: safeSysctlKernelPod,
  858. psp: sysctlAllowAllPSP,
  859. },
  860. "pass sysctl specific profile with unsafe kernel sysctl": {
  861. pod: unsafeSysctlKernelPod,
  862. psp: sysctlAllowAllPSP,
  863. },
  864. "pass hostDir allowed directory validating PSP": {
  865. pod: hostPathDirPod,
  866. psp: hostPathDirPSP,
  867. },
  868. "pass hostDir all volumes allowed validating PSP": {
  869. pod: hostPathDirPod,
  870. psp: hostPathDirAsterisksPSP,
  871. },
  872. "pass seccomp validating PSP": {
  873. pod: seccompPod,
  874. psp: seccompPSP,
  875. },
  876. "flex volume driver in a whitelist (all volumes are allowed)": {
  877. pod: flexVolumePod,
  878. psp: allowFlexVolumesPSP(false, true),
  879. },
  880. "flex volume driver with empty whitelist (all volumes are allowed)": {
  881. pod: flexVolumePod,
  882. psp: allowFlexVolumesPSP(true, true),
  883. },
  884. "flex volume driver in a whitelist (only flex volumes are allowed)": {
  885. pod: flexVolumePod,
  886. psp: allowFlexVolumesPSP(false, false),
  887. },
  888. "flex volume driver with empty whitelist (only flex volumes volumes are allowed)": {
  889. pod: flexVolumePod,
  890. psp: allowFlexVolumesPSP(true, false),
  891. },
  892. "CSI policy with no CSI volumes used": {
  893. pod: defaultPod(),
  894. psp: func() *policy.PodSecurityPolicy {
  895. psp := defaultPSP()
  896. psp.Spec.Volumes = []policy.FSType{policy.CSI}
  897. psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "foo"}, {Name: "bar"}, {Name: "baz"}}
  898. return psp
  899. }(),
  900. },
  901. "CSI policy with CSI inline volumes used": {
  902. pod: csiDriverPod,
  903. psp: func() *policy.PodSecurityPolicy {
  904. psp := defaultPSP()
  905. psp.Spec.Volumes = []policy.FSType{policy.CSI}
  906. psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "foo"}, {Name: "bar"}, {Name: "baz"}}
  907. return psp
  908. }(),
  909. },
  910. "policy.All with CSI inline volumes used": {
  911. pod: csiDriverPod,
  912. psp: func() *policy.PodSecurityPolicy {
  913. psp := defaultPSP()
  914. psp.Spec.Volumes = []policy.FSType{policy.All}
  915. psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "foo"}, {Name: "bar"}, {Name: "baz"}}
  916. return psp
  917. }(),
  918. },
  919. }
  920. for name, test := range successCases {
  921. t.Run(name, func(t *testing.T) {
  922. provider, err := NewSimpleProvider(test.psp, "namespace", NewSimpleStrategyFactory())
  923. require.NoError(t, err, "unable to create provider")
  924. errs := provider.ValidatePod(test.pod)
  925. assert.Empty(t, errs, "expected validation pass but received errors")
  926. })
  927. }
  928. }
  929. func TestValidateContainerSuccess(t *testing.T) {
  930. // success user strategy
  931. userPSP := defaultPSP()
  932. uid := int64(999)
  933. userPSP.Spec.RunAsUser = policy.RunAsUserStrategyOptions{
  934. Rule: policy.RunAsUserStrategyMustRunAs,
  935. Ranges: []policy.IDRange{{Min: uid, Max: uid}},
  936. }
  937. userPod := defaultPod()
  938. userPod.Spec.Containers[0].SecurityContext.RunAsUser = &uid
  939. // success selinux strategy
  940. seLinuxPSP := defaultPSP()
  941. seLinuxPSP.Spec.SELinux = policy.SELinuxStrategyOptions{
  942. Rule: policy.SELinuxStrategyMustRunAs,
  943. SELinuxOptions: &v1.SELinuxOptions{
  944. Level: "foo",
  945. },
  946. }
  947. seLinuxPod := defaultPod()
  948. seLinuxPod.Spec.SecurityContext.SELinuxOptions = &api.SELinuxOptions{Level: "foo"}
  949. seLinuxPod.Spec.Containers[0].SecurityContext.SELinuxOptions = &api.SELinuxOptions{
  950. Level: "foo",
  951. }
  952. appArmorPSP := defaultPSP()
  953. appArmorPSP.Annotations = map[string]string{
  954. apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
  955. }
  956. v1AppArmorPod := defaultV1Pod()
  957. apparmor.SetProfileName(v1AppArmorPod, defaultContainerName, apparmor.ProfileRuntimeDefault)
  958. appArmorPod := &api.Pod{}
  959. k8s_api_v1.Convert_v1_Pod_To_core_Pod(v1AppArmorPod, appArmorPod, nil)
  960. privPSP := defaultPSP()
  961. privPSP.Spec.Privileged = true
  962. privPod := defaultPod()
  963. var priv bool = true
  964. privPod.Spec.Containers[0].SecurityContext.Privileged = &priv
  965. capsPSP := defaultPSP()
  966. capsPSP.Spec.AllowedCapabilities = []v1.Capability{"foo"}
  967. capsPod := defaultPod()
  968. capsPod.Spec.Containers[0].SecurityContext.Capabilities = &api.Capabilities{
  969. Add: []api.Capability{"foo"},
  970. }
  971. // pod should be able to request caps that are in the required set even if not specified in the allowed set
  972. requiredCapsPSP := defaultPSP()
  973. requiredCapsPSP.Spec.DefaultAddCapabilities = []v1.Capability{"foo"}
  974. requiredCapsPod := defaultPod()
  975. requiredCapsPod.Spec.Containers[0].SecurityContext.Capabilities = &api.Capabilities{
  976. Add: []api.Capability{"foo"},
  977. }
  978. hostDirPSP := defaultPSP()
  979. hostDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath}
  980. hostDirPod := defaultPod()
  981. hostDirPod.Spec.Volumes = []api.Volume{
  982. {
  983. Name: "bad volume",
  984. VolumeSource: api.VolumeSource{
  985. HostPath: &api.HostPathVolumeSource{},
  986. },
  987. },
  988. }
  989. hostPortPSP := defaultPSP()
  990. hostPortPSP.Spec.HostPorts = []policy.HostPortRange{{Min: 1, Max: 1}}
  991. hostPortPod := defaultPod()
  992. hostPortPod.Spec.Containers[0].Ports = []api.ContainerPort{{HostPort: 1}}
  993. readOnlyRootFSPodFalse := defaultPod()
  994. readOnlyRootFSFalse := false
  995. readOnlyRootFSPodFalse.Spec.Containers[0].SecurityContext.ReadOnlyRootFilesystem = &readOnlyRootFSFalse
  996. readOnlyRootFSPodTrue := defaultPod()
  997. readOnlyRootFSTrue := true
  998. readOnlyRootFSPodTrue.Spec.Containers[0].SecurityContext.ReadOnlyRootFilesystem = &readOnlyRootFSTrue
  999. seccompPSP := defaultPSP()
  1000. seccompPSP.Annotations = map[string]string{
  1001. seccomp.AllowedProfilesAnnotationKey: "foo",
  1002. }
  1003. seccompPod := defaultPod()
  1004. seccompPod.Annotations = map[string]string{
  1005. api.SeccompPodAnnotationKey: "foo",
  1006. api.SeccompContainerAnnotationKeyPrefix + seccompPod.Spec.Containers[0].Name: "foo",
  1007. }
  1008. seccompPodInherit := defaultPod()
  1009. seccompPodInherit.Annotations = map[string]string{
  1010. api.SeccompPodAnnotationKey: "foo",
  1011. }
  1012. successCases := map[string]struct {
  1013. pod *api.Pod
  1014. psp *policy.PodSecurityPolicy
  1015. }{
  1016. "pass user must run as PSP": {
  1017. pod: userPod,
  1018. psp: userPSP,
  1019. },
  1020. "pass seLinux must run as PSP": {
  1021. pod: seLinuxPod,
  1022. psp: seLinuxPSP,
  1023. },
  1024. "pass AppArmor allowed profiles": {
  1025. pod: appArmorPod,
  1026. psp: appArmorPSP,
  1027. },
  1028. "pass priv validating PSP": {
  1029. pod: privPod,
  1030. psp: privPSP,
  1031. },
  1032. "pass allowed caps validating PSP": {
  1033. pod: capsPod,
  1034. psp: capsPSP,
  1035. },
  1036. "pass required caps validating PSP": {
  1037. pod: requiredCapsPod,
  1038. psp: requiredCapsPSP,
  1039. },
  1040. "pass hostDir validating PSP": {
  1041. pod: hostDirPod,
  1042. psp: hostDirPSP,
  1043. },
  1044. "pass hostPort validating PSP": {
  1045. pod: hostPortPod,
  1046. psp: hostPortPSP,
  1047. },
  1048. "pass read only root fs - nil": {
  1049. pod: defaultPod(),
  1050. psp: defaultPSP(),
  1051. },
  1052. "pass read only root fs - false": {
  1053. pod: readOnlyRootFSPodFalse,
  1054. psp: defaultPSP(),
  1055. },
  1056. "pass read only root fs - true": {
  1057. pod: readOnlyRootFSPodTrue,
  1058. psp: defaultPSP(),
  1059. },
  1060. "pass seccomp container annotation": {
  1061. pod: seccompPod,
  1062. psp: seccompPSP,
  1063. },
  1064. "pass seccomp inherit pod annotation": {
  1065. pod: seccompPodInherit,
  1066. psp: seccompPSP,
  1067. },
  1068. }
  1069. for name, test := range successCases {
  1070. t.Run(name, func(t *testing.T) {
  1071. provider, err := NewSimpleProvider(test.psp, "namespace", NewSimpleStrategyFactory())
  1072. require.NoError(t, err, "unable to create provider")
  1073. errs := provider.ValidatePod(test.pod)
  1074. assert.Empty(t, errs, "expected validation pass but received errors")
  1075. })
  1076. }
  1077. }
  1078. func TestGenerateContainerSecurityContextReadOnlyRootFS(t *testing.T) {
  1079. truePSP := defaultPSP()
  1080. truePSP.Spec.ReadOnlyRootFilesystem = true
  1081. trueVal := true
  1082. expectTrue := &trueVal
  1083. falseVal := false
  1084. expectFalse := &falseVal
  1085. falsePod := defaultPod()
  1086. falsePod.Spec.Containers[0].SecurityContext.ReadOnlyRootFilesystem = expectFalse
  1087. truePod := defaultPod()
  1088. truePod.Spec.Containers[0].SecurityContext.ReadOnlyRootFilesystem = expectTrue
  1089. tests := map[string]struct {
  1090. pod *api.Pod
  1091. psp *policy.PodSecurityPolicy
  1092. expected *bool
  1093. }{
  1094. "false psp, nil sc": {
  1095. psp: defaultPSP(),
  1096. pod: defaultPod(),
  1097. expected: nil,
  1098. },
  1099. "false psp, false sc": {
  1100. psp: defaultPSP(),
  1101. pod: falsePod,
  1102. expected: expectFalse,
  1103. },
  1104. "false psp, true sc": {
  1105. psp: defaultPSP(),
  1106. pod: truePod,
  1107. expected: expectTrue,
  1108. },
  1109. "true psp, nil sc": {
  1110. psp: truePSP,
  1111. pod: defaultPod(),
  1112. expected: expectTrue,
  1113. },
  1114. "true psp, false sc": {
  1115. psp: truePSP,
  1116. pod: falsePod,
  1117. // expect false even though it defaults to true to ensure it doesn't change set values
  1118. // validation catches the mismatch, not generation
  1119. expected: expectFalse,
  1120. },
  1121. "true psp, true sc": {
  1122. psp: truePSP,
  1123. pod: truePod,
  1124. expected: expectTrue,
  1125. },
  1126. }
  1127. for name, test := range tests {
  1128. t.Run(name, func(t *testing.T) {
  1129. provider, err := NewSimpleProvider(test.psp, "namespace", NewSimpleStrategyFactory())
  1130. require.NoError(t, err, "unable to create provider")
  1131. err = provider.MutatePod(test.pod)
  1132. require.NoError(t, err, "unable to mutate container")
  1133. sc := test.pod.Spec.Containers[0].SecurityContext
  1134. if test.expected == nil {
  1135. assert.Nil(t, sc.ReadOnlyRootFilesystem, "expected a nil ReadOnlyRootFilesystem")
  1136. } else {
  1137. require.NotNil(t, sc.ReadOnlyRootFilesystem, "expected a non nil ReadOnlyRootFilesystem")
  1138. assert.Equal(t, *test.expected, *sc.ReadOnlyRootFilesystem)
  1139. }
  1140. })
  1141. }
  1142. }
  1143. func defaultPSP() *policy.PodSecurityPolicy {
  1144. return defaultNamedPSP("psp-sa")
  1145. }
  1146. func defaultNamedPSP(name string) *policy.PodSecurityPolicy {
  1147. allowPrivilegeEscalation := true
  1148. return &policy.PodSecurityPolicy{
  1149. ObjectMeta: metav1.ObjectMeta{
  1150. Name: name,
  1151. Annotations: map[string]string{},
  1152. },
  1153. Spec: policy.PodSecurityPolicySpec{
  1154. RunAsUser: policy.RunAsUserStrategyOptions{
  1155. Rule: policy.RunAsUserStrategyRunAsAny,
  1156. },
  1157. RunAsGroup: &policy.RunAsGroupStrategyOptions{
  1158. Rule: policy.RunAsGroupStrategyRunAsAny,
  1159. },
  1160. SELinux: policy.SELinuxStrategyOptions{
  1161. Rule: policy.SELinuxStrategyRunAsAny,
  1162. },
  1163. FSGroup: policy.FSGroupStrategyOptions{
  1164. Rule: policy.FSGroupStrategyRunAsAny,
  1165. },
  1166. SupplementalGroups: policy.SupplementalGroupsStrategyOptions{
  1167. Rule: policy.SupplementalGroupsStrategyRunAsAny,
  1168. },
  1169. AllowPrivilegeEscalation: &allowPrivilegeEscalation,
  1170. },
  1171. }
  1172. }
  1173. func defaultPod() *api.Pod {
  1174. var notPriv bool = false
  1175. return &api.Pod{
  1176. ObjectMeta: metav1.ObjectMeta{
  1177. Annotations: map[string]string{},
  1178. },
  1179. Spec: api.PodSpec{
  1180. SecurityContext: &api.PodSecurityContext{
  1181. // fill in for test cases
  1182. },
  1183. Containers: []api.Container{
  1184. {
  1185. Name: defaultContainerName,
  1186. SecurityContext: &api.SecurityContext{
  1187. // expected to be set by defaulting mechanisms
  1188. Privileged: &notPriv,
  1189. // fill in the rest for test cases
  1190. },
  1191. },
  1192. },
  1193. },
  1194. }
  1195. }
  1196. func defaultV1Pod() *v1.Pod {
  1197. var notPriv bool = false
  1198. return &v1.Pod{
  1199. ObjectMeta: metav1.ObjectMeta{
  1200. Annotations: map[string]string{},
  1201. },
  1202. Spec: v1.PodSpec{
  1203. SecurityContext: &v1.PodSecurityContext{
  1204. // fill in for test cases
  1205. },
  1206. Containers: []v1.Container{
  1207. {
  1208. Name: defaultContainerName,
  1209. SecurityContext: &v1.SecurityContext{
  1210. // expected to be set by defaulting mechanisms
  1211. Privileged: &notPriv,
  1212. // fill in the rest for test cases
  1213. },
  1214. },
  1215. },
  1216. },
  1217. }
  1218. }
  1219. // TestValidateAllowedVolumes will test that for every field of VolumeSource we can create
  1220. // a pod with that type of volume and deny it, accept it explicitly, or accept it with
  1221. // the FSTypeAll wildcard.
  1222. func TestValidateAllowedVolumes(t *testing.T) {
  1223. defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
  1224. val := reflect.ValueOf(api.VolumeSource{})
  1225. for i := 0; i < val.NumField(); i++ {
  1226. // reflectively create the volume source
  1227. fieldVal := val.Type().Field(i)
  1228. t.Run(fieldVal.Name, func(t *testing.T) {
  1229. volumeSource := api.VolumeSource{}
  1230. volumeSourceVolume := reflect.New(fieldVal.Type.Elem())
  1231. reflect.ValueOf(&volumeSource).Elem().FieldByName(fieldVal.Name).Set(volumeSourceVolume)
  1232. volume := api.Volume{VolumeSource: volumeSource}
  1233. // sanity check before moving on
  1234. fsType, err := psputil.GetVolumeFSType(volume)
  1235. require.NoError(t, err, "error getting FSType")
  1236. // add the volume to the pod
  1237. pod := defaultPod()
  1238. pod.Spec.Volumes = []api.Volume{volume}
  1239. // create a PSP that allows no volumes
  1240. psp := defaultPSP()
  1241. provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory())
  1242. require.NoError(t, err, "error creating provider")
  1243. // expect a denial for this PSP and test the error message to ensure it's related to the volumesource
  1244. errs := provider.ValidatePod(pod)
  1245. require.Len(t, errs, 1, "expected exactly 1 error")
  1246. assert.Contains(t, errs.ToAggregate().Error(), fmt.Sprintf("%s volumes are not allowed to be used", fsType), "did not find the expected error")
  1247. // now add the fstype directly to the psp and it should validate
  1248. psp.Spec.Volumes = []policy.FSType{fsType}
  1249. errs = provider.ValidatePod(pod)
  1250. assert.Empty(t, errs, "directly allowing volume expected no errors")
  1251. // now change the psp to allow any volumes and the pod should still validate
  1252. psp.Spec.Volumes = []policy.FSType{policy.All}
  1253. errs = provider.ValidatePod(pod)
  1254. assert.Empty(t, errs, "wildcard volume expected no errors")
  1255. })
  1256. }
  1257. }
  1258. func TestAllowPrivilegeEscalation(t *testing.T) {
  1259. ptr := pointer.BoolPtr
  1260. tests := []struct {
  1261. pspAPE bool // PSP AllowPrivilegeEscalation
  1262. pspDAPE *bool // PSP DefaultAllowPrivilegeEscalation
  1263. podAPE *bool // Pod AllowPrivilegeEscalation
  1264. expectErr bool
  1265. expectAPE *bool // Expected value of pod APE (if no error)
  1266. }{
  1267. // Test all valid combinations of PSP AllowPrivilegeEscalation,
  1268. // DefaultAllowPrivilegeEscalation, and Pod AllowPrivilegeEscalation.
  1269. {true, nil, nil, false, nil},
  1270. {true, nil, ptr(false), false, ptr(false)},
  1271. {true, nil, ptr(true), false, ptr(true)},
  1272. {true, ptr(false), nil, false, ptr(false)},
  1273. {true, ptr(false), ptr(false), false, ptr(false)},
  1274. {true, ptr(false), ptr(true), false, ptr(true)},
  1275. {true, ptr(true), nil, false, ptr(true)},
  1276. {true, ptr(true), ptr(false), false, ptr(false)},
  1277. {true, ptr(true), ptr(true), false, ptr(true)},
  1278. {false, nil, nil, false, ptr(false)},
  1279. {false, nil, ptr(false), false, ptr(false)},
  1280. {false, nil, ptr(true), true, nil},
  1281. {false, ptr(false), nil, false, ptr(false)},
  1282. {false, ptr(false), ptr(false), false, ptr(false)},
  1283. {false, ptr(false), ptr(true), true, nil},
  1284. // Invalid cases: pspAPE=false, pspDAPE=true
  1285. }
  1286. fmtPtr := func(b *bool) string {
  1287. if b == nil {
  1288. return "nil"
  1289. }
  1290. return strconv.FormatBool(*b)
  1291. }
  1292. for _, test := range tests {
  1293. t.Run(fmt.Sprintf("pspAPE:%t_pspDAPE:%s_podAPE:%s", test.pspAPE, fmtPtr(test.pspDAPE), fmtPtr(test.podAPE)), func(t *testing.T) {
  1294. pod := defaultPod()
  1295. pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = test.podAPE
  1296. psp := defaultPSP()
  1297. psp.Spec.AllowPrivilegeEscalation = &test.pspAPE
  1298. psp.Spec.DefaultAllowPrivilegeEscalation = test.pspDAPE
  1299. provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory())
  1300. require.NoError(t, err)
  1301. err = provider.MutatePod(pod)
  1302. require.NoError(t, err)
  1303. errs := provider.ValidatePod(pod)
  1304. if test.expectErr {
  1305. assert.NotEmpty(t, errs, "expected validation error")
  1306. } else {
  1307. assert.Empty(t, errs, "expected no validation errors")
  1308. ape := pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation
  1309. assert.Equal(t, test.expectAPE, ape, "expected pod AllowPrivilegeEscalation")
  1310. }
  1311. })
  1312. }
  1313. }
  1314. func TestDefaultRuntimeClassName(t *testing.T) {
  1315. const (
  1316. defaultedName = "foo"
  1317. presetName = "tim"
  1318. )
  1319. noRCS := defaultNamedPSP("nil-strategy")
  1320. emptyRCS := defaultNamedPSP("empty-strategy")
  1321. emptyRCS.Spec.RuntimeClass = &policy.RuntimeClassStrategyOptions{}
  1322. noDefaultRCS := defaultNamedPSP("no-default")
  1323. noDefaultRCS.Spec.RuntimeClass = &policy.RuntimeClassStrategyOptions{
  1324. AllowedRuntimeClassNames: []string{"foo", "bar"},
  1325. }
  1326. defaultRCS := defaultNamedPSP("defaulting")
  1327. defaultRCS.Spec.RuntimeClass = &policy.RuntimeClassStrategyOptions{
  1328. DefaultRuntimeClassName: pointer.StringPtr(defaultedName),
  1329. }
  1330. noRCPod := defaultPod()
  1331. noRCPod.Name = "no-runtimeclass"
  1332. rcPod := defaultPod()
  1333. rcPod.Name = "preset-runtimeclass"
  1334. rcPod.Spec.RuntimeClassName = pointer.StringPtr(presetName)
  1335. type testcase struct {
  1336. psp *policy.PodSecurityPolicy
  1337. pod *api.Pod
  1338. expectedRuntimeClassName *string
  1339. }
  1340. tests := []testcase{{
  1341. psp: defaultRCS,
  1342. pod: noRCPod,
  1343. expectedRuntimeClassName: pointer.StringPtr(defaultedName),
  1344. }}
  1345. // Non-defaulting no-preset cases
  1346. for _, psp := range []*policy.PodSecurityPolicy{noRCS, emptyRCS, noDefaultRCS} {
  1347. tests = append(tests, testcase{psp, noRCPod, nil})
  1348. }
  1349. // Non-defaulting preset cases
  1350. for _, psp := range []*policy.PodSecurityPolicy{noRCS, emptyRCS, noDefaultRCS, defaultRCS} {
  1351. tests = append(tests, testcase{psp, rcPod, pointer.StringPtr(presetName)})
  1352. }
  1353. for _, test := range tests {
  1354. t.Run(fmt.Sprintf("%s-psp %s-pod", test.psp.Name, test.pod.Name), func(t *testing.T) {
  1355. provider, err := NewSimpleProvider(test.psp, "namespace", NewSimpleStrategyFactory())
  1356. require.NoError(t, err, "error creating provider")
  1357. actualPod := test.pod.DeepCopy()
  1358. require.NoError(t, provider.MutatePod(actualPod))
  1359. expectedPod := test.pod.DeepCopy()
  1360. expectedPod.Spec.RuntimeClassName = test.expectedRuntimeClassName
  1361. assert.Equal(t, expectedPod, actualPod)
  1362. })
  1363. }
  1364. }
  1365. func TestAllowedRuntimeClassNames(t *testing.T) {
  1366. const (
  1367. goodName = "good"
  1368. )
  1369. noRCPod := defaultPod()
  1370. noRCPod.Name = "no-runtimeclass"
  1371. rcPod := defaultPod()
  1372. rcPod.Name = "good-runtimeclass"
  1373. rcPod.Spec.RuntimeClassName = pointer.StringPtr(goodName)
  1374. otherPod := defaultPod()
  1375. otherPod.Name = "bad-runtimeclass"
  1376. otherPod.Spec.RuntimeClassName = pointer.StringPtr("bad")
  1377. allPods := []*api.Pod{noRCPod, rcPod, otherPod}
  1378. type testcase struct {
  1379. name string
  1380. strategy *policy.RuntimeClassStrategyOptions
  1381. validPods []*api.Pod
  1382. invalidPods []*api.Pod
  1383. }
  1384. tests := []testcase{{
  1385. name: "nil-strategy",
  1386. validPods: allPods,
  1387. }, {
  1388. name: "empty-strategy",
  1389. strategy: &policy.RuntimeClassStrategyOptions{
  1390. AllowedRuntimeClassNames: []string{},
  1391. },
  1392. validPods: []*api.Pod{noRCPod},
  1393. invalidPods: []*api.Pod{rcPod, otherPod},
  1394. }, {
  1395. name: "allow-all-strategy",
  1396. strategy: &policy.RuntimeClassStrategyOptions{
  1397. AllowedRuntimeClassNames: []string{"*"},
  1398. DefaultRuntimeClassName: pointer.StringPtr("foo"),
  1399. },
  1400. validPods: allPods,
  1401. }, {
  1402. name: "named-allowed",
  1403. strategy: &policy.RuntimeClassStrategyOptions{
  1404. AllowedRuntimeClassNames: []string{goodName},
  1405. },
  1406. validPods: []*api.Pod{rcPod},
  1407. invalidPods: []*api.Pod{otherPod},
  1408. }}
  1409. for _, test := range tests {
  1410. t.Run(test.name, func(t *testing.T) {
  1411. psp := defaultNamedPSP(test.name)
  1412. psp.Spec.RuntimeClass = test.strategy
  1413. provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory())
  1414. require.NoError(t, err, "error creating provider")
  1415. for _, pod := range test.validPods {
  1416. copy := pod.DeepCopy()
  1417. assert.NoError(t, provider.ValidatePod(copy).ToAggregate(), "expected valid pod %s", pod.Name)
  1418. assert.Equal(t, pod, copy, "validate should not mutate!")
  1419. }
  1420. for _, pod := range test.invalidPods {
  1421. copy := pod.DeepCopy()
  1422. assert.Error(t, provider.ValidatePod(copy).ToAggregate(), "expected invalid pod %s", pod.Name)
  1423. assert.Equal(t, pod, copy, "validate should not mutate!")
  1424. }
  1425. })
  1426. }
  1427. }