Skip to content

Commit 7528039

Browse files
chore(hermetic-build): use secure base image hosted in docker.com (#3324)
This PR switches the base images of all the Hermetic Build Docker image stages to publicly hosted docker images. The chosen images are mirrored by Airlock or are at least in process of incorporation. The choice of OS family is `alpine` for its security-oriented setup. 0 vulnerabilities were found in the public image scan reports ([example](https://hub.docker.com/layers/library/python/3.12.7-alpine3.20/images/sha256-f498302457ec11162f872199b92239c34e1fbcdbc391ff37a4959e820224aa98?context=explore)). Although several optimizations are possible (see #3196 and its intermediate commits), this PR is restricted to the minimal changes to have a secure base image. _Notes:_ * Since the UNIX tools are from FreeBSD, the `-d` flag in the `rm` command is not supported. This is why we removed its usage in the scripts * A few downstream checks are failing in other PRs as well. I raised #3325 to track this.
1 parent b21c9a4 commit 7528039

File tree

5 files changed

+54
-33
lines changed

5 files changed

+54
-33
lines changed

.cloudbuild/library_generation/library_generation.Dockerfile

+46-25
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,44 @@
1414

1515
# install gapic-generator-java in a separate layer so we don't overload the image
1616
# with the transferred source code and jars
17-
FROM gcr.io/cloud-devrel-public-resources/java21@sha256:2ceff5eeea72260258df56d42e44ed413e52ee421c1b77393c5f2c9c4d7c41da AS ggj-build
17+
18+
# 3.9.9-eclipse-temurin-11-alpine
19+
FROM docker.io/library/maven@sha256:006d25558f9d5244ed55b5d2bd8eaf34d883e447d0c4b940e67b9f44d21167bf AS ggj-build
1820

1921
WORKDIR /sdk-platform-java
2022
COPY . .
2123
# {x-version-update-start:gapic-generator-java:current}
22-
ENV DOCKER_GAPIC_GENERATOR_VERSION="2.49.1-SNAPSHOT"
24+
ENV DOCKER_GAPIC_GENERATOR_VERSION="2.49.1-SNAPSHOT"
2325
# {x-version-update-end}
2426

2527
RUN mvn install -B -ntp -DskipTests -Dclirr.skip -Dcheckstyle.skip
2628
RUN cp "/root/.m2/repository/com/google/api/gapic-generator-java/${DOCKER_GAPIC_GENERATOR_VERSION}/gapic-generator-java-${DOCKER_GAPIC_GENERATOR_VERSION}.jar" \
2729
"./gapic-generator-java.jar"
2830

29-
# build from the root of this repo:
30-
FROM gcr.io/cloud-devrel-public-resources/python@sha256:9c5ea427632f195ad164054831968389d86fdde4a15abca651f3fcb2a71268cb
31+
# alpine:3.20.3
32+
FROM docker.io/library/alpine@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d as glibc-compat
33+
34+
RUN apk add git sudo
35+
# This SHA is the latest known-to-work version of this binary compatibility tool
36+
ARG GLIB_MUS_SHA=7717dd4dc26377dd9cedcc92b72ebf35f9e68a2d
37+
WORKDIR /home
38+
39+
# Install compatibility layer to run glibc-based programs (such as the
40+
# grpc plugin).
41+
# Alpine, by default, only supports musl-based binaries, and there is no public
42+
# downloadable distribution of the grpc plugin that is Alpine (musl) compatible.
43+
# This is one of the recommended approaches to ensure glibc-compatibility
44+
# as per https://wiki.alpinelinux.org/wiki/Running_glibc_programs
45+
RUN git clone https://gitlab.com/manoel-linux1/GlibMus-HQ.git
46+
WORKDIR /home/GlibMus-HQ
47+
# We lock the tool to the latest known-to-work version
48+
RUN git checkout "${GLIB_MUS_SHA}"
49+
RUN chmod a+x compile-x86_64-alpine-linux.sh
50+
RUN sh compile-x86_64-alpine-linux.sh
51+
52+
# python:3.12.7-alpine3.20
53+
FROM docker.io/library/python@sha256:38e179a0f0436c97ecc76bcd378d7293ab3ee79e4b8c440fdc7113670cb6e204 as final
3154

32-
SHELL [ "/bin/bash", "-c" ]
3355

3456

3557
ARG OWLBOT_CLI_COMMITTISH=38fe6f89a2339ee75c77739b31b371f601b01bb3
@@ -40,9 +62,24 @@ ENV HOME=/home
4062
ENV OS_ARCHITECTURE="linux-x86_64"
4163

4264
# install OS tools
43-
RUN apt-get update && apt-get install -y \
44-
unzip openjdk-17-jdk rsync maven jq \
45-
&& apt-get clean
65+
RUN apk update && apk add unzip curl rsync openjdk11 jq bash nodejs npm git
66+
67+
SHELL [ "/bin/bash", "-c" ]
68+
69+
# Copy glibc shared objects to enable execution of the grpc plugin.
70+
# This list was obtained via `libtree -pvvv /grpc/*` in the final container as
71+
# well as inspecting the modifications done by compile-x86_64-alpine-linux.sh
72+
# in the glibc-compat stage using the `dive` command.
73+
COPY --from=glibc-compat /etc/libgcc* /etc/
74+
COPY --from=glibc-compat /lib64/ld-linux-x86-64.so.2 /lib64/
75+
COPY --from=glibc-compat /lib/GLIBCFAKE.so.0 /lib/
76+
COPY --from=glibc-compat /lib/ld-linux-x86-64.so.2 /lib/
77+
COPY --from=glibc-compat /lib/libpthread* /lib/
78+
COPY --from=glibc-compat /lib/libucontext* /lib/
79+
COPY --from=glibc-compat /lib/libc.* /lib/
80+
COPY --from=glibc-compat /usr/lib/libgcc* /usr/lib/
81+
COPY --from=glibc-compat /usr/lib/libstdc* /usr/lib/
82+
COPY --from=glibc-compat /usr/lib/libobstack* /usr/lib/
4683

4784
# copy source code
4885
COPY hermetic_build/common /src/common
@@ -72,10 +109,6 @@ ENV DOCKER_GRPC_VERSION="${GRPC_VERSION}"
72109
COPY --from=ggj-build "/sdk-platform-java/gapic-generator-java.jar" "${HOME}/.library_generation/gapic-generator-java.jar"
73110
RUN chmod 755 "${HOME}/.library_generation/gapic-generator-java.jar"
74111

75-
# use python 3.12 (the base image has several python versions; here we define the default one)
76-
RUN rm $(which python3)
77-
RUN ln -s $(which python3.12) /usr/local/bin/python
78-
RUN ln -s $(which python3.12) /usr/local/bin/python3
79112
RUN python -m pip install --upgrade pip
80113

81114
# install main scripts as a python package
@@ -85,25 +118,14 @@ RUN python -m pip install src/common
85118
RUN python -m pip install --require-hashes -r src/library_generation/requirements.txt
86119
RUN python -m pip install src/library_generation
87120

88-
# Install nvm with node and npm
89-
ENV NODE_VERSION 20.12.0
90-
WORKDIR /home
91-
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
92-
RUN chmod o+rx /home/.nvm
93-
ENV NODE_PATH=/home/.nvm/versions/node/v${NODE_VERSION}/bin
94-
ENV PATH=${PATH}:${NODE_PATH}
95-
RUN node --version
96-
RUN npm --version
97-
98121
# install the owl-bot CLI
99122
WORKDIR /tools
100123
RUN git clone https://github.com/googleapis/repo-automation-bots
101124
WORKDIR /tools/repo-automation-bots/packages/owl-bot
102125
RUN git checkout "${OWLBOT_CLI_COMMITTISH}"
103126
RUN npm i && npm run compile && npm link
104127
RUN owl-bot copy-code --version
105-
RUN chmod -R o+rx ${NODE_PATH}
106-
RUN ln -sf ${NODE_PATH}/* /usr/local/bin
128+
RUN chmod o+rx $(which owl-bot)
107129

108130
# download the Java formatter
109131
ADD https://maven-central.storage-download.googleapis.com/maven2/com/google/googlejavaformat/google-java-format/${JAVA_FORMAT_VERSION}/google-java-format-${JAVA_FORMAT_VERSION}-all-deps.jar \
@@ -120,7 +142,6 @@ RUN git config --system user.name "Cloud Java Bot"
120142

121143
# allow read-write for /home and execution for binaries in /home/.nvm
122144
RUN chmod -R a+rw /home
123-
RUN chmod -R a+rx /home/.nvm
124145

125146
WORKDIR /workspace
126147
ENTRYPOINT [ "python", "/src/library_generation/cli/entry_point.py", "generate" ]

hermetic_build/library_generation/generate_library.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ temp_destination_path="${output_folder}/temp_preprocessed"
119119
mkdir -p "${output_folder}/${destination_path}"
120120
if [ -d "${temp_destination_path}" ]; then
121121
# we don't want the preprocessed sources of a previous run
122-
rm -rd "${temp_destination_path}"
122+
rm -r "${temp_destination_path}"
123123
fi
124124
mkdir -p "${temp_destination_path}"
125125
##################### Section 0 #####################
@@ -274,5 +274,5 @@ rm -rf java_gapic_srcjar java_gapic_srcjar_raw.srcjar.zip java_grpc.jar java_pro
274274
popd # destination path
275275

276276
cp -r ${temp_destination_path}/* "${output_folder}/${destination_path}"
277-
rm -rdf "${temp_destination_path}"
277+
rm -rf "${temp_destination_path}"
278278
exit 0

hermetic_build/library_generation/owlbot/bin/entrypoint.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ library_version=$5
3636

3737
if [[ "${is_monorepo}" == "true" ]]; then
3838
mv owl-bot-staging/* temp
39-
rm -rd owl-bot-staging/
39+
rm -rf owl-bot-staging/
4040
mv temp owl-bot-staging
4141
fi
4242

hermetic_build/library_generation/tests/generate_library_unit_tests.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def setUp(self):
5353
bash_call(f"mkdir {self.output_folder}")
5454

5555
def tearDown(self):
56-
bash_call(f"rm -rdf {self.simulated_home}")
56+
bash_call(f"rm -rf {self.simulated_home}")
5757

5858
def _run_command(self, command, **kwargs):
5959
env = os.environ.copy()

hermetic_build/library_generation/tests/generate_library_unit_tests.sh

+4-4
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ download_tools_succeed_with_baked_protoc() {
138138
download_tools "99.99" "${test_grpc_version}" "linux-x86_64"
139139
assertEquals "${protoc_bin_folder}" "${protoc_path}"
140140

141-
rm -rdf "${output_folder}"
141+
rm -rf "${output_folder}"
142142
unset DOCKER_PROTOC_LOCATION
143143
unset DOCKER_PROTOC_VERSION
144144
unset output_folder
@@ -159,7 +159,7 @@ download_tools_succeed_with_baked_grpc() {
159159
download_tools "${test_protoc_version}" "99.99" "linux-x86_64"
160160
assertEquals "${DOCKER_GRPC_LOCATION}" "${grpc_path}"
161161

162-
rm -rdf "${output_folder}"
162+
rm -rf "${output_folder}"
163163
unset DOCKER_GRPC_LOCATION
164164
unset DOCKER_GRPC_VERSION
165165
unset output_folder
@@ -243,7 +243,7 @@ copy_directory_if_exists_valid_folder_succeeds() {
243243
mkdir -p "${destination}"
244244
copy_directory_if_exists "${source_folder}" "gapic" "${destination}/copied-folder"
245245
n_matching_folders=$(ls "${destination}" | grep -e 'copied-folder' | wc -l)
246-
rm -rdf "${destination}"
246+
rm -rf "${destination}"
247247
assertEquals 1 ${n_matching_folders}
248248
}
249249

@@ -253,7 +253,7 @@ copy_directory_if_exists_invalid_folder_does_not_copy() {
253253
mkdir -p "${destination}"
254254
copy_directory_if_exists "${source_folder}" "gapic" "${destination}/copied-folder"
255255
n_matching_folders=$(ls "${destination}" | grep -e 'copied-folder' | wc -l) || res=$?
256-
rm -rdf "${destination}"
256+
rm -rf "${destination}"
257257
assertEquals 0 ${n_matching_folders}
258258
}
259259

0 commit comments

Comments
 (0)