fix-policies.sh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #!/bin/bash
  2. #
  3. # Generate modified policies. Patch existing modified policies to disable them.
  4. #
  5. # Need files:
  6. # policyexport (a dump of all policies)
  7. # roxctl-token (api auth token)
  8. #
  9. E=central-rhacs.apps.ocp4.example.com
  10. T=$(cat roxctl-token)
  11. DISABLED_POLICY_LIST=(
  12. "ADD Command used instead of COPY"
  13. "Container using read-write root filesystem"
  14. "Curl in Image"
  15. "Docker CIS 4.4: Ensure images are scanned and rebuilt to include security patches"
  16. "Docker CIS 5.21: Ensure the default seccomp profile is not disabled"
  17. "Fixable CVSS >= 7"
  18. "Images with no scans"
  19. "Login Binaries"
  20. "Password Binaries"
  21. "Process with UID 0"
  22. "Required Annotation: Email"
  23. "Required Annotation: Owner/Team"
  24. "Required Image Label"
  25. "Required Label: Owner/Team"
  26. "Secret Mounted as Environment Variable"
  27. "SetUID Processes"
  28. "Shadow File Modification"
  29. "Shell Management"
  30. "Wget in Image"
  31. )
  32. ENABLED_POLICY_LIST=(
  33. "30-Day Scan Age"
  34. "Alpine Linux Package Manager Execution"
  35. "Apache Struts: CVE-2017-5638"
  36. "CAP_SYS_ADMIN capability added"
  37. "Compiler Tool Execution"
  38. "Cryptocurrency Mining Process Execution"
  39. "Docker CIS 4.7: Alert on Update Instruction"
  40. "Docker CIS 5.1 Ensure that, if applicable, an AppArmor Profile is enabled"
  41. "Docker CIS 5.19: Ensure mount propagation mode is not enabled"
  42. "Emergency Deployment Annotation"
  43. "Improper Usage of Orchestrator Secrets Volume"
  44. "Insecure specified in CMD"
  45. "Iptables Executed in Privileged Container"
  46. "Kubernetes Actions: Exec into Pod"
  47. "Kubernetes Actions: Port Forward to Pod"
  48. "Kubernetes Dashboard Deployed"
  49. "Latest tag"
  50. "Linux Group Add Execution"
  51. "Linux User Add Execution"
  52. "Log4Shell: log4j Remote Code Execution vulnerability"
  53. "Netcat Execution Detected"
  54. "Network Management Execution"
  55. "OpenShift: Advanced Cluster Security Central Admin Secret Accessed"
  56. "OpenShift: Kubeadmin Secret Accessed"
  57. "OpenShift: Kubernetes Secret Accessed by an Impersonated User"
  58. "Process Targeting Cluster Kubelet Endpoint"
  59. "Process Targeting Cluster Kubernetes Docker Stats Endpoint"
  60. "Process Targeting Kubernetes Service Endpoint"
  61. "Red Hat Package Manager Execution"
  62. "Remote File Copy Binary Execution"
  63. "Secure Shell (ssh) Port Exposed"
  64. "Secure Shell (ssh) Port Exposed in Image"
  65. "Secure Shell Server (sshd) Execution"
  66. "Shell Spawned by Java Application"
  67. "Ubuntu Package Manager Execution"
  68. "Ubuntu Package Manager in Image"
  69. "Unauthorized Network Flow"
  70. "Unauthorized Process Execution"
  71. "chkconfig Execution"
  72. "crontab Execution"
  73. "iptables Execution"
  74. "nmap Execution"
  75. "systemctl Execution"
  76. "systemd Execution"
  77. )
  78. FIX_POLICY_LIST=(
  79. "90-Day Image Age"
  80. "Alpine Linux Package Manager (apk) in Image"
  81. "Docker CIS 4.1: Ensure That a User for the Container Has Been Created"
  82. "Docker CIS 5.15: Ensure that the host's process namespace is not shared"
  83. "Docker CIS 5.16: Ensure that the host's IPC namespace is not shared"
  84. "Docker CIS 5.7: Ensure privileged ports are not mapped within containers"
  85. "Docker CIS 5.9 and 5.20: Ensure that the host's network namespace is not shared"
  86. "Environment Variable Contains Secret"
  87. "Fixable CVSS >= 6 and Privileged"
  88. "Fixable Severity at least Important"
  89. "Mount Container Runtime Socket"
  90. "Mounting Sensitive Host Directories"
  91. "No resource requests or limits specified"
  92. "Pod Service Account Token Automatically Mounted"
  93. "Privileged Container"
  94. "Red Hat Package Manager in Image"
  95. )
  96. echo "Fixed policies: ${#FIX_POLICY_LIST[*]}"
  97. echo "Enabled policies: ${#ENABLED_POLICY_LIST[*]}"
  98. echo "Disabled policies: ${#DISABLED_POLICY_LIST[*]}"
  99. # Export current policies.
  100. # TODO: decide when to use backup and when to use current state
  101. # XXX: can't delete system policies anyway
  102. oldIFS="${IFS}"
  103. newIFS='
  104. '
  105. IFS="${newIFS}"
  106. for p in ${DISABLED_POLICY_LIST[*]}; do
  107. id="$(jq -r '.policies[] | select(.name == "'${p}'") | .id' < policyexport)"
  108. if [ -z "${id}" ]; then
  109. echo "ERROR: Could not look up ID of \"${p}\"!"
  110. continue
  111. fi
  112. echo -n "Disabling \"${p}\" ($id)... "
  113. curl -ks -XPATCH -H "Authorization: Bearer ${T}" -d '{"id": "'${id}'", "disabled": true}' https://${E}/v1/policies/${id}
  114. echo
  115. done
  116. for p in ${ENABLED_POLICY_LIST[*]}; do
  117. id="$(jq -r '.policies[] | select(.name == "'${p}'") | .id' < policyexport)"
  118. if [ -z "${id}" ]; then
  119. echo "ERROR: Could not look up ID of \"${p}\"!"
  120. continue
  121. fi
  122. echo -n "Enabling \"${p}\" ($id)... "
  123. curl -ks -XPATCH -H "Authorization: Bearer ${T}" -d '{"id": "'${id}'", "disabled": false}' https://${E}/v1/policies/${id}
  124. echo
  125. done
  126. for p in ${FIX_POLICY_LIST[*]}; do
  127. # find matching policies
  128. ids="$(jq -r '.policies[] | select(.name | test("(?i)^'${p//[()]/.}'")) | .id' < policyexport)"
  129. if [ -z "${ids}" ]; then
  130. echo "ERROR: Could not look up ID(s) of \"${p//[()]/.}\"!"
  131. continue
  132. fi
  133. # how many?
  134. nmatch=$(echo "${ids}" | wc -l | tr -d '[[:space:]]')
  135. echo "Found ${nmatch} policies matching \"${p}\"..."
  136. if [ ${nmatch} -gt 1 ]; then
  137. # delete the one(s) that are not an exact match
  138. id="$(jq -r '.policies[] | select(.name == "'${p}'") | .id' < policyexport)"
  139. if [ -z "${id}" ]; then
  140. echo "ERROR: Could not find exact match for \"${p}\"!"
  141. continue
  142. fi
  143. xtraids="$(echo "${ids}" | grep -v ${id})"
  144. for rmid in ${xtraids}; do
  145. echo -n " - removing: ${rmid}"
  146. curl -ks -XDELETE -H "Authorization: Bearer ${T}" https://${E}/v1/policies/${rmid}
  147. echo
  148. done
  149. else
  150. id="${ids}"
  151. fi
  152. echo " - keeping: ${id}"
  153. echo -n " disabling... "
  154. curl -ks -XPATCH -H "Authorization: Bearer ${T}" -d '{"id": "'${id}'", "disabled": true}' https://${E}/v1/policies/${id}
  155. echo
  156. echo -n " creating patched copy... "
  157. PAYLOAD="$(jq '.policies[] | select(.id == "'${id}'") | .exclusions |= [ { "name": "Skip system namespaces", "deployment": { "name": "", "scope": { "cluster": "", "namespace": "^kube-.*|^openshift-.*|^istio-.*|^rhacs$|^stackrox$", "label": null } }, "image": null, "expiration": null } ] | .name |= . + " (non-system)" | .id |= "" | .disabled |= false' < policyexport)"
  158. curl -ks -XPOST -H "Authorization: Bearer ${T}" -d "${PAYLOAD}" https://${E}/v1/policies
  159. echo
  160. done
  161. IFS="${oldIFS}"
  162. unset oldIFS newIFS