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

feat: macos signing and notarization #367

Merged
merged 19 commits into from
Aug 3, 2021
Merged

feat: macos signing and notarization #367

merged 19 commits into from
Aug 3, 2021

Conversation

lidel
Copy link
Member

@lidel lidel commented Jul 21, 2021

This is a streamlined refactor of #362 on road to fix issues described in #8240

This PR adds sign-macos job to CI workflow, adding a transparent signing step.

The main reason is to sign repo migrations and avoid issue from ipfs/kubo#8240 globally (outside of Brave). It also provides us with a template if we wish to add signing for other platforms.

How this works?

Technical details

This PR splits make publish performed in main.yml into three stages:

  1. build executes ./dockerized make all_dists and produces any missing binaries in ./releases
  2. sign-macos signs and notarizes every new binary from ./releases and updates .tar.gz packages and relevant hashes in-place
  3. publish
    • executes make publish and adds any new and signed packages from ./releases to DIST_ROOT
      (/ipns/dist.ipfs.io by default)
    • pins produced CID to ipfs-cluster for persistence

Flow for adding new dist or version

  1. Open a PR against this repo with new entry for one of ./dists/{name}/versions
  2. Wait for CI to build signed dist, put it on IPFS and pin updated DIST_ROOT to ipfs-cluster
  3. Preview link will be published on PR and printed at the end of publish step of CI build
  4. If everything looks good, write down the CID from preview link, and update the DNSlink of dist.ipfs.io

Content routing optimization

IPFS node running on CI manually pre-connects to ipfs-websites cluster peers, which are known to already have all blocks required during dist.ipfs.io build. This way we skip DHT lookup.

Website preview on PRs

Every PR now gets a link to website preview at the dweb.link IPFS gateway:

2021-07-27--01-43-43

TODO

  • sign darwin binaries and put them in the same place as unsigned ones
  • ensure all hashes and manifests match signed binaries
  • ensure the root CID for updated dist.ipfs.io website is persisted after CI job ends
  • gateway link with preview of updated website
  • remove fake DIST_ROOT and ensure CI is no-op when no new binaries are added
  • squash & merge

@lidel lidel force-pushed the feat/signed-ci-build branch 7 times, most recently from d891669 to a06abf7 Compare July 21, 2021 16:46
@lidel lidel mentioned this pull request Jul 21, 2021
11 tasks
@lidel lidel changed the title feat: macos signing and notarization (refactor) feat: macos signing and notarization Jul 21, 2021
@lidel lidel force-pushed the feat/signed-ci-build branch 2 times, most recently from 057619f to 2ba7177 Compare July 21, 2021 18:12
@lidel lidel force-pushed the feat/signed-ci-build branch 18 times, most recently from 7183e8a to 92386a4 Compare July 23, 2021 21:30
@lidel lidel mentioned this pull request Jul 29, 2021
7 tasks
Copy link
Member Author

@lidel lidel left a comment

Choose a reason for hiding this comment

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

Ready for review (silence is compliance – aiming for merging in the beginning of the next week).

'{ state: $state, target_url: $target_url, description: $description, context: $context }' )
curl --output /dev/null --silent --show-error \
-X POST -H "Authorization: Bearer $GITHUB_TOKEN" -H 'Content-Type: application/json' \
--data "$API_PARAMS" 'https://api.github.com/repos/ipfs/distributions/statuses/${GIT_REVISION}'
Copy link
Member Author

Choose a reason for hiding this comment

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

ℹ️ we could replace this script with JS call and actions/github-script but I don't want to sink any more time into refactoring this PR ;)

