appvia / psp-migration

Recreation of common Pod Security Policy configuration in other common Kubernetes policy engines
https://appvia.github.io/psp-migration
MIT License
51 stars 4 forks source link

[Bug]: Some PSPs fields are not migrated #222

Closed jvanz closed 2 years ago

jvanz commented 2 years ago

What happened?

The psp-migration is not able to generate some Kubewarden policies directly from the kubectl output. Consider the following PSP:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: pod-security-policy-restricted-psp
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default'
    apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
    seccomp.security.alpha.kubernetes.io/defaultProfileName: 'runtime/default'
    apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'
spec:
  allowedHostPaths:
    # This allows "/foo", "/foo/", "/foo/bar" etc., but
    # disallows "/fool", "/etc/foo" etc.
    # "/foo/../" is never valid.
    - pathPrefix: "/foo"
      readOnly: true  # only allow read-only mounts
  allowPrivilegeEscalation: false
  # This is redundant with non-root + disallow privilege escalation,
  # but we can provide it for defense in depth.
  fsGroup:
    rule: 'MustRunAs'
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  hostIPC: false
  hostNetwork: false
  hostPID: false
  privileged: false
  readOnlyRootFilesystem: false
  # Required to prevent escalations to root.
  requiredDropCapabilities:
    - ALL
  runAsUser:
    # Require the container to run without root privileges.
    rule: 'MustRunAsNonRoot'
  seLinux:
    # This policy assumes the nodes are using AppArmor rather than SELinux.
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAs'
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  # Allow core volume types.
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    # Assume that persistentVolumes set up by the cluster admin are safe to use.
    - 'persistentVolumeClaim'

After applied, when we tried to generate the Kubewarden policies from the kubectl get psp command, the migration tool generate this:

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-volumes-022aa
spec:
  module: registry://ghcr.io/kubewarden/policies/volumes-psp:v0.1.6
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allowedTypes:
      - configMap
      - emptyDir
      - projected
      - secret
      - downwardAPI
      - persistentVolumeClaim

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-apparmor-d2d41
spec:
  module: registry://ghcr.io/kubewarden/policies/apparmor-psp:v0.1.9
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allowed_profiles:
      - runtime/default

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-seccomp-588b4
spec:
  module: registry://ghcr.io/kubewarden/policies/seccomp-psp:v0.1.1
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allowed_profiles:
      - docker/default
      - runtime/default
    profile_types:
      - RuntimeDefault
    localhost_profiles: []

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-capabilities-60e87
spec:
  module: registry://ghcr.io/kubewarden/policies/capabilities-psp:v0.1.9
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allowed_capabilities: []
    required_drop_capabilities:
      - ALL

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-allowedhostpaths-fdbc0
spec:
  module: registry://ghcr.io/kubewarden/policies/hostpaths-psp:v0.1.5
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allowedHostPaths:
      - pathPrefix: /foo
        readOnly: true

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-usergroup-6b429
spec:
  module: registry://ghcr.io/kubewarden/policies/user-group-psp:v0.2.0
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    run_as_user:
      rule: MustRunAsNonRoot
    supplemental_groups:
      ranges:
        - max: 65535
          min: 1
      rule: MustRunAs

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-fsgroup-a48cf
spec:
  module: registry://ghcr.io/kubewarden/policies/allowed-fsgroups-psp:v0.1.4
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    ranges:
      - max: 65535
        min: 1
    rule: MustRunAs

---
apiVersion: policies.kubewarden.io/v1alpha2
kind: ClusterAdmissionPolicy
metadata:
  name: psp-defaultallowprivilegeescalation-13e07
spec:
  module: >-
    registry://ghcr.io/kubewarden/policies/allow-privilege-escalation-psp:v0.1.11
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    default_allow_privilege_escalation: false

Note that the hostIPC, hostNetwork, hostPID, privileged, readOnlyRootFilesystem fields are not being converted to the correspondent Kubewarden policy. However, if I use the original yaml file used to deploy the PSP the migration tool is able to create the policies.

What policy engine were you generating policy for

Kubewarden

Relevant log output

No response

jvanz commented 2 years ago

AFAICS, the root cause of this issue is that the psp-migration expects the fields hostIPC, hostNetwork, hostPID and readOnlyRootFilesystem to be false. However, if the user deploy these fields with false value, Kubernetes just ignore them. Therefore, when the user forward the output of the kubectl get psp command to the psp-migration tool the fields are not there. Take a look in this example:

jvanz@earth:~/suse/migration-script> cat psp-example3.yaml                                                                                                                                                                                   
apiVersion: policy/v1beta1                                                                                                                                                                                                                   
kind: PodSecurityPolicy                                                                                                                                                                                                                      
metadata:                                                                                                                                                                                                                                    
  name: pod-security-policy-restricted-psp3                                                                                                                                                                                                  
spec:                                                                                                                                                                                                                                        
  fsGroup:
    rule: 'MustRunAs'
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  hostIPC: false
  hostNetwork: false
  hostPID: false
  privileged: false
  readOnlyRootFilesystem: false
  runAsUser:
    # Require the container to run without root privileges. 
    rule: 'MustRunAsNonRoot'
  seLinux:
    # This policy assumes the nodes are using AppArmor rather than SELinux.
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAs'
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  # Allow core volume types.

jvanz@earth:~/suse/migration-script> kubectl apply -f psp-example3.yaml 
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/pod-security-policy-restricted-psp3 created
jvanz@earth:~/suse/migration-script> kubectl get psp pod-security-policy-restricted-psp3 -o json | jq ".spec"
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
{
  "allowPrivilegeEscalation": true,
  "fsGroup": {
    "ranges": [
      {
        "max": 65535,
        "min": 1
      }
    ],
    "rule": "MustRunAs"
  },
  "runAsUser": {
    "rule": "MustRunAsNonRoot"
  },
  "seLinux": {
    "rule": "RunAsAny"
  },
  "supplementalGroups": {
    "ranges": [
      {
        "max": 65535,
        "min": 1
      }
    ],
    "rule": "MustRunAs"
  }
}

This explains why the psp-migration is able to migrate from the original file used to deploy the PSP. But it cannot migration from the kubectl output.