Skip to content

Commit c18b650

Browse files
committed
Add explicit "external-pins", take two
This is a second attempt at 98575e0: > The goal of this directory is two-fold: to list the explicitly allowable external dependencies and to pin those external dependencies to a specific content-addressable digest such that we can update them in the same way we do everything else (and then trigger rebuilds properly based on them, too). See `.external-pins/list.sh` for a useful summary of the assumptions that went into the naming scheme.
1 parent 0b231a6 commit c18b650

File tree

10 files changed

+108
-45
lines changed

10 files changed

+108
-45
lines changed

.external-pins/list.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
set -Eeuo pipefail
3+
4+
dir="$(dirname "$BASH_SOURCE")"
5+
6+
find "$dir" -mindepth 2 -type f -printf '%P\n' | sed -e 's/___/:/' | sort
7+
8+
# assumptions which make the "___" -> ":" conversion ~safe (examples referencing "example.com/foo/bar:baz"):
9+
#
10+
# 1. we *always* specify a tag ("baz")
11+
# 2. the domain ("example.com") cannot contain underscores
12+
# 3. we do not pin to any registry with a non-443 port ("example.com:8443")
13+
# 4. the repository ("foo/bar") can only contain singular or double underscores (never triple underscore), and only between alphanumerics (thus never right up next to ":")
14+
# 5. we do *not* use the "g" regex modifier in our sed, which means only the first instance of triple underscore is replaced (in pure Bash, that's "${img/:/___}" or "${img/___/:}" depending on the conversion direction)
15+
#
16+
# see https://github.com/distribution/distribution/blob/411d6bcfd2580d7ebe6e346359fa16aceec109d5/reference/regexp.go
17+
# (see also https://github.com/docker-library/perl-bashbrew/blob/6685582f7889ef4806f0544b93f10640c7608b1a/lib/Bashbrew/RemoteImageRef.pm#L9-L26 for a condensed version)
18+
#
19+
# see https://github.com/docker-library/official-images/issues/13608 for why we can't just use ":" as-is (even though Linux, macOS, and even Windows via MSYS / WSL2 don't have any issues with it)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sha256:5c9da3bfe1524eab610dfd41c79a0805c080f8307d810d62bba106b5df587698
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sha256:f1125cf932664b039a55afb666bdca7dc28d453a88430fe47be763e0270638b6
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sha256:cbb8b0a709b4e0868cd2e30b1485358197b1021bb0dd4261e36b3af3ca48fd0b
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sha256:8d862016bcfad6040cb9ae0f21b024fe71b058ddb42a077c32a24bcb5fc04628
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sha256:3685c58885771d2ea14608caeab6a4c3949b973588c29ce91f462b486ee1be25

.external-pins/update.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
set -Eeuo pipefail
3+
4+
dir="$(dirname "$BASH_SOURCE")"
5+
6+
if [ "$#" -eq 0 ]; then
7+
images="$("$dir/list.sh")"
8+
set -- $images
9+
fi
10+
11+
for img; do
12+
echo -n "$img -> "
13+
14+
if [[ "$img" != *:* ]]; then
15+
echo >&2 "error: '$img' does not contain ':' -- this violates our assumptions! (did you mean '$img:latest' ?)"
16+
exit 1
17+
fi
18+
19+
digest="$(bashbrew remote arches --json "$img" | jq -r '.desc.digest')"
20+
21+
imgFile="$dir/${img/:/___}" # see ".external-pins/list.sh"
22+
imgDir="$(dirname "$imgFile")"
23+
mkdir -p "$imgDir"
24+
echo "$digest" | tee "$imgFile"
25+
done

.github/workflows/.bashbrew/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ runs:
1010

1111
# these two version numbers are intentionally as close together as I could possibly get them because no matter what I tried, GitHub will not allow me to DRY them (can't have any useful variables in `uses:` and can't even have YAML references to steal it in `env:` or something)
1212
- shell: 'bash -Eeuo pipefail -x {0}'
13-
run: echo BASHBREW_VERSION=v0.1.5 >> "$GITHUB_ENV"
14-
- uses: docker-library/[email protected].5
13+
run: echo BASHBREW_VERSION=v0.1.6 >> "$GITHUB_ENV"
14+
- uses: docker-library/[email protected].6
1515
if: inputs.build == 'host'
1616

1717
- run: docker build --pull --tag oisupport/bashbrew:base "https://github.com/docker-library/bashbrew.git#$BASHBREW_VERSION"

README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,7 @@ When taking over an existing repository, please ensure that the entire Git histo
119119

120120
Rebuilding the same `Dockerfile` should result in the same version of the image being packaged, even if the second build happens several versions later, or the build should fail outright, such that an inadvertent rebuild of a `Dockerfile` tagged as `0.1.0` doesn't end up containing `0.2.3`. For example, if using `apt` to install the main program for the image, be sure to pin it to a specific version (ex: `... apt-get install -y my-package=0.1.0 ...`). For dependent packages installed by `apt` there is not usually a need to pin them to a version.
121121

