naughty-from.sh 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #!/usr/bin/env bash
  2. set -Eeuo pipefail
  3. export BASHBREW_ARCH=
  4. if [ "$#" -eq 0 ]; then
  5. set -- '--all'
  6. fi
  7. externalPinsDir="$(dirname "$BASH_SOURCE")/.external-pins"
  8. declare -A externalPinsArchesCache=(
  9. #[img:tag]='["arch","arch",...]' # (json array of strings)
  10. )
  11. _is_naughty() {
  12. local from="$1"; shift
  13. case "$from" in
  14. # "scratch" isn't a real image and is always permissible (on non-Windows)
  15. scratch)
  16. case "$BASHBREW_ARCH" in
  17. windows-*) return 0 ;; # can't use "FROM scratch" on Windows
  18. *) return 1 ;; # can use "FROM scratch" everywhere else
  19. esac
  20. ;;
  21. # https://github.com/docker-library/official-images/pull/4916#issuecomment-427437270
  22. docker.elastic.co/elasticsearch/elasticsearch:*@sha256:* \
  23. | docker.elastic.co/kibana/kibana:*@sha256:* \
  24. | docker.elastic.co/logstash/logstash:*@sha256:* \
  25. ) ;; # *technically* we should only whitelist these for "elasticsearch", "kibana", and "logstash" respectively, but the chances of other folks trying to use them in their images (*and* doing so without us noticing) seems low
  26. */*)
  27. # must be external, let's check our pins for acceptability
  28. local externalPinFile="$externalPinsDir/${from/:/___}" # see ".external-pins/list.sh"
  29. if [ -s "$externalPinFile" ]; then
  30. local digest
  31. digest="$(< "$externalPinFile")"
  32. from+="@$digest"
  33. else
  34. # not pinned, must not be acceptable
  35. return 0
  36. fi
  37. ;;
  38. esac
  39. case "$from" in
  40. */*@sha256:*)
  41. if [ -z "${externalPinsArchesCache["$from"]:-}" ]; then
  42. local remoteArches
  43. if remoteArches="$(bashbrew remote arches --json "$from" | jq -c '.arches | keys')"; then
  44. externalPinsArchesCache["$from"]="$remoteArches"
  45. else
  46. echo >&2 "warning: failed to query supported architectures of '$from'"
  47. externalPinsArchesCache["$from"]='[]'
  48. fi
  49. fi
  50. if jq <<<"${externalPinsArchesCache["$from"]}" -e 'index(env.BASHBREW_ARCH)' > /dev/null; then
  51. # hooray, a supported architecture!
  52. return 1
  53. fi
  54. ;;
  55. *)
  56. # must be some other official image AND support our current architecture
  57. local archSupported
  58. if archSupported="$(bashbrew cat --format '{{ .TagEntry.HasArchitecture arch | ternary arch "" }}' "$from")" && [ -n "$archSupported" ]; then
  59. return 1
  60. fi
  61. ;;
  62. esac
  63. return 0
  64. }
  65. _arches() {
  66. bashbrew cat --format '
  67. {{- range .TagEntries -}}
  68. {{- .Architectures | join "\n" -}}
  69. {{- "\n" -}}
  70. {{- end -}}
  71. ' "$@" | sort -u
  72. }
  73. _froms() {
  74. bashbrew cat --format '
  75. {{- range .TagEntries -}}
  76. {{- $.DockerFroms . | join "\n" -}}
  77. {{- "\n" -}}
  78. {{- end -}}
  79. ' "$@" | sort -u
  80. }
  81. declare -A naughtyFromsArches=(
  82. #[img:tag=from:tag]='arch arch ...'
  83. )
  84. naughtyFroms=()
  85. declare -A allNaughty=(
  86. #[img:tag]=1
  87. )
  88. tags="$(bashbrew --namespace '' list --uniq "$@" | sort -u)"
  89. for img in $tags; do
  90. arches="$(_arches "$img")"
  91. hasNice= # do we have _any_ arches that aren't naughty? (so we can make the message better if not)
  92. for BASHBREW_ARCH in $arches; do
  93. export BASHBREW_ARCH
  94. froms="$(_froms "$img")"
  95. [ -n "$froms" ] # rough sanity check
  96. for from in $froms; do
  97. if _is_naughty "$from"; then
  98. if [ -z "${naughtyFromsArches["$img=$from"]:-}" ]; then
  99. naughtyFroms+=( "$img=$from" )
  100. else
  101. naughtyFromsArches["$img=$from"]+=', '
  102. fi
  103. naughtyFromsArches["$img=$from"]+="$BASHBREW_ARCH"
  104. else
  105. hasNice=1
  106. fi
  107. done
  108. done
  109. if [ -z "$hasNice" ]; then
  110. allNaughty["$img"]=1
  111. fi
  112. done
  113. for naughtyFrom in "${naughtyFroms[@]:-}"; do
  114. [ -n "$naughtyFrom" ] || continue # https://mywiki.wooledge.org/BashFAQ/112#BashFAQ.2F112.line-8 (empty array + "set -u" + bash 4.3 == sad day)
  115. img="${naughtyFrom%%=*}"
  116. from="${naughtyFrom#$img=}"
  117. if [ -n "${allNaughty["$img"]:-}" ]; then
  118. echo " - $img (FROM $from) -- completely unsupported base!"
  119. else
  120. arches="${naughtyFromsArches[$naughtyFrom]}"
  121. echo " - $img (FROM $from) [$arches]"
  122. fi
  123. done