diff --git a/.github/cloudformation/README.md b/.github/cloudformation/README.md new file mode 100644 index 0000000..05dc840 --- /dev/null +++ b/.github/cloudformation/README.md @@ -0,0 +1,3 @@ +These are +[AWS CloudFormation templates](https://aws.amazon.com/cloudformation/resources/templates/) +for maintaining pypi and homebrew credentials used to publish the CBMC starter kit. diff --git a/.github/cloudformation/oidc.yaml b/.github/cloudformation/oidc.yaml new file mode 100644 index 0000000..90f7770 --- /dev/null +++ b/.github/cloudformation/oidc.yaml @@ -0,0 +1,23 @@ +Description: + Register the GitHub identity provider with the AWS security token service. + +Resources: + GithubIdentityProvider: + Type: AWS::IAM::OIDCProvider + Properties: + Url: + # The GitHub identity provider supporting OIDC + https://token.actions.githubusercontent.com + ThumbprintList: + # The GitHub certification authority (the signature of its certificate) + - 6938fd4d98bab03faadb97b34396831e3780aea1 + ClientIdList: + # The AWS security token service + - sts.amazonaws.com + + +Outputs: + GithubIdentityProvider: + Value: !Ref GithubIdentityProvider + Export: + Name: GithubIdentityProvider diff --git a/.github/cloudformation/token.yaml b/.github/cloudformation/token.yaml new file mode 100644 index 0000000..b501c92 --- /dev/null +++ b/.github/cloudformation/token.yaml @@ -0,0 +1,77 @@ +Description: > + Enable storage of access tokens in AWS Secrets Manager and access to the PAT + from the GitHub workflows in model-checking/cbmc-starter-kit. + +Parameters: + GithubRepoOrganization: + Type: String + Description: GitHub organization for the CBMC starter kit + Default: model-checking + CbmcStarterKitRepoName: + Type: String + Description: GitHub repository for CBMC starter kit + Default: cbmc-starter-kit + CbmcStarterKitPublicationTag: + Type: String + Description: GitHub tag for CBMC starter kit triggering the GitHub publication workflow + Default: starterkit-* + +Resources: + + BrewBotEmail: + Type: AWS::SecretsManager::Secret + Properties: + Name: BOT_EMAIL + Description: > + The email address to use with Homebrew commits. + + BrewToken: + Type: AWS::SecretsManager::Secret + Properties: + Name: RELEASE_CI_ACCESS_TOKEN + Description: > + GitHub access token. + + PypiToken: + Type: AWS::SecretsManager::Secret + Properties: + Name: PYPI_ACCESS_TOKEN + Description: > + Pypi access token. + + PublisherTokenReader: + Type: AWS::IAM::Role + Properties: + RoleName: PublisherTokenReader + Description: > + This role can retrieve the personal access token for the model + checking publisher in the Microsoft Marketplace. + + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Federated: !ImportValue GithubIdentityProvider + Action: sts:AssumeRoleWithWebIdentity + Condition: + StringEquals: + token.actions.githubusercontent.com:aud: sts.amazonaws.com + StringLike: + token.actions.githubusercontent.com:sub: + !Sub repo:${GithubRepoOrganization}/${CbmcStarterKitRepoName}:ref:refs/tags/${CbmcStarterKitPublicationTag} + + Policies: + - PolicyName: PublisherTokenAccess + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: secretsmanager:GetSecretValue + Resource: !Ref BrewBotEmail + - Effect: Allow + Action: secretsmanager:GetSecretValue + Resource: !Ref BrewToken + - Effect: Allow + Action: secretsmanager:GetSecretValue + Resource: !Ref PypiToken diff --git a/.github/workflows/release-brew.yaml b/.github/workflows/release-brew.yaml index cdda0ca..da8e8b3 100644 --- a/.github/workflows/release-brew.yaml +++ b/.github/workflows/release-brew.yaml @@ -46,17 +46,29 @@ env: FORMULA: cbmc-starter-kit TAP: aws/tap BOT_USER: cbmc-starter-kit-release-ci - BOT_EMAIL: ${{ secrets.BOT_EMAIL }} - BOT_TOKEN: ${{ secrets.RELEASE_CI_ACCESS_TOKEN }} RELEASE_TAG: ${GITHUB_REF/refs\/tags\/} # GITHUB_REF = refs/tags/STRING-MAJOR.MINOR VERSION: $(echo $GITHUB_REF | cut -d "/" -f 3 | cut -d "-" -f 2) - FORK_REPO: https://$BOT_TOKEN@github.com/$BOT_USER/homebrew-$(echo $TAP |cut -d "/" -f 2).git + AWS_ROLE: arn:aws:iam::${{secrets.AWS_ACCOUNT}}:role/PublisherTokenReader + AWS_REGION: us-west-2 jobs: homebrew-pr: name: Homebrew Bump Formula PR runs-on: macos-latest + permissions: + id-token: write steps: + - name: Authenticate GitHub workflow to AWS + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.AWS_ROLE }} + aws-region: ${{ env.AWS_REGION }} + + - name: Fetch secrets + run: | + echo "BOT_EMAIL=$(aws secretsmanager get-secret-value --secret-id BOT_EMAIL | jq -r '.SecretString')" >> $GITHUB_ENV + echo "HOMEBREW_GITHUB_API_TOKEN=$(aws secretsmanager get-secret-value --secret-id RELEASE_CI_ACCESS_TOKEN | jq -r '.SecretString')" >> $GITHUB_ENV + - name: Configure git user name and email run: | git config --global user.name ${{ env.BOT_USER }} @@ -66,9 +78,7 @@ jobs: run: | brew tap ${{ env.TAP }} brew update-reset - brew bump-formula-pr --tag "${{ env.RELEASE_TAG }}" --revision "$GITHUB_SHA" ${{ env.TAP }}/${{ env.FORMULA }} --force - env: - HOMEBREW_GITHUB_API_TOKEN: ${{ env.BOT_TOKEN }} + brew bump-formula-pr --tag "${{ env.RELEASE_TAG }}" --revision "${{ github.sha }}" ${{ env.TAP }}/${{ env.FORMULA }} --force build-bottle: needs: homebrew-pr @@ -76,11 +86,25 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} + permissions: + id-token: write + contents: write steps: - name: Set up Homebrew id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@master + - name: Authenticate GitHub workflow to AWS + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.AWS_ROLE }} + aws-region: ${{ env.AWS_REGION }} + + - name: Fetch secrets + run: | + echo "FORK_REPO=https://$(aws secretsmanager get-secret-value --secret-id RELEASE_CI_ACCESS_TOKEN | jq -r '.SecretString')@github.com/${{ env.BOT_USER }}/homebrew-$(echo ${{ env.TAP }} |cut -d / -f 2).git" >> $GITHUB_ENV + echo "GITHUB_TOKEN=$(aws secretsmanager get-secret-value --secret-id RELEASE_CI_ACCESS_TOKEN | jq -r '.SecretString')" >> $GITHUB_ENV + - name: Set up Python # The GitHub action actions/setup-python@v4 installs CPython 3.10 run: | @@ -102,43 +126,55 @@ jobs: - name: Build bottle run: | - brew test-bot --tap ${{ env.TAP }} --testing-formulae ${{ env.TAP }}/${{ env.FORMULA }} --only-formulae --root-url=https://github.com/$GITHUB_REPOSITORY/releases/download/${{ env.RELEASE_TAG }} + brew test-bot --tap ${{ env.TAP }} --testing-formulae ${{ env.TAP }}/${{ env.FORMULA }} --only-formulae --root-url=https://github.com/${{ github.repository }}/releases/download/${{ env.RELEASE_TAG }} - name: Get Package Path id: get_package_path run: | - echo "bottle=$(ls *.tar.gz)" >> $GITHUB_ENV + echo "bottle_name=$(ls *.tar.gz)" >> $GITHUB_OUTPUT - name: Get File Name id: get_file_name run: | - brew install jq - echo "file_name=$(jq -r '."${{ env.TAP }}/${{ env.FORMULA }}".bottle.tags[].filename' *.json)" >> $GITHUB_ENV + file_name="$(cat *.json | jq -r '."${{ env.TAP }}/${{ env.FORMULA }}".bottle.tags[].filename')" + echo "file_name=$file_name" >> $GITHUB_OUTPUT - name: Upload bottles as artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: bottles + name: bottle-${{ matrix.os }} path: '*.bottle.*' - name: Upload release binary # this github action is deprecated, but there is no obvious replacement uses: actions/upload-release-asset@v1.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.bottle }} - asset_name: ${{ env.file_name }} + asset_path: ${{ steps.get_package_path.outputs.bottle_name }} + asset_name: ${{ steps.get_file_name.outputs.file_name }} asset_content_type: application/x-gzip update-pr: needs: build-bottle runs-on: macos-latest + permissions: + id-token: write + contents: write steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 + with: + pattern: bottle-* + + - name: Authenticate GitHub workflow to AWS + uses: aws-actions/configure-aws-credentials@v4 with: - name: bottles + role-to-assume: ${{ env.AWS_ROLE }} + aws-region: ${{ env.AWS_REGION }} + + - name: Fetch secrets + run: | + echo "BOT_EMAIL=$(aws secretsmanager get-secret-value --secret-id BOT_EMAIL | jq -r '.SecretString')" >> $GITHUB_ENV + echo "FORK_REPO=https://$(aws secretsmanager get-secret-value --secret-id RELEASE_CI_ACCESS_TOKEN | jq -r '.SecretString')@github.com/${{ env.BOT_USER }}/homebrew-$(echo ${{ env.TAP }} |cut -d / -f 2).git" >> $GITHUB_ENV - name: Configure git user name and email run: | @@ -156,6 +192,6 @@ jobs: - name: Generate and merge bottle DSL run: | - brew bottle --merge --write $(ls *.json) + brew bottle --merge --write $(ls bottle-*/*.json) cd $(brew --repo ${{ env.TAP }}) git push fork-repo bump-${{ env.FORMULA }}-${{ env.VERSION }} diff --git a/.github/workflows/release-pypi.yaml b/.github/workflows/release-pypi.yaml index f969ec1..1e1f16c 100644 --- a/.github/workflows/release-pypi.yaml +++ b/.github/workflows/release-pypi.yaml @@ -3,32 +3,45 @@ on: release: types: [created] +env: + AWS_ROLE: arn:aws:iam::${{secrets.AWS_ACCOUNT}}:role/PublisherTokenReader + AWS_REGION: us-west-2 + jobs: upload-to-pypi: name: Upload to PyPi runs-on: ubuntu-20.04 + permissions: + id-token: write + contents: write steps: - uses: actions/checkout@v3 - name: Install dependencies run: python3 -m pip install --upgrade pip build setuptools wheel twine - name: Build pip package run: python3 -m build + - name: Authenticate GitHub workflow to AWS + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.AWS_ROLE }} + aws-region: ${{ env.AWS_REGION }} + - name: Fetch secrets + run: | + echo "GITHUB_TOKEN=$(aws secretsmanager get-secret-value --secret-id RELEASE_CI_ACCESS_TOKEN | jq -r '.SecretString')" >> $GITHUB_ENV + echo "TWINE_PASSWORD=$(aws secretsmanager get-secret-value --secret-id PYPI_ACCESS_TOKEN | jq -r '.SecretString')" >> $GITHUB_ENV - name: Get Package Name id: get_package_name run: | - echo "package_name=$(ls dist/*.whl | cut -d "/" -f 2)" >> $GITHUB_ENV + echo "package_name=$(ls dist/*.whl | cut -d / -f 2)" >> $GITHUB_OUTPUT - name: Upload release binary # this github action is deprecated, but there is no obvious replacement uses: actions/upload-release-asset@v1.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} - asset_path: dist/${{ env.package_name }} - asset_name: ${{ env.package_name }} + asset_path: dist/${{ steps.get_package_name.outputs.package_name }} + asset_name: ${{ steps.get_package_name.outputs.package_name }} asset_content_type: application/zip - name: Upload to PyPi env: TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_ACCESS_TOKEN }} run: python3 -m twine upload dist/* diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 737b2a2..054f4e8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -3,13 +3,17 @@ on: push: tags: - starterkit-* +env: + AWS_ROLE: arn:aws:iam::${{secrets.AWS_ACCOUNT}}:role/PublisherTokenReader + AWS_REGION: us-west-2 jobs: Release: name: CBMC starter kit release runs-on: ubuntu-20.04 - env: - GITHUB_TOKEN: ${{ secrets.RELEASE_CI_ACCESS_TOKEN }} + permissions: + id-token: write + contents: write steps: - name: Checkout code uses: actions/checkout@v3 @@ -25,13 +29,15 @@ jobs: echo "Setup and source versions ${{env.SETUP_VERSION}} and ${{env.SOURCE_VERSION}} did not match tag version ${{env.TAG_VERSION}}" exit 1 fi + - name: Authenticate GitHub workflow to AWS + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.AWS_ROLE }} + aws-region: ${{ env.AWS_REGION }} + - name: Fetch secrets + run: | + echo "GITHUB_TOKEN=$(aws secretsmanager get-secret-value --secret-id RELEASE_CI_ACCESS_TOKEN | jq -r '.SecretString')" >> $GITHUB_ENV - name: Create release - # The GitHub action actions/create-release is deprecated: - # https://github.com/actions/create-release - # GitHub recommends ncipollo/release-action@v1, but that - # action fails to trigger the release workflows for brew and - # pypi, perhaps because it does not trigger the expected kind - # of release event. uses: actions/create-release@v1 with: tag_name: starterkit-${{ env.TAG_VERSION }}