Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Official Bandit Images #1088

Merged
merged 12 commits into from Jan 23, 2024
54 changes: 54 additions & 0 deletions .github/workflows/build-publish-image.yml
@@ -0,0 +1,54 @@
name: Build and Publish Bandit Images

on:
release:
types: [created]

jobs:
build-and-publish:
runs-on: ubuntu-latest
permissions:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also want to do this in a specific environment for the project to make it harder for untrusted folks to publish? https://github.com/urllib3/urllib3/blob/8beb3502cf6c945485174d96d90f2f5e5929bcbd/.github/workflows/publish.yml#L15-L16 I believe urllib3 has it such that only a handful of the core maintainers can actually publish a release. I need to see if I can find Seth's blog post on the benefits

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

Could we take this as a follow up?

contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
strategy:
matrix:
python-version: ['38', '39', '310', '311', '312']
architecture: [amd64, arm64]
steps:
- name: Check out the repo
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use hashes here? I believe the OSSF score card prefers those and dependabot will still properly send updates for them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I will pass https://github.com/stacklok/frizbee against this

I was planning on introducing https://github.com/stacklok/minder at some point too, but we can discuss that on discord. With minder, we replace tags with digests as a remediation step.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Install Cosign
uses: sigstore/cosign-installer@v3.3.0
with:
cosign-release: 'v2.2.2'

- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile-py${{ matrix.python-version }}
push: true
tags: ghcr.io/${{ github.repository }}/bandit:py${{ matrix.python-version }}-${{ matrix.architecture }}
platforms: linux/${{ matrix.architecture }}