122-
No official images can be derived from, or depend on, non-official images with the following notable exceptions:
123-
124-
- [`FROM scratch`](https://hub.docker.com/_/scratch/)
125-
- [`FROM mcr.microsoft.com/windows/servercore`](https://hub.docker.com/r/microsoft/windowsservercore/)
126-
- [`FROM mcr.microsoft.com/windows/nanoserver`](https://hub.docker.com/r/microsoft/nanoserver/)
122+
No official images can be derived from, or depend on, non-official images (allowing the non-image [`scratch`](https://hub.docker.com/_/scratch/) and the intentionally limited exceptions pinned in [`.external-pins`](.external-pins) -- see also [`.external-pins/list.sh`](.external-pins/list.sh)).
127123

128124
#### Consistency
129125

naughty-from.sh

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,49 +13,67 @@ if [ "$#" -eq 0 ]; then
1313
set -- '--all'
1414
fi
1515

16+
externalPinsDir="$(dirname "$BASH_SOURCE")/.external-pins"
17+
declare -A externalPinsArchesCache=(
18+
#[img:tag]='["arch","arch",...]' # (json array of strings)
19+
)
1620
_is_naughty() {
1721
local from="$1"; shift
1822

19-
case "$BASHBREW_ARCH=$from" in
20-
# a few images that no longer exist (and are thus not permissible)
21-
# https://techcommunity.microsoft.com/t5/Containers/Removing-the-latest-Tag-An-Update-on-MCR/ba-p/393045
22-
*=mcr.microsoft.com/windows/*:latest) return 0 ;;
23-
24-
25-
# https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/base-image-lifecycle
26-
#*=mcr.microsoft.com/windows/*:ltsc2022) return 0 ;; # "10/13/2026"
27-
#*=mcr.microsoft.com/windows/*:20H2*) return 0 ;; # "05/10/2022" *technically*, but its use is discouraged here given the existence of ltsc2022
28-
*=mcr.microsoft.com/windows/*:2004*) return 0 ;; # "12/14/2021"
29-
*=mcr.microsoft.com/windows/*:1909*) return 0 ;; # "05/11/2021"
30-
*=mcr.microsoft.com/windows/*:1903*) return 0 ;; # "12/08/2020"
31-
#*=mcr.microsoft.com/windows/*:1809*) return 0 ;; # "01/09/2024"
32-
*=mcr.microsoft.com/windows/*:1803*) return 0 ;; # "11/12/2019"
33-
*=mcr.microsoft.com/windows/*:1709*) return 0 ;; # "04/09/2019"
34-
*=mcr.microsoft.com/windows/*:ltsc2016) return 0 ;; # "01/11/2022"
35-
*=mcr.microsoft.com/windows/*:sac2016) return 0 ;; # "10/09/2018"
36-
*=mcr.microsoft.com/windows/*:1607*) return 0 ;; # "10/09/2018"
37-
38-
# a few explicitly permissible exceptions to Santa's naughty list
39-
*=scratch \
40-
| amd64=docker.elastic.co/elasticsearch/elasticsearch:* \
41-
| amd64=docker.elastic.co/kibana/kibana:* \
42-
| amd64=docker.elastic.co/logstash/logstash:* \
43-
| arm64v8=docker.elastic.co/elasticsearch/elasticsearch:* \
44-
| arm64v8=docker.elastic.co/kibana/kibana:* \
45-
| arm64v8=docker.elastic.co/logstash/logstash:* \
46-
| windows-*=mcr.microsoft.com/windows/nanoserver:* \
47-
| windows-*=mcr.microsoft.com/windows/servercore:* \
48-
) return 1 ;;
49-
50-
# "x/y" and not an approved exception
51-
*/*) return 0 ;;
23+
case "$from" in
24+
# "scratch" isn't a real image and is always permissible (on non-Windows)
25+
scratch)
26+
case "$BASHBREW_ARCH" in
27+
windows-*) return 0 ;; # can't use "FROM scratch" on Windows
28+
*) return 1 ;; # can use "FROM scratch" everywhere else
29+
esac
30+
;;
31+
32+
# https://github.com/docker-library/official-images/pull/4916#issuecomment-427437270
33+
docker.elastic.co/elasticsearch/elasticsearch:*@sha256:* \
34+
| docker.elastic.co/kibana/kibana:*@sha256:* \
35+
| docker.elastic.co/logstash/logstash:*@sha256:* \
36+
) ;; # *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
37+
38+
*/*)
39+
# must be external, let's check our pins for acceptability
40+
local externalPinFile="$externalPinsDir/${from/:/___}" # see ".external-pins/list.sh"
41+
if [ -s "$externalPinFile" ]; then
42+
local digest
43+
digest="$(< "$externalPinFile")"
44+
from+="@$digest"
45+
else
46+
# not pinned, must not be acceptable
47+
return 0
48+
fi
49+
;;
5250
esac
5351

54-
# must be some other official image AND support our current architecture
55-
local archSupported
56-
if archSupported="$(bashbrew cat --format '{{ .TagEntry.HasArchitecture arch | ternary arch "" }}' "$from")" && [ -n "$archSupported" ]; then
57-
return 1
58-
fi
52+
case "$from" in
53+
*/*@sha256:*)
54+
if [ -z "${externalPinsArchesCache["$from"]:-}" ]; then
55+
local remoteArches
56+
if remoteArches="$(bashbrew remote arches --json "$from" | jq -c '.arches | keys')"; then
57+
externalPinsArchesCache["$from"]="$remoteArches"
58+
else
59+
echo >&2 "warning: failed to query supported architectures of '$from'"
60+
externalPinsArchesCache["$from"]='[]'
61+
fi
62+
fi
63+
if jq <<<"${externalPinsArchesCache["$from"]}" -e 'index(env.BASHBREW_ARCH)' > /dev/null; then
64+
# hooray, a supported architecture!
65+
return 1
66+
fi
67+
;;
68+
69+
*)
70+
# must be some other official image AND support our current architecture
71+
local archSupported
72+
if archSupported="$(bashbrew cat --format '{{ .TagEntry.HasArchitecture arch | ternary arch "" }}' "$from")" && [ -n "$archSupported" ]; then
73+
return 1
74+
fi
75+
;;
76+
esac
5977

6078
return 0
6179
}

0 commit comments

Comments
 (0)