docker build . -t distributions \
--build-arg CACHEBUST=`date --iso-8601=date` \
--build-arg USER_UID=$(id -u "$USER") \
--build-arg GO_IPFS_VER=${GO_IPFS_VER:-$(curl -s https://dist.ipfs.io/go-ipfs/versions | tail -n 1)} # match http api client version on CI
Copy link
Member Author

Choose a reason for hiding this comment

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

ℹ️ this controls the version of the CLI client inside ./dockerized build, which talks to go-ipfs running outside on the host. Here, we ensure it uses the same version (with fallback to the latest one if GO_IPFS_VER is undefined).

Copy link
Contributor

Choose a reason for hiding this comment

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

Should this comment live in the source file?

Copy link
Member Author

@lidel lidel Aug 3, 2021

Choose a reason for hiding this comment

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

I believe the comment on the very right is enough, more context can be found on this PR.

Comment on lines +20 to +21
if [[ $(jq '.peer_map[].status' cluster-pin-status | grep '"pinned"' | wc -l) -ge 2 ]]; then
echo "Got 2 pin confirmations, finishing the workflow"
Copy link
Member Author

Choose a reason for hiding this comment

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

ℹ️ to make CI faster and avoid hanging forever if parts of cluster are out of sync, cluster pinning is considered "done" after we have 2 copies.

Here, I do it manually in userland, but filled ipfs-cluster/ipfs-cluster#1427 to add this sort of thing to ipfs-cluster-ctl CLI tool.

Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to above: when do we decide to put this in the PR vs. the code itself? Do folks tend to do a git blame and look for comments to find more context?

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 often use git blame, but in this specific case those comments are provided mostly to make PR review easier.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok. I'll defer to the team for the standard. I was bringing this up because it was hard for me to imagine a case where a comment is useful during PR where it isn't also useful 6 months in the future when looking at the code with fresh eyes. Anyways, sounds good.

Comment on lines +9 to +10
# fix resolv - DNS provided by Github is unreliable for DNSLik/dnsaddr
sudo sed -i -e 's/nameserver 127.0.0.*/nameserver 1.1.1.1/g' /etc/resolv.conf
Copy link
Member Author

Choose a reason for hiding this comment

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

ℹ️ This was pretty annoying. Entire build failed because Githubs DNS proxying cache at 127.0.0.* randomly timeouted while resolving _dnslink or _dnsaddr. Switching to Cloudflare here make the problem go away.

EXECUTABLES=$(jq -nc '$ARGS.positional' --args $(find "./tmp/${DIST_NAME}_${DIST_VERSION}_${arch}-unsigned/" -perm +111 -type f -print))
echo "{
\"source\" : $EXECUTABLES,
\"bundle_id\" : \"io.ipfs.dist.${DIST_NAME}\",
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 registered the wildcard bundle_id=io.ipfs.dist.* at Apple, which enables us to have each package "isolated" from each other. This is important in case Apple decides to block something from running on macOS – we don't have all egs in one basket.

brew install ipfs coreutils gawk gnu-sed jq mitchellh/gon/gon
ipfs init --profile test # needed for calculating NEW_CID later
- name: Import Keychain Certs
uses: apple-actions/import-codesign-certs@253ddeeac23f2bdad1646faac5c8c2832e800071 # v1@2020-02-03
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 hardcoded specific revision because this is a third-party action and in theory someone could swap-out git tag and steal our signing keys.

Comment on lines +68 to +69
brew tap mitchellh/gon
brew install ipfs coreutils gawk gnu-sed jq mitchellh/gon/gon
Copy link
Member Author

Choose a reason for hiding this comment

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

ℹ️ gon package is used by Terraform project, so multiple eyes are looking at this

Comment on lines +97 to +102
To produce a signed, **official build** for use in DNSLink at `dist.ipfs.io`:

1. Run `./dist.sh add-version` locally.
2. Commit created changes to `dists/<dist>` and open a PR against `ipfs/distributions`.
3. Wait for Github Action to finish PR build. It runs `./dockerized` build, then signs macOS binaries and spits out updated root CID at the end.
4. If everything looks good, write down the CID from the preview link on the PR, and update the DNSlink at `dist.ipfs.io`.
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 believe this is the TLDR of this entire PR :)

Copy link
Contributor

@aschmahmann aschmahmann left a comment

Choose a reason for hiding this comment

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

LGTM, although I mostly reviewed the README. We may learn more as we start using it for nightlies though ❤️

README.md Show resolved Hide resolved
Copy link
Contributor

@BigLep BigLep left a comment

Choose a reason for hiding this comment

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

Great work!
Only comments were around inlining comments PR into the code for discoverability. Your call.

docker build . -t distributions \
--build-arg CACHEBUST=`date --iso-8601=date` \
--build-arg USER_UID=$(id -u "$USER") \
--build-arg GO_IPFS_VER=${GO_IPFS_VER:-$(curl -s https://dist.ipfs.io/go-ipfs/versions | tail -n 1)} # match http api client version on CI
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this comment live in the source file?

Comment on lines +20 to +21
if [[ $(jq '.peer_map[].status' cluster-pin-status | grep '"pinned"' | wc -l) -ge 2 ]]; then
echo "Got 2 pin confirmations, finishing the workflow"
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to above: when do we decide to put this in the PR vs. the code itself? Do folks tend to do a git blame and look for comments to find more context?

+ add ability to run workflow against arbitrary path - until we have
  signed nightlies
@lidel
Copy link
Member Author

lidel commented Aug 3, 2021

As agreed during stewards call, I'm starting the merge dance starting with this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants