Tuesday, 31 August 2021

Munging Dockerfiles using Bash and Jenkins

Whilst trying to mitigate an issue with a Docker image, in order to remediate a pair of CVE: -

CVE-2021-3711

CVE-2021-3712

I needed to ensure that the latest version of openssl was being used.

Now this image is based, in part, on Alpine Linux, and already included: -

FROM alpine:3.14.1 AS run

...

RUN apk --no-cache add openssl

which *should* mean that I'd be getting the required version of openssl as advised by the two CVEs, namely: -

OpenSSL 1.1.1l

and yet I was still seeing the issues when scanning the resulting image using IBM Container Registry's Vulnerability Advisor tool.

I even added: -

RUN apk info --all openssl

to the Dockerfile, which returned: -

openssl-1.1.1l-r0 description:
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.14/main: No such file or directory
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.14/community: No such file or directory
Toolkit for Transport Layer Security (TLS)
openssl-1.1.1l-r0 webpage:
https://www.openssl.org/
openssl-1.1.1l-r0 installed size:
660 KiB
openssl-1.1.1l-r0 depends on:
so:libc.musl-x86_64.so.1
so:libcrypto.so.1.1
so:libssl.so.1.1
openssl-1.1.1l-r0 provides:
cmd:openssl
openssl-1.1.1l-r0 is required by:
openssl-1.1.1l-r0 contains:
usr/bin/openssl
openssl-1.1.1l-r0 triggers:
openssl-1.1.1l-r0 has auto-install rule:
openssl-1.1.1l-r0 affects auto-installation of:
openssl-1.1.1l-r0 replaces:
libressl
openssl-1.1.1l-r0 license:
OpenSSL

After much tinkering, I came to the realisation that there's more to life than just apk add, namely there's a need to (a) update the Alpine repository sources and (b) upgrade Alpine itself ...

In the Ubuntu world, this would achieved by apt get update && apt-get upgrade -y

In the Alpine world, this is achieved by apk update && apk upgrade

Therefore, I amended my Dockerfile from: -

RUN apk --no-cache add openssl

to: -

RUN apk update && apk upgrade && apk --no-cache add openssl

which did the trick

However, because I'm building the image using Jenkins, via a Bash script wrapped up in a Groovy script ( the Jenkinsfile ), I needed to do some escape magic.

I started with this: -

sed -i'' "s/RUN apk \-\-no-cache add openssl/RUN apk update \&\& apk upgrade \&\& apk \-\-no-cache add openssl/g" Dockerfile

but the Jenkins job failed with: -

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 22: unexpected char: '\' @ line 22, column 41.
             sed -i'' "s/RUN apk \-\-no-cac


Now I was going a little bit OTT with the escape characters, as I didn't really need to escape out the hyphens ( - ) but the same problem occurred with this: -

sed -i'' "s/RUN apk --no-cache add openssl/RUN apk update \&\& apk upgrade \&\& apk --no-cache add openssl/g" Dockerfile

because I'd forgotten that escaping in Bash in Groovy has its own set of peculiar rules ...

TL;DR; I needed to double escape ...

sed -i'' "s/RUN apk --no-cache add openssl/RUN apk update \\&\\& apk upgrade \\&\\& apk --no-cache add openssl/g" Dockerfile

With this in place, all is good - the build runs smoothly AND the resulting image is clean and green ...


No comments:

Yay, VMware Fusion and macOS Big Sur - no longer "NAT good friends" - forgive the double negative and the terrible pun ...

After macOS 11 Big Sur was released in 2020, VMware updated their Fusion product to v12 and, sadly, managed to break Network Address Trans...