mirror of
https://github.com/anchore/grype
synced 2024-11-10 06:34:13 +00:00
Resolve security warning for macOS users (#194)
Signed-off-by: Dan Luhring <dan.luhring@anchore.com>
This commit is contained in:
parent
50e9800594
commit
5725f26c04
8 changed files with 116 additions and 31 deletions
31
.github/scripts/mac-prepare-for-signing.sh
vendored
Executable file
31
.github/scripts/mac-prepare-for-signing.sh
vendored
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
CI_HOME="/Users/runner"
|
||||||
|
if [[ "${HOME}" != "${CI_HOME}" ]]; then
|
||||||
|
printf "WARNING! It looks like this isn't the CI environment. This script modifies the macOS Keychain setup in ways you probably wouldn't want for your own machine. It also requires an Apple Developer ID Certificate that you shouldn't have outside of the CI environment.\n\nExiting early to make sure nothing bad happens.\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install gon (see https://github.com/mitchellh/gon for details).
|
||||||
|
brew tap mitchellh/gon
|
||||||
|
brew install mitchellh/gon/gon
|
||||||
|
|
||||||
|
# Write signing certificate to disk from environment variable.
|
||||||
|
CERT_FILE="$HOME/developer_id_certificate.p12"
|
||||||
|
echo -n "$APPLE_DEVELOPER_ID_CERT" | base64 --decode > "$CERT_FILE"
|
||||||
|
|
||||||
|
# In order to have all keychain interactions avoid an interactive user prompt, we need to control the password for the keychain in question, which means we need to create a new keychain into which we'll import the signing certificate and from which we'll later access this certificate during code signing.
|
||||||
|
EPHEMERAL_KEYCHAIN="ci-ephemeral-keychain"
|
||||||
|
EPHEMERAL_KEYCHAIN_PASSWORD="$(openssl rand -base64 100)"
|
||||||
|
security create-keychain -p "${EPHEMERAL_KEYCHAIN_PASSWORD}" "${EPHEMERAL_KEYCHAIN}"
|
||||||
|
|
||||||
|
# Import signing certificate into the keychain. (This is a pre-requisite for gon, which is invoked via goreleaser.)
|
||||||
|
EPHEMERAL_KEYCHAIN_FULL_PATH="$HOME/Library/Keychains/${EPHEMERAL_KEYCHAIN}-db"
|
||||||
|
security import "${CERT_FILE}" -k "${EPHEMERAL_KEYCHAIN_FULL_PATH}" -P "${APPLE_DEVELOPER_ID_CERT_PASS}" -T "$(command -v codesign)"
|
||||||
|
|
||||||
|
# Setting the partition list for this certificate's private key to include "apple-tool:" and "apple:" allows the codesign command to access this keychain item without an interactive user prompt. (codesign is invoked by gon.)
|
||||||
|
security set-key-partition-list -S "apple-tool:,apple:" -s -k "${EPHEMERAL_KEYCHAIN_PASSWORD}" "${EPHEMERAL_KEYCHAIN_FULL_PATH}"
|
||||||
|
|
||||||
|
# Make this new keychain the user's default keychain, so that codesign will be able to find this certificate when we specify it during signing.
|
||||||
|
security default-keychain -d "user" -s "${EPHEMERAL_KEYCHAIN_FULL_PATH}"
|
16
.github/scripts/mac-sign-and-notarize.sh
vendored
Executable file
16
.github/scripts/mac-sign-and-notarize.sh
vendored
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
IS_SNAPSHOT="$1" # e.g. "true", "false"
|
||||||
|
|
||||||
|
if [[ "${IS_SNAPSHOT}" == "true" ]]; then
|
||||||
|
# This is a snapshot build —— skipping signing and notarization...
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
GON_CONFIG="$2" # e.g. "gon.hcl"
|
||||||
|
NEW_DMG_NAME="$3" # e.g. "./dist/syft-0.1.0.dmg"
|
||||||
|
ORIGINAL_DMG_NAME="./dist/output.dmg" # This should match dmg output_path in the gon config file.
|
||||||
|
|
||||||
|
gon "${GON_CONFIG}"
|
||||||
|
mv -v "${ORIGINAL_DMG_NAME}" "${NEW_DMG_NAME}"
|
13
.github/scripts/update-version-file.sh
vendored
13
.github/scripts/update-version-file.sh
vendored
|
@ -15,14 +15,9 @@ fi
|
||||||
echo "creating and publishing version file"
|
echo "creating and publishing version file"
|
||||||
|
|
||||||
# create a version file for version-update checks
|
# create a version file for version-update checks
|
||||||
echo "${VERSION}" | tee ${DISTDIR}/VERSION
|
VERSION_FILE="${DISTDIR}/VERSION"
|
||||||
|
echo "${VERSION}" | tee "${VERSION_FILE}"
|
||||||
|
|
||||||
# upload the version file that supports the application version update check
|
# upload the version file that supports the application version update check
|
||||||
docker run --rm \
|
export AWS_DEFAULT_REGION=us-west-2
|
||||||
-i \
|
aws s3 cp "${VERSION_FILE}" s3://toolbox-data.anchore.io/${BIN}/releases/latest/VERSION
|
||||||
-e AWS_DEFAULT_REGION=us-west-2 \
|
|
||||||
-e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
|
|
||||||
-e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
|
|
||||||
-v $(pwd)/${DISTDIR}/:/distmount \
|
|
||||||
amazon/aws-cli \
|
|
||||||
s3 cp /distmount/VERSION s3://toolbox-data.anchore.io/${BIN}/releases/latest/VERSION
|
|
||||||
|
|
8
.github/workflows/acceptance-test.yaml
vendored
8
.github/workflows/acceptance-test.yaml
vendored
|
@ -15,7 +15,7 @@ env:
|
||||||
jobs:
|
jobs:
|
||||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||||
Build-Snapshot-Artifacts:
|
Build-Snapshot-Artifacts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: macos-latest # We're creating these snapshot builds on macOS to be consistent with our release workflow's build process, which also takes place on macOS (due to code signing requirements).
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
|
@ -36,10 +36,6 @@ jobs:
|
||||||
${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}-
|
${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}-
|
||||||
${{ runner.os }}-go-${{ env.GO_VERSION }}-
|
${{ runner.os }}-go-${{ env.GO_VERSION }}-
|
||||||
|
|
||||||
- name: Bootstrap dependencies
|
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
|
||||||
run: make ci-bootstrap
|
|
||||||
|
|
||||||
- name: Import GPG key
|
- name: Import GPG key
|
||||||
id: import_gpg
|
id: import_gpg
|
||||||
uses: crazy-max/ghaction-import-gpg@v2
|
uses: crazy-max/ghaction-import-gpg@v2
|
||||||
|
@ -92,4 +88,4 @@ jobs:
|
||||||
path: snapshot
|
path: snapshot
|
||||||
|
|
||||||
- name: Compare Anchore inline-scan results against snapshot build output
|
- name: Compare Anchore inline-scan results against snapshot build output
|
||||||
run: make compare-snapshot
|
run: make compare-snapshot
|
||||||
|
|
15
.github/workflows/release.yaml
vendored
15
.github/workflows/release.yaml
vendored
|
@ -13,7 +13,7 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
wait-for-checks:
|
wait-for-checks:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest # This OS choice is arbitrary. None of the steps in this job are specific to either Linux or macOS.
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -71,7 +71,7 @@ jobs:
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: [ wait-for-checks ]
|
needs: [ wait-for-checks ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: macos-latest # Due to our code signing process, it's vital that we run our release steps on macOS.
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
|
@ -82,6 +82,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# We are expecting this cache to have been created during the "Build-Snapshot-Artifacts" job in the "Acceptance" workflow.
|
||||||
- name: Restore bootstrap cache
|
- name: Restore bootstrap cache
|
||||||
id: cache
|
id: cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
@ -94,10 +95,6 @@ jobs:
|
||||||
${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('Makefile') }}-
|
${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('Makefile') }}-
|
||||||
${{ runner.os }}-go-${{ env.GO_VERSION }}-
|
${{ runner.os }}-go-${{ env.GO_VERSION }}-
|
||||||
|
|
||||||
- name: Bootstrap dependencies
|
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
|
||||||
run: make ci-bootstrap
|
|
||||||
|
|
||||||
- name: Import GPG key
|
- name: Import GPG key
|
||||||
id: import_gpg
|
id: import_gpg
|
||||||
uses: crazy-max/ghaction-import-gpg@v2
|
uses: crazy-max/ghaction-import-gpg@v2
|
||||||
|
@ -121,6 +118,10 @@ jobs:
|
||||||
SIGNING_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
|
SIGNING_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
||||||
|
APPLE_DEVELOPER_ID_CERT: ${{ secrets.APPLE_DEVELOPER_ID_CERT }} # Used during macOS code signing.
|
||||||
|
APPLE_DEVELOPER_ID_CERT_PASS: ${{ secrets.APPLE_DEVELOPER_ID_CERT_PASS }} # Used during macOS code signing.
|
||||||
|
AC_USERNAME: ${{ secrets.ENG_CI_APPLE_ID }} # Used during macOS notarization.
|
||||||
|
AC_PASSWORD: ${{ secrets.ENG_CI_APPLE_ID_PASS }} # Used during macOS notarization.
|
||||||
|
|
||||||
- uses: 8398a7/action-slack@v3
|
- uses: 8398a7/action-slack@v3
|
||||||
with:
|
with:
|
||||||
|
@ -134,4 +135,4 @@ jobs:
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
path: dist/**/*
|
path: dist/**/*
|
||||||
|
|
|
@ -7,12 +7,13 @@ release:
|
||||||
# If set to true, will not auto-publish the release. This is done to allow us to review the changelog before publishing.
|
# If set to true, will not auto-publish the release. This is done to allow us to review the changelog before publishing.
|
||||||
draft: true
|
draft: true
|
||||||
|
|
||||||
signs:
|
# This ensures any macOS signed artifacts get included with the release.
|
||||||
- artifacts: checksum
|
extra_files:
|
||||||
args: ["--output", "${signature}", "--detach-sign", "${artifact}"]
|
- glob: "./dist/*.dmg"
|
||||||
|
|
||||||
builds:
|
builds:
|
||||||
- binary: grype
|
- binary: grype
|
||||||
|
id: grype
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
goos:
|
goos:
|
||||||
|
@ -32,6 +33,31 @@ builds:
|
||||||
-X github.com/anchore/grype/internal/version.gitCommit={{.Commit}}
|
-X github.com/anchore/grype/internal/version.gitCommit={{.Commit}}
|
||||||
-X github.com/anchore/grype/internal/version.buildDate={{.Date}}
|
-X github.com/anchore/grype/internal/version.buildDate={{.Date}}
|
||||||
-X github.com/anchore/grype/internal/version.gitTreeState={{.Env.BUILD_GIT_TREE_STATE}}
|
-X github.com/anchore/grype/internal/version.gitTreeState={{.Env.BUILD_GIT_TREE_STATE}}
|
||||||
|
# For more info on this macOS build, see: https://github.com/mitchellh/gon#usage-with-goreleaser
|
||||||
|
- binary: grype
|
||||||
|
id: grype-macos
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- darwin
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
# Set the modified timestamp on the output binary to the git timestamp (to ensure a reproducible build)
|
||||||
|
mod_timestamp: '{{ .CommitTimestamp }}'
|
||||||
|
ldflags: |
|
||||||
|
-w
|
||||||
|
-s
|
||||||
|
-extldflags '-static'
|
||||||
|
-X github.com/anchore/grype/internal/version.version={{.Version}}
|
||||||
|
-X github.com/anchore/grype/internal/version.gitCommit={{.Commit}}
|
||||||
|
-X github.com/anchore/grype/internal/version.buildDate={{.Date}}
|
||||||
|
-X github.com/anchore/grype/internal/version.gitTreeState={{.Env.BUILD_GIT_TREE_STATE}}
|
||||||
|
hooks:
|
||||||
|
post: ./.github/scripts/mac-sign-and-notarize.sh "{{.IsSnapshot}}" "gon.hcl" "./dist/grype_{{.Tag}}_{{.Target}}.dmg"
|
||||||
|
|
||||||
|
signs:
|
||||||
|
- artifacts: checksum
|
||||||
|
args: ["--output", "${signature}", "--detach-sign", "${artifact}"]
|
||||||
|
|
||||||
nfpms:
|
nfpms:
|
||||||
- license: "Apache 2.0"
|
- license: "Apache 2.0"
|
||||||
|
@ -51,7 +77,8 @@ brews:
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
- format: tar.gz
|
- format: tar.gz
|
||||||
|
builds:
|
||||||
|
- grype # i.e. Linux only
|
||||||
format_overrides:
|
format_overrides:
|
||||||
- goos: windows
|
- goos: windows
|
||||||
format: zip
|
format: zip
|
||||||
|
|
||||||
|
|
18
Makefile
18
Makefile
|
@ -65,6 +65,10 @@ help:
|
||||||
ci-bootstrap: bootstrap
|
ci-bootstrap: bootstrap
|
||||||
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y bc jq libxml2-utils
|
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y bc jq libxml2-utils
|
||||||
|
|
||||||
|
.PHONY:
|
||||||
|
ci-bootstrap-mac:
|
||||||
|
github_changelog_generator --version || sudo gem install github_changelog_generator
|
||||||
|
|
||||||
.PHONY: boostrap
|
.PHONY: boostrap
|
||||||
bootstrap: ## Download and install all go dependencies (+ prep tooling in the ./tmp dir)
|
bootstrap: ## Download and install all go dependencies (+ prep tooling in the ./tmp dir)
|
||||||
$(call title,Boostrapping dependencies)
|
$(call title,Boostrapping dependencies)
|
||||||
|
@ -172,8 +176,7 @@ compare:
|
||||||
changelog-release:
|
changelog-release:
|
||||||
@echo "Last tag: $(SECOND_TO_LAST_TAG)"
|
@echo "Last tag: $(SECOND_TO_LAST_TAG)"
|
||||||
@echo "Current tag: $(VERSION)"
|
@echo "Current tag: $(VERSION)"
|
||||||
@docker run -i --rm \
|
@github_changelog_generator \
|
||||||
-v "$(shell pwd)":/usr/local/src/your-app ferrarimarco/github-changelog-generator \
|
|
||||||
--user anchore \
|
--user anchore \
|
||||||
--project $(BIN) \
|
--project $(BIN) \
|
||||||
-t ${GITHUB_TOKEN} \
|
-t ${GITHUB_TOKEN} \
|
||||||
|
@ -187,8 +190,9 @@ changelog-release:
|
||||||
|
|
||||||
.PHONY: changelog-unreleased
|
.PHONY: changelog-unreleased
|
||||||
changelog-unreleased: ## show the current changelog that will be produced on the next release (note: requires GITHUB_TOKEN set)
|
changelog-unreleased: ## show the current changelog that will be produced on the next release (note: requires GITHUB_TOKEN set)
|
||||||
@docker run -it --rm \
|
@docker run -it --rm \
|
||||||
-v "$(shell pwd)":/usr/local/src/your-app ferrarimarco/github-changelog-generator \
|
-v "$(shell pwd)":/usr/local/src/your-app \
|
||||||
|
ferrarimarco/github-changelog-generator \
|
||||||
--user anchore \
|
--user anchore \
|
||||||
--project $(BIN) \
|
--project $(BIN) \
|
||||||
-t ${GITHUB_TOKEN} \
|
-t ${GITHUB_TOKEN} \
|
||||||
|
@ -204,8 +208,12 @@ changelog-unreleased: ## show the current changelog that will be produced on the
|
||||||
/CHANGELOG.md
|
/CHANGELOG.md
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: clean-dist changelog-release ## Build and publish final binaries and packages
|
release: clean-dist ci-bootstrap-mac changelog-release ## Build and publish final binaries and packages. Intended to be run only on macOS.
|
||||||
$(call title,Publishing release artifacts)
|
$(call title,Publishing release artifacts)
|
||||||
|
|
||||||
|
# Prepare for macOS-specific signing process
|
||||||
|
.github/scripts/mac-prepare-for-signing.sh
|
||||||
|
|
||||||
# create a config with the dist dir overridden
|
# create a config with the dist dir overridden
|
||||||
echo "dist: $(DISTDIR)" > $(TEMPDIR)/goreleaser.yaml
|
echo "dist: $(DISTDIR)" > $(TEMPDIR)/goreleaser.yaml
|
||||||
cat .goreleaser.yaml >> $(TEMPDIR)/goreleaser.yaml
|
cat .goreleaser.yaml >> $(TEMPDIR)/goreleaser.yaml
|
||||||
|
|
11
gon.hcl
Normal file
11
gon.hcl
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
source = ["./dist/grype-macos_darwin_amd64/grype"] # The 'dist' directory path should ideally reference an env var, where the source of truth is the Makefile. I wasn't able to figure out how to solve this.
|
||||||
|
bundle_id = "com.anchore.toolbox.grype"
|
||||||
|
|
||||||
|
sign {
|
||||||
|
application_identity = "Developer ID Application: ANCHORE, INC. (9MJHKYX5AT)"
|
||||||
|
}
|
||||||
|
|
||||||
|
dmg {
|
||||||
|
output_path = "./dist/output.dmg"
|
||||||
|
volume_name = "Grype"
|
||||||
|
}
|
Loading…
Reference in a new issue