diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2efcc6143..854dced3d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,6 +81,7 @@ jobs: outputs: do_release: ${{ env.DO_RELEASE }} + do_prod_release: ${{ env.DO_PROD_RELEASE }} do_dev_release: ${{ env.DO_DEV_RELEASE }} release_tag: ${{ env.RELEASE_TAG }} @@ -248,6 +249,56 @@ jobs: with: path: ./artifacts name: combined-artifacts + + # For now, we only publish fcli-scratch image, but we do build the other images just for testing + docker-linux: + needs: [native_linux] + runs-on: ubuntu-latest + env: + DOCKER_SRC: fcli-other/fcli-docker/linux + steps: + - name: Check-out source code + uses: actions/checkout@v4 + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: ./artifacts + name: fcli-linux + + - name: Build Linux images + run: | + tar -zxvf ./artifacts/release-assets/fcli-linux.tgz -C ${DOCKER_SRC} + cd ${DOCKER_SRC} + docker build . --target fcli-scratch -t fcli-scratch + docker build . --target fcli-alpine -t fcli-alpine + docker build . --target fcli-ubi9 -t fcli-ubi9 + + - name: Docker Login + if: needs.build.outputs.do_release + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: DEV - Tag Linux images + if: needs.build.outputs.do_prod_release + run: | + docker tag fcli-scratch fortifydocker/fcli:${RELEASE_TAG} + + - name: PROD - Tag Linux images + if: needs.build.outputs.do_prod_release + run: | + docker tag fcli-scratch fortifydocker/fcli:latest + docker tag fcli-scratch fortifydocker/fcli:${{steps.create_prod_release.outputs.major}} + docker tag fcli-scratch fortifydocker/fcli:${{steps.create_prod_release.outputs.major}}.${{steps.create_prod_release.outputs.minor}} + docker tag fcli-scratch fortifydocker/fcli:${RELEASE_VERSION} + + # TODO Should we sign the images as well? + - name: Publish Linux Docker images + if: needs.build.outputs.do_release + run: | + docker push --all-tags fortifydocker/fcli release: name: release diff --git a/fcli-other/fcli-docker/linux/.gitignore b/fcli-other/fcli-docker/linux/.gitignore new file mode 100644 index 0000000000..dbb0b8442f --- /dev/null +++ b/fcli-other/fcli-docker/linux/.gitignore @@ -0,0 +1 @@ +fcli diff --git a/fcli-other/fcli-docker/linux/Dockerfile b/fcli-other/fcli-docker/linux/Dockerfile new file mode 100644 index 0000000000..99e4fced95 --- /dev/null +++ b/fcli-other/fcli-docker/linux/Dockerfile @@ -0,0 +1,78 @@ +# This Dockerfile defines the following targets for building an fcli fcli Docker image: +# - fcli-alpine +# - fcli-ubi9 +# - fcli-scratch +# You can select between these variants by passing the --target option to the 'docker build' +# command, for example 'docker build . --target fcli-alpine'. If no target is specified, all +# targets may be built but the final image will correspond to the fcli-scratch target. +# +# In general, the fcli-scratch image is preferred to avoid having to deal with any CVEs reported +# on the base images, and potentially having to provide refreshed images for older fcli versions +# to fix such CVEs. Potentially, we could add commands to upgrade all base OS packages to reduce +# the number of CVEs on those packages, in case the base image doesn't include those upgraded +# packages yet. +# +# For now, we're only automatically publishing the fcli-scratch image for the reasons above; if +# there's any demand, we can also publish ubi9, alpine and/or other (like busybox) images that +# include a shell. Primary advantage is that this would allow for running a sequence of fcli +# commands in a single container invocation (potentially removing the need to mount the data +# directory to a persistent volume/host directory, as fcli state will be stored inside the container +# for as long the container is alive). Primary disadvantage is that users might expect to be able to +# run something like the following: +# fcli tool sc-client install +# scancentral package ... +# submit scan request, ... +# However, these images don't include Java (required to run ScanCentral Client) nor any other +# build tools (which may be required by ScanCentral Client to properly package application source +# code). Users would need to build a custom image that includes fcli and any other tools required +# for building/packaging an application, or alternatively any of the fcli Docker images can be +# used to install ScanCentral Client on the host system (using proper volume mappings), from +# where it can be run with (presumably) all relevant build tools and Java being available. +# +# Before running the 'docker build' command, the fcli executable to be included in the image +# must be copied into the same directory as this Dockerfile. The fcli build process will +# automatically take care of this when releasing a new fcli version. For manual testing of +# this Dockerfile, you can safely copy fcli 2.5.4 or above into your workspace; the .gitignore +# file will have git operations ignore the fcli executable. +# +# All of the targets defined below have more or less the same structure: +# - Add fcli user to /etc/passwd +# - Add fcli executable to the image +# - Add /data (and /tmp for fcli-scratch) directories with 777 permissions to the image +# - Set WORKDIR to /data +# - Set FCLI_USER_HOME to /data +# - Set container user to fcli user +# - Define an appropriate entrypoint (fcli for fcli-scratch, shell for others) +# +# Regarding FCLI_USER_HOME, fcli uses user.home by default, but if the Docker container is being +# run as a different user through 'docker run -u :', user.home returns a directory +# containing a '?' to represent unknown user name for the given UID, which causes issues. Fcli +# versions 2.5.4 and up allow for overriding user.home through FCLI_USER_HOME. + +FROM alpine:3 AS fcli-alpine +RUN echo "fcli:x:10001:10001:fcli:/data:/sbin/nologin" >> /etc/passwd +ADD fcli /bin/fcli +ADD data.tgz / +WORKDIR /data +ENV FCLI_USER_HOME=/data +USER fcli +ENTRYPOINT ["/bin/sh"] + +FROM redhat/ubi9-minimal:9.4 AS fcli-ubi9 +RUN echo "fcli:x:10001:10001:fcli:/data:/sbin/nologin" >> /etc/passwd +ADD fcli /bin/fcli +ADD data.tgz / +WORKDIR /data +ENV FCLI_USER_HOME=/data +USER fcli +ENTRYPOINT ["/bin/bash"] + +FROM scratch AS fcli-scratch +ADD minimal-passwd /etc/passwd +ADD fcli /bin/fcli +ADD tmp.tgz / +ADD data.tgz / +WORKDIR /data +ENV FCLI_USER_HOME=/data +USER fcli +ENTRYPOINT ["/bin/fcli"] diff --git a/fcli-other/fcli-docker/linux/data.tgz b/fcli-other/fcli-docker/linux/data.tgz new file mode 100644 index 0000000000..ce9a9f34ca Binary files /dev/null and b/fcli-other/fcli-docker/linux/data.tgz differ diff --git a/fcli-other/fcli-docker/linux/minimal-passwd b/fcli-other/fcli-docker/linux/minimal-passwd new file mode 100644 index 0000000000..4c9d66c59d --- /dev/null +++ b/fcli-other/fcli-docker/linux/minimal-passwd @@ -0,0 +1 @@ +fcli:x:10001:10001:fcli:/data:/sbin/nologin \ No newline at end of file diff --git a/fcli-other/fcli-docker/linux/tmp.tgz b/fcli-other/fcli-docker/linux/tmp.tgz new file mode 100644 index 0000000000..cace2f3c08 Binary files /dev/null and b/fcli-other/fcli-docker/linux/tmp.tgz differ diff --git a/fcli-other/fcli-docker/windows/.gitignore b/fcli-other/fcli-docker/windows/.gitignore new file mode 100644 index 0000000000..5aca0b1879 --- /dev/null +++ b/fcli-other/fcli-docker/windows/.gitignore @@ -0,0 +1 @@ +fcli.exe diff --git a/fcli-other/fcli-docker/windows/Dockerfile b/fcli-other/fcli-docker/windows/Dockerfile new file mode 100644 index 0000000000..c722ed9464 --- /dev/null +++ b/fcli-other/fcli-docker/windows/Dockerfile @@ -0,0 +1,46 @@ +# This Dockerfile allows for building a Windows-based fcli image. Although functional, for now +# this is considered just a prototype and not automatically published; we can fine-tune and +# publish if there's any demand for a Windows-based image. Note that may suffer from some of +# the same issues regarding base OS CVEs and ability run run ScanCentral Client as detailed in +# the Linux Dockerfile. +# +# Some questions to be answered (also see more detailed comments on the actual Dockerfile instructions): +# - What base image to use for the final image; nanoserver, servercore, ...? +# - Any improvements necessary for VC++ redistributables installation? +# - Should container run as ContainerUser, or should we create fcli user like for the Linux images? +# - Should we have fcli.exe or CMD.exe as entry point (or both)? +# +# Before running the 'docker build' command, the fcli Windows executable to be included in the +# image must be copied into the same directory as this Dockerfile. If we decide to automatically +# release Windows-based images, the fcli build process will automatically take care of this when +# releasing a new fcli version. For manual testing of this Dockerfile, you can safely copy fcli.exe +# 2.5.4 or above into your workspace; the .gitignore file will have git operations ignore the fcli +# executable. + +# Install Visual C++ redistributables; this requires at least servercore and will fail on nanoserver, +# hence we do this in a separate build phase. +FROM mcr.microsoft.com/windows/servercore:ltsc2022 as installer +ADD https://aka.ms/vs/17/release/vc_redist.x64.exe /vc_redist.x64.exe +RUN /vc_redist.x64.exe /install /quiet /norestart + +# Build fcli nanoserver-based image. We manually copy any VC++ DLLs required by fcli into this image +# from the installer phase above. This process is somewhat fragile and may break the image if a future +# fcli version requires additional VC++ DLLs but we forget to update the Dockerfile to copy them. We +# may want to add an instruction like 'RUN fcli -h' instruction after installing fcli, to ensure fcli +# can run successfully with the manually copied set of DLLs. +FROM mcr.microsoft.com/windows/nanoserver:ltsc2022 AS fcli-ltsc2022 +COPY --from=installer C:/Windows/System32/vcruntime140.dll C:/Windows/System32/vcruntime140.dll +COPY --from=installer C:/Windows/System32/vcruntime140_1.dll C:/Windows/System32/vcruntime140_1.dll +ADD fcli.exe C:/bin/fcli.exe +ADD data.tgz C:/ +WORKDIR C:/data +ENV FCLI_USER_HOME=C:/data +USER ContainerUser +# TODO, do we want to have the image have fcli as the entrypoint to mimic behavior of the fcli-scratch +# Linux image, or CMD.exe as the entrypoint to mimic behavior of the shell-based Linux images? Maybe +# we want to have both, in which case we'd remove the ENTRYPOINT instruction here, and move it two +# two new build stages that use this build phase as the base image, just adding the applicable ENTRYPOINT +# (and PATH for CMD.exe-based image) to those new build stages. +# ENV PATH=$PATH:C:\bin # Only for interactive shell image? Might also be useful for fcli entrypoint, as +# # users may override the entrypoint to CMD.exe. +ENTRYPOINT ["C:\\bin\\fcli.exe"] diff --git a/fcli-other/fcli-docker/windows/data.tgz b/fcli-other/fcli-docker/windows/data.tgz new file mode 100644 index 0000000000..ce9a9f34ca Binary files /dev/null and b/fcli-other/fcli-docker/windows/data.tgz differ