From a62263e967faa8c51b3bacf5af5b4b329a935690 Mon Sep 17 00:00:00 2001 From: Christian Mesh Date: Thu, 7 Dec 2023 14:58:26 -0500 Subject: [PATCH 1/3] Fix crash when fed invalid key Signed-off-by: Christian Mesh --- src/cmd/verify-gpg-key/main.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 084269ea3d..3f7c82b7bb 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -114,6 +114,11 @@ func VerifyKey(location string) *verification.Step { return nil }) + if key == nil { + // The previous step failed. + return verifyStep + } + verifyStep.RunStep("Key is not expired", func() error { if key.IsExpired() { return fmt.Errorf("key is expired") From 33aaf737dca0bd98f84aeccb6deebb140966b1f2 Mon Sep 17 00:00:00 2001 From: Christian Mesh Date: Thu, 7 Dec 2023 15:31:39 -0500 Subject: [PATCH 2/3] Add provider key submission workflow Signed-off-by: Christian Mesh --- .github/ISSUE_TEMPLATE/provider_key.yml | 24 +++++++ .github/workflows/issue-to-pr.yaml | 87 ++++++++++++++++++++++++- src/cmd/verify-gpg-key/main.go | 18 +++++ 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/provider_key.yml diff --git a/.github/ISSUE_TEMPLATE/provider_key.yml b/.github/ISSUE_TEMPLATE/provider_key.yml new file mode 100644 index 0000000000..9bacd72bc1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/provider_key.yml @@ -0,0 +1,24 @@ +name: Submit new Provider Key +description: Submit a new OpenTofu Provider Key +title: "Provider Key: " +labels: ["provider-key", "submission"] +body: + - type: input + id: namespace + attributes: + label: Provider Namespace + description: Path to a public GitHub repository following the pattern {owner}/terraform-provider-{name}, ex. opentofu/terraform-provider-aws + validations: + required: true + - type: textarea + id: gpgkey + attributes: + label: Provider GPG Key + description: Armoured public PGP key + - type: checkboxes + id: dco + attributes: + label: DCO + options: + - label: I sign this project's [DCO](https://developercertificate.org/) + required: true diff --git a/.github/workflows/issue-to-pr.yaml b/.github/workflows/issue-to-pr.yaml index 271cac608e..e3d97711fa 100644 --- a/.github/workflows/issue-to-pr.yaml +++ b/.github/workflows/issue-to-pr.yaml @@ -74,7 +74,7 @@ jobs: git push -u origin $branch # Create pull request and update issue - pr=$(gh pr create --title "$TITLE" --body "Created $(echo $jsonfile | sed -e 's/../src/') for provider $namespace/$name. See issue #$NUMBER for details.") #--assignee opentofu/core-engineers) + pr=$(gh pr create --title "$TITLE" --body "Created $(echo $jsonfile | sed -e 's/../src/') for provider $namespace/$name. Closes #$NUMBER.") #--assignee opentofu/core-engineers) gh issue comment $NUMBER -b "Your submission has been validated and has moved on to the pull request phase ($pr). This issue has been locked." gh issue lock $NUMBER -r resolved submit-module: @@ -147,6 +147,89 @@ jobs: git push -u origin $branch # Create pull request and update issue - pr=$(gh pr create --title "$TITLE" --body "Created $(echo $jsonfile | sed -e 's/../src/') for module $namespace/$name/$target. See issue #$NUMBER for details.") #--assignee opentofu/core-engineers) + pr=$(gh pr create --title "$TITLE" --body "Created $(echo $jsonfile | sed -e 's/../src/') for module $namespace/$name/$target. Closes #$NUMBER.") #--assignee opentofu/core-engineers) + gh issue comment $NUMBER -b "Your submission has been validated and has moved on to the pull request phase ($pr). This issue has been locked." + gh issue lock $NUMBER -r resolved + submit-provider-key: + if: contains(github.event.issue.labels.*.name, 'provider-key') && contains(github.event.issue.labels.*.name, 'submission') + runs-on: ubuntu-latest + permissions: + issues: write + contents: write + pull-requests: write + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: './src/go.mod' + + - name: Validate Provider and Create PR + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + GH_USER: ${{ github.event.issue.user.login }} + NUMBER: ${{ github.event.issue.number }} + URL: ${{ github.event.issue.url }} + TITLE: ${{ github.event.issue.title }} + BODY: ${{ github.event.issue.body }} + working-directory: ./src + run: | + set +e + echo "$BODY" | grep "\- \[[xX]\] I sign this project's \[DCO\](https://developercertificate.org/)" + if [[ "$?" != 0 ]]; then + gh issue comment $NUMBER -b "DCO must be signed to submit this repository" + exit 1 + fi + set -e + + namespace=$(echo "$BODY" | grep "### Provider Namespace" -A2 | tail -n1 | tr "[:upper:]" "[:lower:]" | sed -e 's/[\r\n]//g') + keydata=$(echo "$BODY" | grep -A 1000 "BEGIN PGP PUBLIC KEY BLOCK" | grep -B 1000 "END PGP PUBLIC KEY BLOCK") + echo "$keydata" > tmp.key + + set +e + go run ./cmd/verify-gpg-key -org "$namespace" -username "$GH_USER" -key-file=tmp.key -output=./output.json + verification=$? + set -e + + gh issue comment $NUMBER -b "$(cat ./output.json | jq -r '.')" + if [[ "$verification" != 0 ]]; then + exit 1 + fi + + keyfile="../keys/${namespace:0:1}/$namespace/provider.asc" + if [ -d $(dirname $keyfile) ]; then + msg=Updated + git rm $(dirname $keyfile)/* + else + msg=Created + fi + mkdir -p $(dirname $keyfile) + mv tmp.key $keyfile + + # Create Branch + branch=provider-key-submission_${namespace} + set +e + git checkout -b $branch + if [[ "$?" != 0 ]]; then + gh issue comment $NUMBER -b "Failed validation: A branch already exists for this provider '$branch'" + exit 1 + fi + set -e + + # Add result + git add $keyfile + + # Commit and push result + git config --global user.email "no-reply@opentofu.org" + git config --global user.name "OpenTofu Automation" + git commit -s -m "Create provider key $namespace/$name" + git push -u origin $branch + + # Create pull request and update issue + pr=$(gh pr create --title "$TITLE" --body "$msg $(echo $keyfile | sed -e 's/.././') for provider $namespace. Closes #$NUMBER.") #--assignee opentofu/core-engineers) gh issue comment $NUMBER -b "Your submission has been validated and has moved on to the pull request phase ($pr). This issue has been locked." gh issue lock $NUMBER -r resolved diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 3f7c82b7bb..fca7b7bc8c 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -10,6 +10,7 @@ import ( "regexp" "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/opentofu/registry-stable/internal/files" "github.com/opentofu/registry-stable/internal/github" "github.com/opentofu/registry-stable/internal/gpg" "github.com/opentofu/registry-stable/pkg/verification" @@ -22,6 +23,7 @@ func main() { keyFile := flag.String("key-file", "", "Location of the GPG key to verify") username := flag.String("username", "", "Github username to verify the GPG key against") orgName := flag.String("org", "", "Github organization name to verify the GPG key against") + outputFile := flag.String("output", "", "Path to write JSON result to") flag.Parse() logger = logger.With(slog.String("github", *username), slog.String("org", *orgName)) @@ -48,6 +50,18 @@ func main() { // TODO: Add verification to ensure that the key has been used to sign providers in this github organization fmt.Println(result.RenderMarkdown()) + + if *outputFile != "" { + jsonErr := files.SafeWriteObjectToJSONFile(*outputFile, result.RenderMarkdown()) + if jsonErr != nil { + // This really should not happen + panic(jsonErr) + } + } + + if result.DidFail() { + os.Exit(-1) + } } func VerifyGithubUser(client github.Client, username string, orgName string) *verification.Step { @@ -74,6 +88,10 @@ func VerifyGithubUser(client github.Client, username string, orgName string) *ve } s := verifyStep.RunStep(fmt.Sprintf("User is a member of the organization %s", orgName), func() error { + if username == orgName { + // Adding to user namespace not org namespace + return nil + } // Todo: maybe handle pagination, but in theory I doubt people are in 99+ organizations for _, org := range user.User.Organizations.Nodes { if org.Name == githubv4.String(orgName) { From 762d15e79f70fe4fe00d9c65d726a1fb7cc5ae11 Mon Sep 17 00:00:00 2001 From: Christian Mesh Date: Fri, 8 Dec 2023 10:54:51 -0500 Subject: [PATCH 3/3] Fix description of signing keys Signed-off-by: Christian Mesh --- .github/ISSUE_TEMPLATE/provider_key.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/provider_key.yml b/.github/ISSUE_TEMPLATE/provider_key.yml index 9bacd72bc1..5465ab98fa 100644 --- a/.github/ISSUE_TEMPLATE/provider_key.yml +++ b/.github/ISSUE_TEMPLATE/provider_key.yml @@ -1,5 +1,5 @@ -name: Submit new Provider Key -description: Submit a new OpenTofu Provider Key +name: Submit new Provider Signing Key +description: Submit a new OpenTofu Provider Signing Key title: "Provider Key: " labels: ["provider-key", "submission"] body: @@ -7,7 +7,7 @@ body: id: namespace attributes: label: Provider Namespace - description: Path to a public GitHub repository following the pattern {owner}/terraform-provider-{name}, ex. opentofu/terraform-provider-aws + description: Github Username or Organization that contains Providers validations: required: true - type: textarea