• Stars
    star
    190
  • Rank 203,739 (Top 5 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created almost 3 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simple mac binary signing from any platform

Quill

Simple mac binary signing and notarization from any platform (replacing the codesign utility for simple use cases).

quill-demo

$ quill sign-and-notarize --p12 [path-to-p12] [path-to-unsigned-binary]

Installation

curl -sSfL https://raw.githubusercontent.com/anchore/quill/main/install.sh | sh -s -- -b /usr/local/bin

... or, you can specify a release version and destination directory for the installation:

curl -sSfL https://raw.githubusercontent.com/anchore/quill/main/install.sh | sh -s -- -b <DESTINATION_DIR> <RELEASE_VERSION>

Usage

First you need to download the signing private key and certificate from Apple (this is in the form of a ".p12" file).

# run on **any platform** to sign the binary

$ export QUILL_SIGN_P12=[path-to-p12]         # can also be base64 encoded contents instead of a file path
$ export QUILL_SIGN_PASSWORD=[p12-password]

$ quill sign [path/to/binary]

Note: The signing certificate must be issued by Apple and the full certificate chain must be available at signing time. See the section below on "Attaching the full certificate chain" if you do not wish to rely on the Apple intermediate and root certificates embedded into the Quill binary.

After signing you can notarize the binary against Apple's notary service:

$ export QUILL_NOTARY_KEY=[path-to-private-key-file-from-apple]   # can also be base64 encoded contents instead of a file path
$ export QUILL_NOTARY_KEY_ID=[apple-private-key-id]               # e.g. XS319FABCD
$ export QUILL_NOTARY_ISSUER=[apple-notary-issuer-id]             # e.g. a1234b5-1234-5f5d-b0c8-1234bedc5678

$ quill notarize [path/to/binary]

...or you can sign and notarize in one step:

$ quill sign-and-notarize [path/to/binary]

Here's an example of using quill with goreleaser:

# .goreleaser.yml
builds:
  - binary: my-app
    goos:
      - darwin
    goarch:
      - amd64
      - arm64
    hooks:
      post:
        # The binary is signed and notarized when running a production release, but for snapshot builds notarization is
        # skipped and only ad-hoc signing is performed (not cryptographic material is needed).
        #
        # note: environment variables required for signing and notarization (set in CI) but are not needed for snapshot builds
        #    QUILL_SIGN_P12, QUILL_SIGN_PASSWORD, QUILL_NOTARY_KEY, QUILL_NOTARY_KEY_ID, QUILL_NOTARY_ISSUER
        - cmd: quill sign-and-notarize "{{ .Path }}" --dry-run={{ .IsSnapshot }} --ad-hoc={{ .IsSnapshot }} -vv
          env:
            - QUILL_LOG_FILE=/tmp/quill-{{ .Target }}.log

Attaching the full certificate chain

In order to pass notarization with Apple you must use:

  1. A signing certificate that is issued by Apple
  2. Have the full certificate chain available at signing time

Without the full chain, Apple will reject the notarization request with the following error:

{
  "issues": [
    {
      "severity": "error",
      "code": null,
      "message": "The signature of the binary is invalid.",
      "docUrl": "https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/resolving_common_notarization_issues#3087735"
    },
    {
      "severity": "error",
      "code": null,
      "message": "The signature does not include a secure timestamp.",
      "docUrl": "https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/resolving_common_notarization_issues#3087733"
    }
  ]
}

Quill can attach the full certificate chain at signing time with the Apple root and intermediate certificates embedded into the Quill binary (obtained from Apple directly). However, an alternative to this approach is to attach the full certificate chain to your P12 file:

# run on a mac if you want to use certs from your keychain.
# otherwise this will embed any matching Apple certs that are found within Quill into the P12 file.

$ export QUILL_P12_PASSWORD=[p12-password]

$ quill p12 attach-chain [path-to-p12-from-apple]

# a new P12 file was created with the suffix `-with-chain.p12`

At this point you can use quill p12 describe to confirm the full certificate chain is attached.

Commands

  • sign [binary-file]: sign a mac executable binary
  • notarize [binary-file]: notarize a signed a mac binary with Apple's Notary service
  • sign-and-notarize [binary-file] sign and notarize a mac binary
  • submission list: list previous submissions to Apple's Notary service
  • submission logs [id]: fetch logs for an existing submission from Apple's Notary service
  • submission status [id]: check against Apple's Notary service to see the status of a notarization submission request
  • describe [binary-file]: show the details of a mac binary
  • extract certificates [binary-file]: extract certificates from a signed mac binary
  • p12 attach-chain [p12-file]: attach the full Apple certificate chain into a p12 file (MUST run on a mac with keychain access)
  • p12 describe [p12-file]: describe the contents of a p12 file

Configuration

Search locations: .quill.yaml, quill.yaml, .quill/config.yaml, ~/.quill.yaml, ~/quill.yaml, $XDG_CONFIG_HOME/quill/config.yaml

log:
  # suppress logging output (env var: "QUILL_LOG_QUIET")
  quiet: false
  
  # error, warn, info, debug, trace (env var: "QUILL_LOG_LEVEL")
  level: "info"
  
  # file to write all loge entries to (env var: "QUILL_LOG_FILE")
  file: ""

Why make this?

The mac codesign utility is great, but it's not available on all platforms. For cross-platform toolchains like golang this can get painful in subtle ways. Goreleaser is a great "one-shot" release solution, but requiring running on a mac just for the signing step now forces the reset of your build steps to work on a mac as well -- and since this is part of the release process, it needs to work in CI. This is a problem since, due to licensing reasons, the default mac runner for github actions cannot have docker installed by default. This means that you need to resort to installing docker on a mac in CI first before getting started, which can take upwards of 20 minutes.

Unlike docker, which inherently needs to run on a linux host (docker on a mac is a VM), there is nothing inherently mac-specific about signing a binary. This tool enables already cross-platform toolchains to run the signing step on any platform.

More Repositories

1

grype

A vulnerability scanner for container images and filesystems
Go
5,959
star
2

syft

CLI tool and library for generating a Software Bill of Materials from container images and filesystems
Go
4,261
star
3

anchore-engine

A service that analyzes docker images and scans for vulnerabilities
Python
1,547
star
4

anchore

This project is deprecated. Work is now done on https://github.com/anchore/syft and https://github.com/anchore/grype for local-host Software Bill of Materials and vulnerability scanning tools.
Python
360
star
5

scan-action

Anchore container analysis and scan provided as a GitHub Action
JavaScript
157
star
6

sbom-action

GitHub Action for creating software bill of materials using Syft.
TypeScript
113
star
7

anchore-cli

Simple command-line client to the Anchore Engine service
Python
108
star
8

grant

Search an SBOM for licenses and the packages they belong to
Go
58
star
9

kubernetes-admission-controller

Service implementation for a Kubernetes Dynamic Webhook controller for interacting with Anchore
Go
56
star
10

stereoscope

go library for processing container images and simulating a squash filesystem
Go
54
star
11

k8s-inventory

KAI (Kubernetes Automated Inventory) can poll Kubernetes Cluster API(s) to tell Anchore which Images are currently in-use
Go
52
star
12

anchore-charts

Helm charts for Anchore tools and services
Mustache
42
star
13

ci-tools

Contains scripts for running anchore engine in CI pipelines
Shell
34
star
14

chronicle

a fast changelog generator sourced from PRs and Issues
Go
32
star
15

harbor-scanner-adapter

Harbor Scanner Adapter for Anchore Engine and Enterprise
Go
29
star
16

vunnel

Tool for collecting vulnerability data from various sources (used to build the grype database)
Python
26
star
17

grype-db

Go
18
star
18

grype-vscode

Grype vulnerability check plugin for Visual Studio Code
TypeScript
15
star
19

anchore-grafeas-cli

Tool for connecting to an anchore-engine DB and generating grafeas note/occurrence JSON documents
Python
9
star
20

sbom-examples

Repository of SBOMs generated by the syft SBOM generator tool, against a list of popular dockerhub container images.
Python
8
star
21

yardstick

Compare vulnerability scanners results (to make them better!)
Python
5
star
22

vulnerability-match-labels

Labeled vulnerability-package match pairs used as ground truth to evaluate vulnerability scanners
Python
5
star
23

engine-operator

Helm based anchore engine operator
Makefile
4
star
24

test-infra

Contains infrastructure for running functional tests using Helm chart deployments
Python
4
star
25

azure-devops-task

Anchore Task Extension for Azure DevOps Pipelines
TypeScript
4
star
26

client-go

Golang client for Anchore API
Makefile
4
star
27

fangs

Go
2
star
28

go-struct-converter

Go library that provides a set of conversion utilities to help migrate between different versioned Go structs.
Go
2
star
29

ecs-inventory

Go
2
star
30

go-macholibre

Go
2
star
31

homebrew-syft

homebrew tap for syft
Ruby
2
star
32

enterprise-client-go

Go client for enterprise API
Mustache
2
star
33

circleci-orb-grype

Repository for the Grype based CircleCI orb
Shell
2
star
34

test-images

Container automation for testing and validation
Dockerfile
2
star
35

go-logger

Go
1
star
36

engine-db-preload

Some scripting to handling creation of preloaded anchore DB container
Shell
1
star
37

deployment-templates

Repository for example Anchore Engine deployment methods and integrations
1
star
38

homebrew-grype

homebrew tap for grype
Ruby
1
star
39

modular-policy

CLI utility for managing Anchore policy bundles as individual components. Useful for git-based policy management.
Python
1
star