From 177887252ec18bd47373fb5c78b487dc788bea68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Bl=C3=A4cker?= Date: Wed, 11 Dec 2024 20:31:53 +0700 Subject: [PATCH 1/3] git action added to bypass PRs --- .github/workflows/forceMergePRBypassAudit.yml | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .github/workflows/forceMergePRBypassAudit.yml diff --git a/.github/workflows/forceMergePRBypassAudit.yml b/.github/workflows/forceMergePRBypassAudit.yml new file mode 100644 index 000000000..00109d18c --- /dev/null +++ b/.github/workflows/forceMergePRBypassAudit.yml @@ -0,0 +1,82 @@ +name: Force-Merge PR (Bypass Audit Requirement) +# - This git action may only be used in exceptional cases +# - it can only be executed by the CTO or the Information Security Manager/Architect +# - a valid reason must be provided in order to force-merge a given PR + +on: + workflow_dispatch: + inputs: + pr_number: + description: 'PR number to bypass' + required: true + justification: + description: 'Reason for bypass' + required: true + +jobs: + force-merge-pr-bypass-audit: + runs-on: ubuntu-latest + steps: + - name: Fetch Information Security Team Members + env: + GH_PAT: ${{ secrets.GIT_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ##### Unset default GITHUB_TOKEN (insufficient permissions) + unset GITHUB_TOKEN + + ##### Authenticate with Personal Access Token + echo $GH_PAT | gh auth login --with-token + + ##### Fetch team members of 'informationsecuritymanager' team + ORG_NAME="lifinance" + TEAM_SLUG="informationsecuritymanager" + + TEAM_MEMBERS=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/orgs/$ORG_NAME/teams/$TEAM_SLUG/members" | jq -r '.[].login') + + if [[ -z "$TEAM_MEMBERS" ]]; then + echo -e "\033[31mERROR: Could not retrieve team members of $TEAM_SLUG.\033[0m" + exit 1 + fi + + echo "The following users are members of $TEAM_SLUG: $TEAM_MEMBERS" + echo "$TEAM_MEMBERS" > team_members.txt + + - name: Verify Actor's Team Membership + run: | + ##### Check if the actor is in the team members list + ACTOR="${{ github.actor }}" + TEAM_MEMBERS=$(cat team_members.txt) + + if echo "$TEAM_MEMBERS" | grep -q "^$ACTOR$"; then + echo -e "\033[32m$ACTOR is authorized to approve bypasses.\033[0m" + echo "CONTINUE=true" >> "$GITHUB_ENV" + else + echo -e "\033[31mERROR: $ACTOR is NOT authorized to approve bypasses\033[0m" + exit 1 + fi + + - name: Log Justification + if: env.CONTINUE == 'true' + run: | + echo "Bypass approved for PR #${{ github.event.inputs.pr_number }} by $ACTOR." + echo "Justification: ${{ github.event.inputs.justification }}" + + - name: Merge the PR + uses: actions/github-script@v7.0.1 + if: env.CONTINUE == 'true' + with: + script: | + const pr = parseInt(core.getInput('pr_number')); + console.log(`Merging PR ${pr} now`) + + const { context } = github; + await github.rest.pulls.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr, + merge_method: "squash" + }); From af08b5b73eabb6b3dce3b931db3a1628418e1411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Bl=C3=A4cker?= Date: Thu, 12 Dec 2024 09:18:17 +0700 Subject: [PATCH 2/3] improved the git action based on coderabbit review comments --- .github/workflows/forceMergePRBypassAudit.yml | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/forceMergePRBypassAudit.yml b/.github/workflows/forceMergePRBypassAudit.yml index 00109d18c..0d5a012fc 100644 --- a/.github/workflows/forceMergePRBypassAudit.yml +++ b/.github/workflows/forceMergePRBypassAudit.yml @@ -1,5 +1,7 @@ name: Force-Merge PR (Bypass Audit Requirement) # - This git action may only be used in exceptional cases +# - Exceptional cases are for example issues in an audit-protected contract that do not touch the code itself such +# as an issue with the solidity pragma or some issue in a comment # - it can only be executed by the CTO or the Information Security Manager/Architect # - a valid reason must be provided in order to force-merge a given PR @@ -26,6 +28,7 @@ jobs: unset GITHUB_TOKEN ##### Authenticate with Personal Access Token + echo "::add-mask::$GH_PAT" # Mask the token echo $GH_PAT | gh auth login --with-token ##### Fetch team members of 'informationsecuritymanager' team @@ -51,7 +54,10 @@ jobs: ACTOR="${{ github.actor }}" TEAM_MEMBERS=$(cat team_members.txt) - if echo "$TEAM_MEMBERS" | grep -q "^$ACTOR$"; then + # Strict validation of actor against team members + if echo "$TEAM_MEMBERS" | while read -r member; do + [[ "$member" == "$ACTOR" ]] && exit 0 + done; then echo -e "\033[32m$ACTOR is authorized to approve bypasses.\033[0m" echo "CONTINUE=true" >> "$GITHUB_ENV" else @@ -71,12 +77,34 @@ jobs: with: script: | const pr = parseInt(core.getInput('pr_number')); + const { context } = github; console.log(`Merging PR ${pr} now`) - const { context } = github; + // Fetch PR details + const { data: prData } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr + }); + + // Validate PR state + if (!prData.mergeable) { + throw new Error('PR is not in a mergeable state'); + } + await github.rest.pulls.merge({ owner: context.repo.owner, repo: context.repo.repo, pull_number: pr, - merge_method: "squash" + merge_method: "squash", + commit_title: `[BYPASS] ${prData.title}`, + commit_message: `Bypassed by ${context.actor}\nJustification: ${core.getInput('justification')}` }); + + - name: Send Discord message + uses: Ilshidur/action-discord@0.3.2 + with: + args: | + :warning: '${{ github.actor }} just bypassed the audit requirement controls to force-merge PR #${{ github.event.inputs.pr_number }}.' + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_DEV_SMARTCONTRACTS }} From e09372e5fe7ce8192d30b42d59291b7225dcefc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Bl=C3=A4cker?= Date: Thu, 12 Dec 2024 09:23:07 +0700 Subject: [PATCH 3/3] add specific write permissions --- .github/workflows/forceMergePRBypassAudit.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/forceMergePRBypassAudit.yml b/.github/workflows/forceMergePRBypassAudit.yml index 0d5a012fc..6142d8cb0 100644 --- a/.github/workflows/forceMergePRBypassAudit.yml +++ b/.github/workflows/forceMergePRBypassAudit.yml @@ -18,6 +18,9 @@ on: jobs: force-merge-pr-bypass-audit: runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write steps: - name: Fetch Information Security Team Members env: