Skip to content
This repository has been archived by the owner on Sep 19, 2021. It is now read-only.

A missing *secure* link between Quay.io build triggers and Github Action's repository_dispatch events

License

Notifications You must be signed in to change notification settings

lewagon/quay-github-actions-dispatch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Quay Github Actions Dispatch

A mini-service for securely forwarding Quay build notifications to Github Actions' obscure repository_dispatch webhook to trigger any workflow in your repository remotely as a "callback" on successful image build.

It combines the speed and caching efficiency of Quay.io for building your production Docker images with the "I don't ever need another CI/CD tool" promise of Github Actions.

Here's how it works:

+-------------+                                      +---------+
| GitHub Repo +--------+build trigger👷‍+------------>+ Quay.io |
+------+------+                                      +-----+---+
       ^                                                   |
       |                                                   |
       |                                                   |
       |                                      Webhook      |
       |                                      success      |
       |  Triggers                            notification |
       |  Github Actions                      over HTTPS   |
       |  workflow👌                                       |
       |                                                   |
       |               +-----------------+                 |
       +---------------+ This service :) +<----------------+
                       +-----------------+

                        Verifies authenticity
                        through Quay's SSL cert 🔑

Usage

Running your own quay-github-actions-dispatch endpoint

It is recommended to run this service on a dedicated VPS with no load balancer or reverse proxy and an open 443 port. You should also obtain a certificate for a domain name you will put your endpoint on as Quay needs to send you a webhook over HTTPS (otherwise you will not be able to authenticate through SSL) and point this domain name to your VPS' IP address.

⚠️ quay-github-actions-dispatch performs it's own SSL termination to read Quay's certificate and it needs access to relevant .pem and .key files.

On the server with a 443 port exposed and certificates for domain name set up:

 docker run -d --rm -p 443:443 \
 -v /certs:/certs \                # /certs folder on your host needs to have .key and .pem files
 -e GH_TOKEN=YOUR_GITHUB_TOKEN \   # token needs only `repo:read` access
 -e DEBUG=true \                  # optional to log incoming and outgoing requests and responses
 lewagon/quay-github-actions-dispatch:0.2

In your Quay repository settings, under "Events and Notifications" create a "Webhook POST" notification for "Dockerfile Build Successfully Completed" and provide https://YOUR_CERTIFIED_DOMAIN.com/incoming endpoint.

Incoming payload

{
  "build_id": "fake-build-id",
  "trigger_kind": "GitHub",
  "name": "your_repo_name",
  "repository": "your_github/your_repo_name",
  "namespace": "your_repo_name",
  "docker_url": "quay.io/your_github/your_repo_name",
  "trigger_id": "1245634",
  "docker_tags": [
    "latest",
    "foo",
    "bar"
  ],
  "build_name": "some-fake-build",
  "image_id": "1245657346",
  "trigger_metadata": {
    "default_branch": "master",
    "ref": "refs/heads/somebranch",
    "commit": "42d4a62c53350993ea41069e9f2cfdefb0df097d"
  },
  "homepage": "https://quay.io/your_github/your_repo_name/your_repo_name/build/fake-build-id"
}

Outgoing payload

Will be sent to https://api.github.com/repos/your_github/your_repo/dispatches

{
  "event_type": "QUAY_BUILD_SUCCESS",
  "client_payload": {
    "text": "42d4a62"
  }
}

"text" field will contain first 7 chars of your commit SHA from the incoming payload

The service wil also set the headers that Github requires:

Authorization: token your-token-here
Accept: application/vnd.github.everest-preview+json

Token will be read from the ENV variable GH_TOKEN that you can set to your GitHub token value with the repo:read scope.

Workflow example to trigger on QUAY_BUILD_SUCCESS event

Deploy to Digital Ocean managed Kubernetes with Helm 3

name: Helm deploy all things
on:
  repository_dispatch:
    types: [QUAY_BUILD_SUCCESS]

jobs:
  build:
    if: startsWith(github.sha, github.event.client_payload.text)
    name: Helm update
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master

      - name: Save DigitalOcean kubeconfig
        uses: digitalocean/action-doctl@master
        env:
          DIGITALOCEAN_ACCESS_TOKEN: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
        with:
          args: kubernetes cluster kubeconfig show CLUSTER_NAME > $GITHUB_WORKSPACE/.kubeconfig

      - name: Upgrade/install chart
        run: |
        export KUBECONFIG=$GITHUB_WORKSPACE/.kubeconfig && \
        helm upgrade your_release charts/chart_name --install \
        --atomic --cleanup-on-fail \
        --set-string image.tag=$(echo $GITHUB_SHA | head -c7) \

Why?

  • Containers are awesome. Kubernetes makes them even more awesome.
  • Github Actions are awesome, but it's not possible to cache Docker builds, so bigger production images can take long (10 mins+) to build.
  • Quay is awesome: easy to trigger a build from a push to any branch on GitHub and label an image either with a branch name or a commit SHA. Builds are cached and it takes very little time to build a new image, if the only layer changed is your COPY . /myawesomeapp. There is even a possibility to send a POST request to any webhook if the build has started/succeeded/failed. However, there is no control over headers or a body of that POST request.
  • Github Actions workflows can be triggered by the external repository_dispatch event, but GitHub HTTP API expects very certain payload with very certain headers.
  • Imagine the world where Quay could send a webhook POST directly to GitHub and trigger a workflow in your repo if the image was successfully built.

quay-github-actions-dispatch is exactly that ☝️ missing link.

How

Easy, you think, just let me code an endpoint that receives a webhook payload from Quay and transforms it into a webhook request for GitHub.

Not so fast!

Quay notifications bare no authentication, so anyone simulating the Quay payload could trigger events directly in your repo and this is definitely not what you want. However:

When the URL is HTTPS, the call will have an SSL client certificate set from Quay.io. Verification of this certificate will prove the call originated from Quay.io. —Quay.io Repository Notifications Manual

This is exactly what quay-github-actions-dispatch does: verifies that Quay is indeed Quay by looking at it's TLS peer certificate

Build your own Docker image from source

Use latest versions of Go with built-in modules support

git clone git@github.com:lewagon/quay-github-actions-dispatch.git
cd quay-github-actions-dispatch
GOOS=linux GOARCH=amd64 go build .  # assuming you use a Linux server
docker build -t IMAGE:TAG .

About

A missing *secure* link between Quay.io build triggers and Github Action's repository_dispatch events

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages