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

Image Signing #9

Merged
merged 6 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Release to Production

on:
push:
branches: [ main ]
branches: [main]

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down Expand Up @@ -43,7 +43,6 @@ jobs:
if: ${{ steps.version.outputs.VERSION != ''}}
uses: docker/setup-buildx-action@v2


- name: Login to GHCR
if: ${{ steps.version.outputs.VERSION != ''}}
uses: docker/login-action@v1
Expand All @@ -54,14 +53,31 @@ jobs:

- name: Build and Push Docker Image
if: ${{ steps.version.outputs.VERSION != ''}}
id: build-and-push
uses: docker/build-push-action@v2
with:
context: .
build-args: VERSION=${{steps.version.outputs.VERSION}}
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/${{ github.repository }}:${{steps.version.outputs.VERSION}}


- uses: sigstore/[email protected]

- name: Image Signing
run: |
cosign sign --yes \
-a "repo=${{ github.repository }}" \
-a "workflow=${{ github.workflow }}" \
-a "ref=${{ github.sha }}" \
-a "owner=Spectro Cloud" \
--key env://COSIGN_PRIVATE_KEY --recursive "${TAGS}@${DIGEST}"
env:
TAGS: ghcr.io/${{ github.repository }}:${{steps.dependencies.outputs.VERSION}}
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}

release:
name: "Release"
needs: [docker]
Expand All @@ -82,4 +98,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx semantic-release
npx semantic-release
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ hello-universe-api
node_modules/

.env*
VERSION*
VERSION*

## Security

cosign.key
2 changes: 2 additions & 0 deletions .releaserc.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Copyright (c) HashiCorp, Inc.

branches: [main]
repositoryUrl: https://github.com/spectrocloud/hello-universe-api
plugins:
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Catch All Rule
* @spectrocloud/education-engineers
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Copyright (c) HashiCorp, Inc.

FROM golang:1.20.2-alpine3.17 as builder
WORKDIR /go/src/app
COPY . .
Expand Down
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.PHONY: license


VERSION:=1.0.0

Expand All @@ -21,4 +23,9 @@ ci-tests: build docker-pull-db docker-run-db

start-server: build docker-pull-db docker-run-db
sleep 3
./hello-universe-api
./hello-universe-api


license: ## Adds a license header to all files. Reference https://github.com/hashicorp/copywrite to learn more.
@echo "Applying license headers..."
copywrite headers
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)

# Hello Universe API

A Spectro Cloud demo application. This is the API server for the [Hello Universe](https://github.com/spectrocloud/hello-universe) app.
Expand All @@ -9,6 +9,7 @@ A Spectro Cloud demo application. This is the API server for the [Hello Universe
</p>

# Overview

The [Hello Universe](https://github.com/spectrocloud/hello-universe) app includes an API server that expands the capabilities of the application. The API server requires a Postgres database to store and retrieve data. Use the [Hello Universe DB](https://github.com/spectrocloud/hello-universe-db) container for simple integration with a Postgres database.

# Endpoints
Expand All @@ -17,7 +18,7 @@ A Postman collection is available to help you explore the API. Review the [Postm

# Usage

The quickest method to start the API server locally is by using the Docker image.
The quickest method to start the API server locally is by using the Docker image.

```shell
docker pull ghcr.io/spectrocloud/hello-universe-api:1.0.9
Expand All @@ -30,18 +31,17 @@ To start the API server you must have connectivity to a Postgres instance. Use [

The API server accepts the following environment variables.

| Variable | Description | Default |
|-------------|----------------------------------------------------|-----------|
| `PORT` | The port number the application will listen on. | `3000` |
| `HOST` | The host value name the API server will listen on. | `0.0.0.0` |
| `DB_NAME` | The database name. | `counter` |
| `DB_USER` | The database user name to use for queries. | `postgres` |
| `DB_HOST` | The hostname or url to the database. | `0.0.0.0` |
| `DB_PASSWORD` | The database password. | `password` |
| `DB_ENCRYPTION`| The Postgres [ssl mode](https://www.postgresql.org/docs/current/libpq-ssl.html) behavior to enable. Allowed values are: `require`, `verify-full`, `verify-ca`, or `disable` |`disable`|
| `DB_INIT` | Set to `true` if you want the API server to create the required database schema and tables in the target database.| `false` |
| `AUTHORIZATION` | Set to `true` if you want the API server to require authorization tokens in the request.| `false` |

| Variable | Description | Default |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `PORT` | The port number the application will listen on. | `3000` |
| `HOST` | The host value name the API server will listen on. | `0.0.0.0` |
| `DB_NAME` | The database name. | `counter` |
| `DB_USER` | The database user name to use for queries. | `postgres` |
| `DB_HOST` | The hostname or url to the database. | `0.0.0.0` |
| `DB_PASSWORD` | The database password. | `password` |
| `DB_ENCRYPTION` | The Postgres [ssl mode](https://www.postgresql.org/docs/current/libpq-ssl.html) behavior to enable. Allowed values are: `require`, `verify-full`, `verify-ca`, or `disable` | `disable` |
| `DB_INIT` | Set to `true` if you want the API server to create the required database schema and tables in the target database. | `false` |
| `AUTHORIZATION` | Set to `true` if you want the API server to require authorization tokens in the request. | `false` |

## Authorization

Expand All @@ -57,4 +57,8 @@ Ensure all API requests have an `Authorization` header with the Bearer token.
```shell
curl --location --request POST 'http://localhost:3000/api/v1/counter' \
--header 'Authorization: Bearer 931A3B02-8DCC-543F-A1B2-69423D1A0B94'
```
```

## Image Verification

We sign our images through [Cosign](https://docs.sigstore.dev/signing/quickstart/). Review the [Image Verification](./docs/image-verification.md) page to learn more.
4 changes: 4 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* Copyright (c) HashiCorp, Inc.
*/

module.exports = {
extends: [
'@commitlint/config-conventional'
Expand Down
81 changes: 81 additions & 0 deletions docs/image-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Image Verification

The Hello Universe container image is signed using [Sigstore's](https://sigstore.dev/) Cosign. The container image is signed using a cryptographic key pair that is private and stored internally. The public key is available in the official Spectro Cloud documentation repository at [**static/cosign.pub**](https://raw.githubusercontent.com/spectrocloud/librarium/master/static/cosign.pub). Use the public key to verify the authenticity of the container image. You can learn more about the container image signing process by reviewing the [Signing Containers](https://docs.sigstore.dev/signing/signing_with_containers) documentation page.
karl-cardenas-coding marked this conversation as resolved.
Show resolved Hide resolved

> [!NOTE]
> Cosign generates a key pair that uses the ECDSA-P256 algorithm for the signature and SHA256 for hashes. The keys are stored in PEM-encoded PKCS8 format.

Use the following command to verify the authenticity of the container image. Replace the image tag with the version you want to verify.

```shell
cosign verify --key https://raw.githubusercontent.com/spectrocloud/librarium/master/static/cosign.pub \
docker pull ghcr.io/spectrocloud/hello-universe-api:1.0.10
```

If the container image is valid, the following output is displayed. The example output is formatted using `jq` to improve readability.

```shell hideClipboard
Verification for ghcr.io/spectrocloud/hello-universe-api:1.0.10 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The signatures were verified against the specified public key
[
{
"critical": {
"identity": {
"docker-reference": "ghcr.io/spectrocloud/hello-universe-api:1.0.10"
},
"image": {
"docker-manifest-digest": "sha256:285a95a8594883b3748138460182142f5a1b74f80761e2fecb1b86d3c9b9d191"
},
"type": "cosign container image signature"
},
"optional": {
"Bundle": {
"SignedEntryTimestamp": "MEYCIQCZ6FZzNB5wA9+W/lF57jx0qTaszZhg5FxJiBmgIFxPVwIhANnoQQ5gqjr1h93LCq1Td8BohqrxxIvfrXTnT1tYR4i7",
"Payload": {
"body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI0MzU0MzFjNjY1Y2Y2ZGZjYzM0NzI2YWRkNjAzMDVjYjZlMzhlNjVkZmJlMWQ0NWU2ZGVkM2IzNzg3NTYwY2MxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUM0TFFxYVFDclhOc0VzdkI0ZE84bmtZSWg0L3o5UzdScGVEdUZnUDJwbDJ3SWdOdEJsNElDaHBmT3RnVDBlNW5QTmRMYWt4RTJHcnFFK0tjV1JXSGZPTnpnPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGV1VoeVl6SlhTVVV6WVhCTFRHMWplR3hHUmtoNVZsRkRVVnBYYUFveUsyRnNOVmN2Vmsxc1VISXpkVFJGV2k5V0wwZFBRbTAySzFrNVowWXpWWE16ZEhkMVpWaFpaMlJaWlVadk5XODNRbFZ1TnpCTlVGQjNQVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=",
"integratedTime": 1702758491,
"logIndex": 57230483,
"logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
}
},
"owner": "Spectro Cloud",
"ref": "e597f70be238369ce4f0e5778492a155e23fec17",
"repo": "spectrocloud/hello-universe-api",
"workflow": "Release"
}
}
]
```

> [!CAUTION]
> Do not use the container image if the authenticity cannot be verified. Verify you downloaded the correct public key and that the container image is from `ghcr.io/spectrocloud/hello-universe-api`.

If the container image is not valid, an error is displayed. The following example shows an error when the container image is not valid.

```shell hideClipboard
cosign verify --key https://raw.githubusercontent.com/spectrocloud/librarium/master/static/cosign.pub \
ghcr.io/spectrocloud/hello-universe-api:1.0.9
```

```shell hideClipboard
Error: no matching signatures: error verifying bundle: comparing public key PEMs, expected -----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEheVfGYrVn2mIUQ4cxMJ6x09oXf82
zFEMG++p4q8Mf+y2gp7Ae4oUaXk6Q9V7aVjjltRVN6SQcoSASxf2H2EpgA==
-----END PUBLIC KEY-----
, got -----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYHrc2WIE3apKLmcxlFFHyVQCQZWh
2+al5W/VMlPr3u4EZ/V/GOBm6+Y9gF3Us3twueXYgdYeFo5o7BUn70MPPw==
-----END PUBLIC KEY-----

main.go:69: error during command execution: no matching signatures: error verifying bundle: comparing public key PEMs, expected -----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEheVfGYrVn2mIUQ4cxMJ6x09oXf82
zFEMG++p4q8Mf+y2gp7Ae4oUaXk6Q9V7aVjjltRVN6SQcoSASxf2H2EpgA==
-----END PUBLIC KEY-----
, got -----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYHrc2WIE3apKLmcxlFFHyVQCQZWh
2+al5W/VMlPr3u4EZ/V/GOBm6+Y9gF3Us3twueXYgdYeFo5o7BUn70MPPw==
-----END PUBLIC KEY-----
```
2 changes: 2 additions & 0 deletions endpoints/counterRoute.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package endpoints

import (
Expand Down
2 changes: 2 additions & 0 deletions endpoints/healthRoute.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package endpoints

import (
Expand Down
2 changes: 2 additions & 0 deletions endpoints/types.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package endpoints

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/authorization.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package internal

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/authorization_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package internal

import "testing"
Expand Down
2 changes: 2 additions & 0 deletions internal/constants.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package internal

const (
Expand Down
2 changes: 2 additions & 0 deletions internal/database.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package internal

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/helpers.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package internal

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/log.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package internal

import (
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c) HashiCorp, Inc.

package main

import (
Expand Down
Loading