- name: Sign the image
env:
TAGS: ghcr.io/${{ github.repository }}/bandit:py${{ matrix.python-version }}-${{ matrix.architecture }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
run: |
echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
39 changes: 39 additions & 0 deletions README.rst
Expand Up @@ -83,3 +83,42 @@ https://greentreesnakes.readthedocs.org/en/latest/
Documentation of the various types of AST nodes that Bandit currently covers
or could be extended to cover:
https://greentreesnakes.readthedocs.org/en/latest/nodes.html

Container Images
----------------

Bandit is available as a container image, built within the bandit repository
using GitHub Actions. The image is available on gchr.io:
lukehinds marked this conversation as resolved.
Show resolved Hide resolved

```bash
docker pull gcr.io/pycqa/bandit/bandit:py312-arm64
lukehinds marked this conversation as resolved.
Show resolved Hide resolved
```

The image is built for the following architectures:

* amd64
* arm64

The image is tagged with the Python version and architecture, for example:

* py312-amd64
* py312-arm64

Python versions supported are:

* 3.8 (py38-amd64)
* 3.9 (py39-amd64)
* 3.10 (py310-amd64)
* 3.11 (py311-amd64)
* 3.12 (py312-amd64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tl;dr:

  • We should list supported versions without tag names or with both tag names
  • I would prefer we provide one version of Python (until we have an overwhelming demand for more versions) and it only be latest 3.12
  • I think we need a way to manually rebuild an image with the latest version of the base image to ensure security vulnerabilities are updated/patched in the image. So we'd need something like <bandit-version>-<image-version-starting-at-0-or-1>-py<ver>-<arch> for best effort of providing a secure image to users

Above we say arm64 and amd64 but here we're only listing the x86 versions.

Further, why do we want to do this for all the different versions of Python? That seems... unnecessary. I know the AST, standard-library, etc. are all different across things but the AST isn't so radically backwards incompatible that only providing an image against 3.12 would be bad.

Finally, my last concern here is that by having this many images, imagine the scenario where someone discloses a CPython vulnerability that affects everything before 3.12.(latest). If we genuinely care about what we're providing, we should be able to republish against the latest versions of the alpine images with patched CPython, but I don't think we have a good way of doing that today with this setup.

Copy link
Member Author

@lukehinds lukehinds Jan 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am good with just providing 3.12

How about I remove everything save 3.12 as amd64 / arm64 arch builds?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, just py3.12 is a nice choice. As for architectures, we never had to be concerned with it before, but now would need to with the base image. I guess now we might be excluding other architectures (https://wiki.alpinelinux.org/wiki/Architecture). That's probably okay, but who knows, there might be users on PPC64.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are very few people on ppc64 for the usecase we're carrying about here (CI/CD that relies primarily on container images). The ppc64 people are also usually very hostile (and have harassed people out of the python community) so I'm not inclined to support them anyway.


Every image is signed with sigstore cosign and it is possible to verify the
source of origin using the following cosign command:

```bash
cosign verify ghcr.io/pycqa/bandit/bandit:py39-amd64 \
--certificate-identity https://github.com/pycqa/bandit/.github/workflows/build-publish-image.yml@refs/tags/1.7.6 \
lukehinds marked this conversation as resolved.
Show resolved Hide resolved
--certificate-oidc-issuer https://token.actions.githubusercontent.com
```

Where `1.7.6` is the release version of Bandit.
lukehinds marked this conversation as resolved.
Show resolved Hide resolved
29 changes: 29 additions & 0 deletions docker/Dockerfile-py310
@@ -0,0 +1,29 @@
#
# Copyright 2024 Bandit Authors
#
# SPDX-License-Identifier: Apache-2.0
# #############################################################################
# Bandit Baseline is a tool that runs Bandit against a Git commit, and compares
# the current commit findings to the parent commit findings.
# To do this it checks out the parent commit, runs Bandit (with any provided
# filters or profiles), checks out the current commit, runs Bandit, and then
# reports on any new findings.
# #############################################################################

FROM python:3.10-alpine

# Install Git (required for pbr versioning)
RUN apk add --no-cache git

# Copy the source code into the container
COPY . /bandit

# Set the working directory
WORKDIR /bandit

# Install Bandit from the source code using pip
RUN pip install .

# Define entrypoint and default command
ENTRYPOINT ["bandit"]

29 changes: 29 additions & 0 deletions docker/Dockerfile-py311
@@ -0,0 +1,29 @@
#
# Copyright 2024 Bandit Authors
#
# SPDX-License-Identifier: Apache-2.0
# #############################################################################
# Bandit Baseline is a tool that runs Bandit against a Git commit, and compares
# the current commit findings to the parent commit findings.
# To do this it checks out the parent commit, runs Bandit (with any provided
# filters or profiles), checks out the current commit, runs Bandit, and then
# reports on any new findings.
# #############################################################################

FROM python:3.11-alpine

# Install Git (required for pbr versioning)
RUN apk add --no-cache git

# Copy the source code into the container
COPY . /bandit

# Set the working directory
WORKDIR /bandit

# Install Bandit from the source code using pip
RUN pip install .

# Define entrypoint and default command
ENTRYPOINT ["bandit"]

29 changes: 29 additions & 0 deletions docker/Dockerfile-py312
@@ -0,0 +1,29 @@
#
# Copyright 2024 Bandit Authors
lukehinds marked this conversation as resolved.
Show resolved Hide resolved
#
# SPDX-License-Identifier: Apache-2.0
# #############################################################################
# Bandit Baseline is a tool that runs Bandit against a Git commit, and compares
# the current commit findings to the parent commit findings.
# To do this it checks out the parent commit, runs Bandit (with any provided
# filters or profiles), checks out the current commit, runs Bandit, and then
# reports on any new findings.
# #############################################################################

FROM python:3.12-alpine

# Install Git (required for pbr versioning)
RUN apk add --no-cache git

# Copy the source code into the container
COPY . /bandit

# Set the working directory
WORKDIR /bandit

# Install Bandit from the source code using pip
RUN pip install .

# Define entrypoint and default command
ENTRYPOINT ["bandit"]

lukehinds marked this conversation as resolved.
Show resolved Hide resolved
29 changes: 29 additions & 0 deletions docker/Dockerfile-py38
@@ -0,0 +1,29 @@
#
# Copyright 2024 Bandit Authors
#
# SPDX-License-Identifier: Apache-2.0
# #############################################################################
# Bandit Baseline is a tool that runs Bandit against a Git commit, and compares
# the current commit findings to the parent commit findings.
# To do this it checks out the parent commit, runs Bandit (with any provided
# filters or profiles), checks out the current commit, runs Bandit, and then
# reports on any new findings.
# #############################################################################

FROM python:3.8-alpine

# Install Git (required for pbr versioning)
RUN apk add --no-cache git

# Copy the source code into the container
COPY . /bandit

# Set the working directory
WORKDIR /bandit

# Install Bandit from the source code using pip
RUN pip install .

# Define entrypoint and default command
ENTRYPOINT ["bandit"]

29 changes: 29 additions & 0 deletions docker/Dockerfile-py39
@@ -0,0 +1,29 @@
#
# Copyright 2024 Bandit Authors
#
# SPDX-License-Identifier: Apache-2.0
# #############################################################################
# Bandit Baseline is a tool that runs Bandit against a Git commit, and compares
# the current commit findings to the parent commit findings.
# To do this it checks out the parent commit, runs Bandit (with any provided
# filters or profiles), checks out the current commit, runs Bandit, and then
# reports on any new findings.
# #############################################################################

FROM python:3.9-alpine

# Install Git (required for pbr versioning)
RUN apk add --no-cache git

# Copy the source code into the container
COPY . /bandit

# Set the working directory
WORKDIR /bandit

# Install Bandit from the source code using pip
RUN pip install .

# Define entrypoint and default command
ENTRYPOINT ["bandit"]