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
63 changes: 63 additions & 0 deletions .github/workflows/build-publish-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Build and Publish Bandit Images

on:
release:
types: [created]
schedule:
- cron: '0 0 * * 0' # Every Sunday at midnight
workflow_dispatch:

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
id-token: write

steps:

- name: Get latest release tag
if: github.event_name != 'release'
id: get-latest-tag
run: |
TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name)
echo "Latest tag is $TAG"
echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV
Copy link
Member

Choose a reason for hiding this comment

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

I've never seen this construct before, is it possible that GITHUB_ENV does not have a terminating \n in it? Is that potentially something someone could exploit to publish unreleased code?

Copy link
Member Author

Choose a reason for hiding this comment

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


- name: Check out the repo
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'release' && github.ref || env.RELEASE_TAG }}
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if after this we should set something up for adding to the docker image as a label. But we can probably do that as a fast follow to this change


- 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
push: true
tags: ghcr.io/${{ github.repository }}/bandit:latest
Copy link
Member

Choose a reason for hiding this comment

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

We can specify a list here, do we want to try to do that?

For example, we could do use the current date too so that we're tagging both latest and the current date, e.g., 2024-01-08 to help with folks wanting stable-ish tags.

Copy link
Member

Choose a reason for hiding this comment

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

I also don't see us including the version of Bandit here but maybe that's because we are using the same action on a schedule and for releases?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, also, if we're doing this on a schedule like this, does that mean we're publishing the head of main every week? Do we want to ensure we're only publishing the last released version with the new image?

Copy link
Member Author

Choose a reason for hiding this comment

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

That is actually a very good point, with a schedule we end up pushing main and not a release (I am not at my best this morning!). Let me dwell on if there is a better method for this (I am not sure there is) unless we get into trying to predict what the last release was

Copy link
Member Author

Choose a reason for hiding this comment

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

I also thought it best to not use bandit releases, latest should always be usable.

Copy link
Member

Choose a reason for hiding this comment

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

I wonder, also if we want to add labels here to the image, e.g., git_commit=... and version=... and maybe org.pycqa.bandit.version=... equivalents?

If we're running a schedule, could we find the latest tag, check that out and rebuild? I assume the scheduled rebuild is to address vulnerabilities in the base image like I raised as a concern?

Copy link
Member Author

Choose a reason for hiding this comment

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

Getting back on to this , apologies for the haitus.

If we're running a schedule, could we find the latest tag, check that out and rebuild? I assume the scheduled rebuild is to address vulnerabilities in the base image like I raised as a concern?

Yes, this rebuild the entire image every sunday at midnight. This covers off any CVEs in the base image that have collected since our last release.

I am going to push another commit now with a workflow_dispatch. this will allow us to manually start the action if anything particular comes out nasty between the scheduled runs.

platforms: linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v8

- name: Sign the image
env:
TAGS: ghcr.io/${{ github.repository }}/bandit:latest
DIGEST: ${{ steps.build-and-push.outputs.digest }}
run: |
echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
34 changes: 34 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,37 @@ 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 ghcr.io:

```bash
docker pull ghcr.io/pycqa/bandit/bandit
```

The image is built for the following architectures:

* amd64
* arm64
* armv7
* armv8

To pull a specific architecture, use the following format:

```bash
docker pull --platform=<architecture> ghcr.io/pycqa/bandit/bandit:latest
```

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/<version> \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
```

Where `<version>` is the release version of Bandit.
16 changes: 16 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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"]