From edf5b776e082f41e9d484e4efc20ede6856ff800 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Sat, 4 Jan 2025 01:43:04 -0300 Subject: [PATCH 01/23] feat: add initial code for checkers Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 3 +- .../verify-gpg-key/verify-key-in-providers.go | 139 ++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/cmd/verify-gpg-key/verify-key-in-providers.go diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index adcc7d5260..3d990f6200 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -47,7 +47,8 @@ func main() { s = VerifyGithubUser(ghClient, *username, *orgName) result.Steps = append(result.Steps, s) - // TODO: Add verification to ensure that the key has been used to sign providers in this github organization + s = VerifyKeyInProviders(logger, ghClient, *keyFile, *orgName) + result.Steps = append(result.Steps, s) fmt.Println(result.RenderMarkdown()) diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go new file mode 100644 index 0000000000..efe2ee7907 --- /dev/null +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -0,0 +1,139 @@ +package main + +import ( + "fmt" + "log/slog" + "os" + "os/exec" + "strings" + + "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/opentofu/registry-stable/internal/github" + "github.com/opentofu/registry-stable/internal/gpg" + "github.com/opentofu/registry-stable/internal/parallel" + "github.com/opentofu/registry-stable/internal/provider" + "github.com/opentofu/registry-stable/pkg/verification" +) + +const templateString = ` +terraform { + required_providers { + %s = { + source = "%s/%s" + version = "%s" + } + } +} +` + +func VerifyKeyInProviders(logger *slog.Logger, ghClient github.Client, location string, orgName string) *verification.Step { + + verifyStep := &verification.Step{ + Name: "Verify GPG key in providers", + } + + providerDataDir := "../providers" + providerNamespace := "" + + // read the key from the filesystem + data, err := os.ReadFile(location) + if err != nil { + verifyStep.AddError(fmt.Errorf("failed to read key file: %w", err)) + verifyStep.Status = verification.StatusFailure + return verifyStep + } + + var key *crypto.Key + verifyStep.RunStep("Key is a valid PGP key", func() error { + k, err := gpg.ParseKey(string(data)) + if err != nil { + return fmt.Errorf("could not parse key: %w", err) + } + key = k + return nil + }) + + if key == nil { + logger.Error("Failed to parse key", slog.Any("err", err)) + } + + providers, err := provider.ListProviders(providerDataDir, providerNamespace, logger, ghClient) + if err != nil { + logger.Error("Failed to list providers", slog.Any("err", err)) + os.Exit(1) + } + err = providers.Parallel(10, func(p provider.Provider) error { + if p.Namespace == "opentofu" || p.Namespace == "hashicorp" { + // Skip! + return nil + } + + metadata, err := p.ReadMetadata() + if err != nil { + return err + } + + pke := ProviderKeyCheckError{p: p, errs: make(map[string]error)} + + actions := make([]parallel.Action, len(metadata.Versions)) + for i, ver := range metadata.Versions { + ver := ver + actions[i] = func() error { + dir, err := os.MkdirTemp("", "provider-keys") + if err != nil { + return err + } + defer os.RemoveAll(dir) + + contents := fmt.Sprintf(templateString, p.ProviderName, p.Namespace, p.ProviderName, ver.Version) + err = os.WriteFile(dir+"/main.tf", []byte(contents), 0644) + if err != nil { + return err + } + + p.Logger.Info(fmt.Sprintf("Checking version %s", ver.Version)) + cmd := exec.Command("/opt/homebrew/bin/tofu", "init", "-no-color") + cmd.Dir = dir + out := new(strings.Builder) + cmd.Stdout = out + cmd.Stderr = out + if err := cmd.Run(); err != nil { + p.Logger.Info(fmt.Sprintf("Version %s failed!", ver.Version), "out", out.String()) + pke.errs[ver.Version] = fmt.Errorf("%w: %s", err, out.String()) + } + return nil + } + } + + errs := parallel.ForEach(actions, 10) + if len(errs) != 0 { + return fmt.Errorf("encountered %d errors processing %d provider keys", len(errs), len(metadata.Versions)) + } + + if len(pke.errs) != 0 { + return pke + } + + return nil + }) + if err != nil { + logger.Error(err.Error()) + os.Exit(1) + } + + logger.Info("Completed ") + return verifyStep +} + +type ProviderKeyCheckError struct { + p provider.Provider + errs map[string]error +} + +func (err ProviderKeyCheckError) Error() string { + msg := fmt.Sprintf("%s/%s encountered %d versions with errors:", err.p.Namespace, err.p.ProviderName, len(err.errs)) + for ver, verr := range err.errs { + msg += fmt.Sprintf("\n\t%s: %s", ver, verr) + } + return msg +} From 65886f372b3ca7aa0371f58745ee3820f889036b Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Sun, 5 Jan 2025 09:52:55 -0300 Subject: [PATCH 02/23] verifying using shamsumsrl + shasumnurlsignatur Signed-off-by: Diogenes Fernandes --- .../verify-gpg-key/verify-key-in-providers.go | 110 ++++++++++++------ src/internal/gpg/key.go | 9 ++ 2 files changed, 81 insertions(+), 38 deletions(-) diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index efe2ee7907..1bca9a8363 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -2,10 +2,10 @@ package main import ( "fmt" + "io" "log/slog" + "net/http" "os" - "os/exec" - "strings" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/opentofu/registry-stable/internal/github" @@ -15,25 +15,14 @@ import ( "github.com/opentofu/registry-stable/pkg/verification" ) -const templateString = ` -terraform { - required_providers { - %s = { - source = "%s/%s" - version = "%s" - } - } -} -` - func VerifyKeyInProviders(logger *slog.Logger, ghClient github.Client, location string, orgName string) *verification.Step { verifyStep := &verification.Step{ Name: "Verify GPG key in providers", } - providerDataDir := "../providers" - providerNamespace := "" + providerDataDir := "/Users/diogenesaherminio/workspace/opentofu/opentofu-registry/providers" + providerNamespace := "wombelix" // read the key from the filesystem data, err := os.ReadFile(location) @@ -53,15 +42,28 @@ func VerifyKeyInProviders(logger *slog.Logger, ghClient github.Client, location return nil }) - if key == nil { - logger.Error("Failed to parse key", slog.Any("err", err)) - } + logger.Info(key.GetArmoredPublicKey()) providers, err := provider.ListProviders(providerDataDir, providerNamespace, logger, ghClient) - if err != nil { - logger.Error("Failed to list providers", slog.Any("err", err)) - os.Exit(1) - } + verifyStep.RunStep("Provider list is valid", func() error { + if err != nil { + return fmt.Errorf("could not read providers: %w", err) + } + return nil + }) + + signingKeyRing, err := gpg.BuildSigningKeyRing(key) + verifyStep.RunStep("Can build a valid keyring", func() error { + if err != nil { + return fmt.Errorf("could not read build a keyring: %w", err) + } + return nil + }) + + logger.Info("Keyring", slog.String("keyring", signingKeyRing.FirstKeyID)) + logger.Info("Providers", slog.String("providers", providers[0].ProviderName)) + logger.Info("Providers", slog.String("providers", providers[0].Namespace)) + err = providers.Parallel(10, func(p provider.Provider) error { if p.Namespace == "opentofu" || p.Namespace == "hashicorp" { // Skip! @@ -77,7 +79,6 @@ func VerifyKeyInProviders(logger *slog.Logger, ghClient github.Client, location actions := make([]parallel.Action, len(metadata.Versions)) for i, ver := range metadata.Versions { - ver := ver actions[i] = func() error { dir, err := os.MkdirTemp("", "provider-keys") if err != nil { @@ -85,22 +86,59 @@ func VerifyKeyInProviders(logger *slog.Logger, ghClient github.Client, location } defer os.RemoveAll(dir) - contents := fmt.Sprintf(templateString, p.ProviderName, p.Namespace, p.ProviderName, ver.Version) - err = os.WriteFile(dir+"/main.tf", []byte(contents), 0644) + // Check ShaSum signature + resp, err := http.Get(ver.SHASumsURL) if err != nil { return err } + defer resp.Body.Close() - p.Logger.Info(fmt.Sprintf("Checking version %s", ver.Version)) - cmd := exec.Command("/opt/homebrew/bin/tofu", "init", "-no-color") - cmd.Dir = dir - out := new(strings.Builder) - cmd.Stdout = out - cmd.Stderr = out - if err := cmd.Run(); err != nil { - p.Logger.Info(fmt.Sprintf("Version %s failed!", ver.Version), "out", out.String()) - pke.errs[ver.Version] = fmt.Errorf("%w: %s", err, out.String()) + respSig, err := http.Get(ver.SHASumsSignatureURL) + if err != nil { + return err } + defer respSig.Body.Close() + + fileBytes, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + providerData := crypto.NewPlainMessage(fileBytes) + + fileSigBytes, err := io.ReadAll(respSig.Body) + if err != nil { + return err + } + + pgpSignature := crypto.NewPGPSignature(fileSigBytes) + + err = signingKeyRing.VerifyDetached(providerData, pgpSignature, crypto.GetUnixTime()) + if err != nil { + return err + } + + logger.Info("Verified", slog.String("provider", ver.SHASumsURL)) + + // Option 2: Download versions and check in another way - need to talk to core devs + // for _, target := range ver.Targets { + // resp, err := http.Get(target.DownloadURL) + // if err != nil { + // return err + // } + // defer resp.Body.Close() + + // bodyBytes, err := io.ReadAll(resp.Body) + // providerData := crypto.NewPlainMessage(bodyBytes) + + // verifyResult, err := signingKeyRing.VerifyDetached(providerData, crypto.GetUnixTime()) + // if err != nil { + // return err + // } + + // logger.Info("Verified", slog.String("provider", target.DownloadURL)) + // return nil + // } return nil } } @@ -116,10 +154,6 @@ func VerifyKeyInProviders(logger *slog.Logger, ghClient github.Client, location return nil }) - if err != nil { - logger.Error(err.Error()) - os.Exit(1) - } logger.Info("Completed ") return verifyStep diff --git a/src/internal/gpg/key.go b/src/internal/gpg/key.go index b406a9c2a7..04b1b4ee89 100644 --- a/src/internal/gpg/key.go +++ b/src/internal/gpg/key.go @@ -48,3 +48,12 @@ func ParseKey(data string) (*crypto.Key, error) { return key, nil } + +func BuildSigningKeyRing(pubKeyObj *crypto.Key) (*crypto.KeyRing, error) { + signingKeyRing, err := crypto.NewKeyRing(pubKeyObj) + if err != nil { + return nil, fmt.Errorf("could not build keyring: %w", err) + } + + return signingKeyRing, nil +} From 5a6e562ec48dea3d8d8bd7a86c90b02f8fa36670 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 10:58:25 -0300 Subject: [PATCH 03/23] Using libregistry to validate the keys Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 17 +- .../verify-gpg-key/verify-key-in-providers.go | 172 ++---------------- src/internal/gpg/key.go | 16 +- 3 files changed, 41 insertions(+), 164 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 3d990f6200..cea3d5630a 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -8,6 +8,7 @@ import ( "net/mail" "os" "regexp" + "time" "github.com/ProtonMail/gopenpgp/v2/crypto" @@ -36,20 +37,17 @@ func main() { os.Exit(1) } - ctx := context.Background() + ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) ghClient := github.NewClient(ctx, logger, token) result := &verification.Result{} - s := VerifyKey(*keyFile) + s := VerifyKey(ctx, *keyFile, *orgName) result.Steps = append(result.Steps, s) s = VerifyGithubUser(ghClient, *username, *orgName) result.Steps = append(result.Steps, s) - s = VerifyKeyInProviders(logger, ghClient, *keyFile, *orgName) - result.Steps = append(result.Steps, s) - fmt.Println(result.RenderMarkdown()) if *outputFile != "" { @@ -88,7 +86,7 @@ func VerifyGithubUser(client github.Client, username string, orgName string) *ve var gpgNameEmailRegex = regexp.MustCompile(`.*\<(.*)\>`) -func VerifyKey(location string) *verification.Step { +func VerifyKey(ctx context.Context, location string, orgName string) *verification.Step { verifyStep := &verification.Step{ Name: "Validate GPG key", } @@ -171,6 +169,13 @@ func VerifyKey(location string) *verification.Step { return nil }) + verifyStep.RunStep("Key is used to sign the provider", func() error { + if err := verifyKeyInProviders(ctx, key, orgName); err != nil { + return fmt.Errorf("key is not used to sign the provider: %w", err) + } + return nil + }) + emailStep.FailureToWarning() return verifyStep diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index 1bca9a8363..f53d54a773 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -1,173 +1,31 @@ package main import ( - "fmt" - "io" - "log/slog" + "context" "net/http" - "os" + "time" "github.com/ProtonMail/gopenpgp/v2/crypto" - "github.com/opentofu/registry-stable/internal/github" - "github.com/opentofu/registry-stable/internal/gpg" - "github.com/opentofu/registry-stable/internal/parallel" - "github.com/opentofu/registry-stable/internal/provider" - "github.com/opentofu/registry-stable/pkg/verification" + "github.com/opentofu/libregistry/key_verification" + "github.com/opentofu/libregistry/metadata/storage/filesystem" ) -func VerifyKeyInProviders(logger *slog.Logger, ghClient github.Client, location string, orgName string) *verification.Step { +func verifyKeyInProviders(ctx context.Context, key *crypto.Key, providerNamespace string) error { + providerDataDir := "/Users/diogenesaherminio/workspace/opentofu/opentofu-registry/providers" + storage := filesystem.New(providerDataDir) - verifyStep := &verification.Step{ - Name: "Verify GPG key in providers", + httpClient := http.Client{ + Timeout: time.Second * 10, } - providerDataDir := "/Users/diogenesaherminio/workspace/opentofu/opentofu-registry/providers" - providerNamespace := "wombelix" - - // read the key from the filesystem - data, err := os.ReadFile(location) + keyVerification, err := key_verification.New(httpClient, storage) if err != nil { - verifyStep.AddError(fmt.Errorf("failed to read key file: %w", err)) - verifyStep.Status = verification.StatusFailure - return verifyStep + return err } - var key *crypto.Key - verifyStep.RunStep("Key is a valid PGP key", func() error { - k, err := gpg.ParseKey(string(data)) - if err != nil { - return fmt.Errorf("could not parse key: %w", err) - } - key = k - return nil - }) - - logger.Info(key.GetArmoredPublicKey()) - - providers, err := provider.ListProviders(providerDataDir, providerNamespace, logger, ghClient) - verifyStep.RunStep("Provider list is valid", func() error { - if err != nil { - return fmt.Errorf("could not read providers: %w", err) - } - return nil - }) - - signingKeyRing, err := gpg.BuildSigningKeyRing(key) - verifyStep.RunStep("Can build a valid keyring", func() error { - if err != nil { - return fmt.Errorf("could not read build a keyring: %w", err) - } - return nil - }) - - logger.Info("Keyring", slog.String("keyring", signingKeyRing.FirstKeyID)) - logger.Info("Providers", slog.String("providers", providers[0].ProviderName)) - logger.Info("Providers", slog.String("providers", providers[0].Namespace)) - - err = providers.Parallel(10, func(p provider.Provider) error { - if p.Namespace == "opentofu" || p.Namespace == "hashicorp" { - // Skip! - return nil - } - - metadata, err := p.ReadMetadata() - if err != nil { - return err - } - - pke := ProviderKeyCheckError{p: p, errs: make(map[string]error)} - - actions := make([]parallel.Action, len(metadata.Versions)) - for i, ver := range metadata.Versions { - actions[i] = func() error { - dir, err := os.MkdirTemp("", "provider-keys") - if err != nil { - return err - } - defer os.RemoveAll(dir) - - // Check ShaSum signature - resp, err := http.Get(ver.SHASumsURL) - if err != nil { - return err - } - defer resp.Body.Close() - - respSig, err := http.Get(ver.SHASumsSignatureURL) - if err != nil { - return err - } - defer respSig.Body.Close() - - fileBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - providerData := crypto.NewPlainMessage(fileBytes) - - fileSigBytes, err := io.ReadAll(respSig.Body) - if err != nil { - return err - } - - pgpSignature := crypto.NewPGPSignature(fileSigBytes) - - err = signingKeyRing.VerifyDetached(providerData, pgpSignature, crypto.GetUnixTime()) - if err != nil { - return err - } - - logger.Info("Verified", slog.String("provider", ver.SHASumsURL)) - - // Option 2: Download versions and check in another way - need to talk to core devs - // for _, target := range ver.Targets { - // resp, err := http.Get(target.DownloadURL) - // if err != nil { - // return err - // } - // defer resp.Body.Close() - - // bodyBytes, err := io.ReadAll(resp.Body) - // providerData := crypto.NewPlainMessage(bodyBytes) - - // verifyResult, err := signingKeyRing.VerifyDetached(providerData, crypto.GetUnixTime()) - // if err != nil { - // return err - // } - - // logger.Info("Verified", slog.String("provider", target.DownloadURL)) - // return nil - // } - return nil - } - } - - errs := parallel.ForEach(actions, 10) - if len(errs) != 0 { - return fmt.Errorf("encountered %d errors processing %d provider keys", len(errs), len(metadata.Versions)) - } - - if len(pke.errs) != 0 { - return pke - } - - return nil - }) - - logger.Info("Completed ") - return verifyStep -} - -type ProviderKeyCheckError struct { - p provider.Provider - errs map[string]error -} - -func (err ProviderKeyCheckError) Error() string { - msg := fmt.Sprintf("%s/%s encountered %d versions with errors:", err.p.Namespace, err.p.ProviderName, len(err.errs)) - for ver, verr := range err.errs { - msg += fmt.Sprintf("\n\t%s: %s", ver, verr) + if err := keyVerification.VerifyKey(ctx, key, providerNamespace); err != nil { + return err } - return msg + + return nil } diff --git a/src/internal/gpg/key.go b/src/internal/gpg/key.go index 04b1b4ee89..3714913cfd 100644 --- a/src/internal/gpg/key.go +++ b/src/internal/gpg/key.go @@ -49,7 +49,7 @@ func ParseKey(data string) (*crypto.Key, error) { return key, nil } -func BuildSigningKeyRing(pubKeyObj *crypto.Key) (*crypto.KeyRing, error) { +func parseKeyRing(pubKeyObj *crypto.Key) (*crypto.KeyRing, error) { signingKeyRing, err := crypto.NewKeyRing(pubKeyObj) if err != nil { return nil, fmt.Errorf("could not build keyring: %w", err) @@ -57,3 +57,17 @@ func BuildSigningKeyRing(pubKeyObj *crypto.Key) (*crypto.KeyRing, error) { return signingKeyRing, nil } + +func ParseSigningKeyRing(data string) (*crypto.KeyRing, error) { + key, err := ParseKey(data) + if err != nil { + return nil, fmt.Errorf("could not parse key: %w", err) + } + + keyring, err := parseKeyRing(key) + if err != nil { + return nil, fmt.Errorf("could not build keyring: %w", err) + } + + return keyring, nil +} From 4b8d25428a8cc9b04ab5e498e83edbc326ad0091 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 11:02:15 -0300 Subject: [PATCH 04/23] Passing the provider data dir Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 7 ++++--- src/cmd/verify-gpg-key/verify-key-in-providers.go | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index cea3d5630a..be148e9567 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -25,6 +25,7 @@ func main() { 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") + providerDataDir := flag.String("provider-data", "../providers", "Directory containing the provider data") flag.Parse() logger = logger.With(slog.String("github", *username), slog.String("org", *orgName)) @@ -42,7 +43,7 @@ func main() { result := &verification.Result{} - s := VerifyKey(ctx, *keyFile, *orgName) + s := VerifyKey(ctx, *providerDataDir, *keyFile, *orgName) result.Steps = append(result.Steps, s) s = VerifyGithubUser(ghClient, *username, *orgName) @@ -86,7 +87,7 @@ func VerifyGithubUser(client github.Client, username string, orgName string) *ve var gpgNameEmailRegex = regexp.MustCompile(`.*\<(.*)\>`) -func VerifyKey(ctx context.Context, location string, orgName string) *verification.Step { +func VerifyKey(ctx context.Context, providerDataDir string, location string, orgName string) *verification.Step { verifyStep := &verification.Step{ Name: "Validate GPG key", } @@ -170,7 +171,7 @@ func VerifyKey(ctx context.Context, location string, orgName string) *verificati }) verifyStep.RunStep("Key is used to sign the provider", func() error { - if err := verifyKeyInProviders(ctx, key, orgName); err != nil { + if err := verifyKeyInProviders(ctx, providerDataDir, key, orgName); err != nil { return fmt.Errorf("key is not used to sign the provider: %w", err) } return nil diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index f53d54a773..23e85162a6 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -10,8 +10,7 @@ import ( "github.com/opentofu/libregistry/metadata/storage/filesystem" ) -func verifyKeyInProviders(ctx context.Context, key *crypto.Key, providerNamespace string) error { - providerDataDir := "/Users/diogenesaherminio/workspace/opentofu/opentofu-registry/providers" +func verifyKeyInProviders(ctx context.Context, providerDataDir string, key *crypto.Key, providerNamespace string) error { storage := filesystem.New(providerDataDir) httpClient := http.Client{ From 84c5a0a5bf4678700aac2e8ee27819995ca4cea1 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 11:03:37 -0300 Subject: [PATCH 05/23] Removing unused func Signed-off-by: Diogenes Fernandes --- src/internal/gpg/key.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/internal/gpg/key.go b/src/internal/gpg/key.go index 3714913cfd..70fe7f2c3e 100644 --- a/src/internal/gpg/key.go +++ b/src/internal/gpg/key.go @@ -57,17 +57,3 @@ func parseKeyRing(pubKeyObj *crypto.Key) (*crypto.KeyRing, error) { return signingKeyRing, nil } - -func ParseSigningKeyRing(data string) (*crypto.KeyRing, error) { - key, err := ParseKey(data) - if err != nil { - return nil, fmt.Errorf("could not parse key: %w", err) - } - - keyring, err := parseKeyRing(key) - if err != nil { - return nil, fmt.Errorf("could not build keyring: %w", err) - } - - return keyring, nil -} From 484d1ea66e46cc2f11646691b78198d1857adf24 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 11:04:42 -0300 Subject: [PATCH 06/23] Removing unused funcs Signed-off-by: Diogenes Fernandes --- src/internal/gpg/key.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/internal/gpg/key.go b/src/internal/gpg/key.go index 70fe7f2c3e..b406a9c2a7 100644 --- a/src/internal/gpg/key.go +++ b/src/internal/gpg/key.go @@ -48,12 +48,3 @@ func ParseKey(data string) (*crypto.Key, error) { return key, nil } - -func parseKeyRing(pubKeyObj *crypto.Key) (*crypto.KeyRing, error) { - signingKeyRing, err := crypto.NewKeyRing(pubKeyObj) - if err != nil { - return nil, fmt.Errorf("could not build keyring: %w", err) - } - - return signingKeyRing, nil -} From 19bcd93949122cc148f36bfb571ea8e0308f6c23 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 12:46:23 -0300 Subject: [PATCH 07/23] Adding step per provider Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 39 +++++++++++++++---- .../verify-gpg-key/verify-key-in-providers.go | 35 +++++++++++------ 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index be148e9567..d1d64557db 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -12,6 +12,7 @@ import ( "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/opentofu/libregistry/metadata/storage/filesystem" "github.com/opentofu/registry-stable/internal/files" "github.com/opentofu/registry-stable/internal/github" "github.com/opentofu/registry-stable/internal/gpg" @@ -25,7 +26,7 @@ func main() { 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") - providerDataDir := flag.String("provider-data", "../providers", "Directory containing the provider data") + providerDataDir := flag.String("provider-data", "..", "Directory containing the provider data") flag.Parse() logger = logger.With(slog.String("github", *username), slog.String("org", *orgName)) @@ -43,6 +44,11 @@ func main() { result := &verification.Result{} + if err != nil { + logger.Error("Error getting absolute path", slog.Any("err", err)) + os.Exit(1) + } + s := VerifyKey(ctx, *providerDataDir, *keyFile, *orgName) result.Steps = append(result.Steps, s) @@ -170,12 +176,31 @@ func VerifyKey(ctx context.Context, providerDataDir string, location string, org return nil }) - verifyStep.RunStep("Key is used to sign the provider", func() error { - if err := verifyKeyInProviders(ctx, providerDataDir, key, orgName); err != nil { - return fmt.Errorf("key is not used to sign the provider: %w", err) - } - return nil - }) + storageAPI := filesystem.New(providerDataDir) + providers, err := listProviders(ctx, storageAPI, orgName) + + if err != nil { + verifyStep.AddError(fmt.Errorf("failed to list provider %s: %w", orgName, err)) + verifyStep.Status = verification.StatusFailure + return verifyStep + } + + keyVerification, err := buildKeyVerifier(storageAPI) + if err != nil { + verifyStep.AddError(fmt.Errorf("failed to build key verifier: %w", err)) + verifyStep.Status = verification.StatusFailure + return verifyStep + } + + for _, provider := range providers { + stepName := fmt.Sprintf("Key is used to sign the provider %s", provider) + verifyStep.RunStep(stepName, func() error { + if err := keyVerification.VerifyKey(ctx, key, provider); err != nil { + return err + } + return nil + }) + } emailStep.FailureToWarning() diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index 23e85162a6..0af6dfcc8d 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -2,29 +2,42 @@ package main import ( "context" + "fmt" "net/http" "time" - "github.com/ProtonMail/gopenpgp/v2/crypto" - "github.com/opentofu/libregistry/key_verification" - "github.com/opentofu/libregistry/metadata/storage/filesystem" + "github.com/opentofu/libregistry/metadata" + "github.com/opentofu/libregistry/metadata/storage" + "github.com/opentofu/libregistry/provider_verification" + "github.com/opentofu/libregistry/types/provider" ) -func verifyKeyInProviders(ctx context.Context, providerDataDir string, key *crypto.Key, providerNamespace string) error { - storage := filesystem.New(providerDataDir) - +func buildKeyVerifier(storageAPI storage.API) (provider_verification.KeyVerification, error) { httpClient := http.Client{ Timeout: time.Second * 10, } - keyVerification, err := key_verification.New(httpClient, storage) + keyVerification, err := provider_verification.New(httpClient, storageAPI) + if err != nil { + return nil, err + } + return keyVerification, nil +} + +func listProviders(ctx context.Context, storageAPI storage.API, namespace string) ([]provider.Addr, error) { + dataAPI, err := metadata.New(storageAPI) + if err != nil { + return nil, err + } + + providers, err := dataAPI.ListProvidersByNamespace(ctx, namespace, false) if err != nil { - return err + return nil, err } - if err := keyVerification.VerifyKey(ctx, key, providerNamespace); err != nil { - return err + if len(providers) == 0 { + return nil, fmt.Errorf("no providers found for namespace %s", namespace) } - return nil + return providers, nil } From 6b3ddba2c5d8ad8a9571b504f4a3aa92e06f5947 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 12:50:25 -0300 Subject: [PATCH 08/23] Rename to provider_verifier Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/verify-key-in-providers.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index 0af6dfcc8d..3e0bb713aa 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -8,16 +8,16 @@ import ( "github.com/opentofu/libregistry/metadata" "github.com/opentofu/libregistry/metadata/storage" - "github.com/opentofu/libregistry/provider_verification" + "github.com/opentofu/libregistry/provider_verifier" "github.com/opentofu/libregistry/types/provider" ) -func buildKeyVerifier(storageAPI storage.API) (provider_verification.KeyVerification, error) { +func buildKeyVerifier(storageAPI storage.API) (provider_verifier.KeyVerification, error) { httpClient := http.Client{ Timeout: time.Second * 10, } - keyVerification, err := provider_verification.New(httpClient, storageAPI) + keyVerification, err := provider_verifier.New(httpClient, storageAPI) if err != nil { return nil, err } From e9f0f36cbadc703db659b2b5ba64baffceaabe2d Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 12:51:27 -0300 Subject: [PATCH 09/23] unused code Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index d1d64557db..2102766dad 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -44,11 +44,6 @@ func main() { result := &verification.Result{} - if err != nil { - logger.Error("Error getting absolute path", slog.Any("err", err)) - os.Exit(1) - } - s := VerifyKey(ctx, *providerDataDir, *keyFile, *orgName) result.Steps = append(result.Steps, s) From ed6662e390ad4fbe81ddbf14208c02910149354c Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Fri, 10 Jan 2025 13:02:13 -0300 Subject: [PATCH 10/23] using metadata api directly Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 13 ++++++++++--- src/cmd/verify-gpg-key/verify-key-in-providers.go | 12 +++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 2102766dad..9181877b32 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -12,6 +12,7 @@ import ( "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/opentofu/libregistry/metadata" "github.com/opentofu/libregistry/metadata/storage/filesystem" "github.com/opentofu/registry-stable/internal/files" "github.com/opentofu/registry-stable/internal/github" @@ -171,8 +172,14 @@ func VerifyKey(ctx context.Context, providerDataDir string, location string, org return nil }) - storageAPI := filesystem.New(providerDataDir) - providers, err := listProviders(ctx, storageAPI, orgName) + dataAPI, err := metadata.New(filesystem.New(providerDataDir)) + if err != nil { + verifyStep.AddError(fmt.Errorf("failed to create a metadata API: %w", err)) + verifyStep.Status = verification.StatusFailure + return verifyStep + } + + providers, err := listProviders(ctx, dataAPI, orgName) if err != nil { verifyStep.AddError(fmt.Errorf("failed to list provider %s: %w", orgName, err)) @@ -180,7 +187,7 @@ func VerifyKey(ctx context.Context, providerDataDir string, location string, org return verifyStep } - keyVerification, err := buildKeyVerifier(storageAPI) + keyVerification, err := buildKeyVerifier(dataAPI) if err != nil { verifyStep.AddError(fmt.Errorf("failed to build key verifier: %w", err)) verifyStep.Status = verification.StatusFailure diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index 3e0bb713aa..8d88a4be18 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -7,29 +7,23 @@ import ( "time" "github.com/opentofu/libregistry/metadata" - "github.com/opentofu/libregistry/metadata/storage" "github.com/opentofu/libregistry/provider_verifier" "github.com/opentofu/libregistry/types/provider" ) -func buildKeyVerifier(storageAPI storage.API) (provider_verifier.KeyVerification, error) { +func buildKeyVerifier(dataAPI metadata.API) (provider_verifier.KeyVerification, error) { httpClient := http.Client{ Timeout: time.Second * 10, } - keyVerification, err := provider_verifier.New(httpClient, storageAPI) + keyVerification, err := provider_verifier.New(httpClient, dataAPI) if err != nil { return nil, err } return keyVerification, nil } -func listProviders(ctx context.Context, storageAPI storage.API, namespace string) ([]provider.Addr, error) { - dataAPI, err := metadata.New(storageAPI) - if err != nil { - return nil, err - } - +func listProviders(ctx context.Context, dataAPI metadata.API, namespace string) ([]provider.Addr, error) { providers, err := dataAPI.ListProvidersByNamespace(ctx, namespace, false) if err != nil { return nil, err From 6af47aaa3feaba62826b23a24eaa34e833111e44 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Mon, 13 Jan 2025 10:09:32 -0300 Subject: [PATCH 11/23] addressing more suggestions from abstractionFactory Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 8 ++++---- src/cmd/verify-gpg-key/verify-key-in-providers.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 9181877b32..02cf0a4ea3 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -40,7 +40,7 @@ func main() { os.Exit(1) } - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, _ := context.WithTimeout(context.Background(), 60*time.Second) ghClient := github.NewClient(ctx, logger, token) result := &verification.Result{} @@ -95,7 +95,7 @@ func VerifyKey(ctx context.Context, providerDataDir string, location string, org } // read the key from the filesystem - data, err := os.ReadFile(location) + keyData, err := os.ReadFile(location) if err != nil { verifyStep.AddError(fmt.Errorf("failed to read key file: %w", err)) verifyStep.Status = verification.StatusFailure @@ -104,7 +104,7 @@ func VerifyKey(ctx context.Context, providerDataDir string, location string, org var key *crypto.Key verifyStep.RunStep("Key is a valid PGP key", func() error { - k, err := gpg.ParseKey(string(data)) + k, err := gpg.ParseKey(string(keyData)) if err != nil { return fmt.Errorf("could not parse key: %w", err) } @@ -197,7 +197,7 @@ func VerifyKey(ctx context.Context, providerDataDir string, location string, org for _, provider := range providers { stepName := fmt.Sprintf("Key is used to sign the provider %s", provider) verifyStep.RunStep(stepName, func() error { - if err := keyVerification.VerifyKey(ctx, key, provider); err != nil { + if err := keyVerification.VerifyKey(ctx, keyData, provider); err != nil { return err } return nil diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index 8d88a4be18..24172394a1 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -13,7 +13,7 @@ import ( func buildKeyVerifier(dataAPI metadata.API) (provider_verifier.KeyVerification, error) { httpClient := http.Client{ - Timeout: time.Second * 10, + Timeout: 60 * time.Second, } keyVerification, err := provider_verifier.New(httpClient, dataAPI) @@ -30,7 +30,7 @@ func listProviders(ctx context.Context, dataAPI metadata.API, namespace string) } if len(providers) == 0 { - return nil, fmt.Errorf("no providers found for namespace %s", namespace) + return nil, fmt.Errorf("there are no providers in namespace %s; please submit at least one provider before submitting a GPG key", namespace) } return providers, nil From e1faecf18fce0c4212ef88e453664b292912965e Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Mon, 13 Jan 2025 11:54:32 -0300 Subject: [PATCH 12/23] call cancel from context.WithTimeout Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 02cf0a4ea3..44e904966e 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -40,7 +40,9 @@ func main() { os.Exit(1) } - ctx, _ := context.WithTimeout(context.Background(), 60*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + ghClient := github.NewClient(ctx, logger, token) result := &verification.Result{} From b18b1f23ed8f74ee0d92e88ba0903c0f7caecb3a Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Mon, 13 Jan 2025 12:26:55 -0300 Subject: [PATCH 13/23] implement checking by provider level instead of only namespacing Signed-off-by: Diogenes Fernandes --- .github/scripts/submit-provider-key.sh | 4 +-- src/cmd/verify-gpg-key/main.go | 13 ++++--- .../verify-gpg-key/verify-key-in-providers.go | 35 +++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/.github/scripts/submit-provider-key.sh b/.github/scripts/submit-provider-key.sh index b4623f11a2..9bea4e79ac 100755 --- a/.github/scripts/submit-provider-key.sh +++ b/.github/scripts/submit-provider-key.sh @@ -41,7 +41,7 @@ if [[ -n "${providername}" ]]; then fi set +e -go run ./cmd/verify-gpg-key -org "${namespace}" -username "${GH_USER}" -key-file=tmp.key -output=./output.json +go run ./cmd/verify-gpg-key -org "${namespace}" -provider-name "${providername}" -username "${GH_USER}" -key-file=tmp.key -output=./output.json verification=$? set -euo pipefail @@ -89,4 +89,4 @@ git push -u origin "${branch}" # Create pull request and update issue pr=$(gh pr create --title "${TITLE}" --body "${msg} ${keyfile/.././} 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 \ No newline at end of file +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 44e904966e..1fa5219e97 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -21,11 +21,16 @@ import ( ) func main() { - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) + opts := &slog.HandlerOptions{ + Level: slog.LevelError, + } + logger := slog.New(slog.NewJSONHandler(os.Stdout, opts)) 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") + providerName := flag.String("provider-name", "", "Key used to sign provider-scoped name") + outputFile := flag.String("output", "", "Path to write JSON result to") providerDataDir := flag.String("provider-data", "..", "Directory containing the provider data") flag.Parse() @@ -47,7 +52,7 @@ func main() { result := &verification.Result{} - s := VerifyKey(ctx, *providerDataDir, *keyFile, *orgName) + s := VerifyKey(ctx, *logger, *providerDataDir, *keyFile, *orgName, *providerName) result.Steps = append(result.Steps, s) s = VerifyGithubUser(ghClient, *username, *orgName) @@ -91,7 +96,7 @@ func VerifyGithubUser(client github.Client, username string, orgName string) *ve var gpgNameEmailRegex = regexp.MustCompile(`.*\<(.*)\>`) -func VerifyKey(ctx context.Context, providerDataDir string, location string, orgName string) *verification.Step { +func VerifyKey(ctx context.Context, logger slog.Logger, providerDataDir string, location string, orgName string, providerName string) *verification.Step { verifyStep := &verification.Step{ Name: "Validate GPG key", } @@ -181,7 +186,7 @@ func VerifyKey(ctx context.Context, providerDataDir string, location string, org return verifyStep } - providers, err := listProviders(ctx, dataAPI, orgName) + providers, err := getProviders(ctx, logger, dataAPI, orgName, providerName) if err != nil { verifyStep.AddError(fmt.Errorf("failed to list provider %s: %w", orgName, err)) diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index 24172394a1..bec998e92b 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "log/slog" "net/http" "time" @@ -23,8 +24,22 @@ func buildKeyVerifier(dataAPI metadata.API) (provider_verifier.KeyVerification, return keyVerification, nil } +func getProvider(ctx context.Context, dataAPI metadata.API, namespace string, providerName string) (provider.Addr, error) { + providerAddr := provider.Addr{ + Namespace: namespace, + Name: providerName, + } + canonicalAddr, err := dataAPI.GetProviderCanonicalAddr(ctx, providerAddr) + if err != nil { + return provider.Addr{}, err + } + + return canonicalAddr, nil +} + func listProviders(ctx context.Context, dataAPI metadata.API, namespace string) ([]provider.Addr, error) { providers, err := dataAPI.ListProvidersByNamespace(ctx, namespace, false) + if err != nil { return nil, err } @@ -35,3 +50,23 @@ func listProviders(ctx context.Context, dataAPI metadata.API, namespace string) return providers, nil } + +func getProviders(ctx context.Context, logger slog.Logger, dataAPI metadata.API, namespace string, providerName string) ([]provider.Addr, error) { + var err error + var providers []provider.Addr + var providerAddr provider.Addr + + if len(providerName) > 0 { + logger.Debug("Using provider", slog.String("provider", providerName)) + providerAddr, err = getProvider(ctx, dataAPI, namespace, providerName) + providers = append(providers, providerAddr) + } else { + logger.Debug("Using namespace", slog.String("namespace", namespace)) + providers, err = listProviders(ctx, dataAPI, namespace) + } + + if err != nil { + return nil, fmt.Errorf("failed to list providers: %w", err) + } + return providers, nil +} From 45ef284405e860e27f0ba8240893e3c1b4ab8cc5 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Mon, 13 Jan 2025 12:40:24 -0300 Subject: [PATCH 14/23] remove timeout from the httpclient Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/verify-key-in-providers.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index bec998e92b..651d039236 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -5,7 +5,6 @@ import ( "fmt" "log/slog" "net/http" - "time" "github.com/opentofu/libregistry/metadata" "github.com/opentofu/libregistry/provider_verifier" @@ -13,9 +12,7 @@ import ( ) func buildKeyVerifier(dataAPI metadata.API) (provider_verifier.KeyVerification, error) { - httpClient := http.Client{ - Timeout: 60 * time.Second, - } + httpClient := http.Client{} keyVerification, err := provider_verifier.New(httpClient, dataAPI) if err != nil { From e269cde208a1c8ad9ab03b9e17e88712709e7367 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Mon, 13 Jan 2025 13:52:00 -0300 Subject: [PATCH 15/23] check only 10 versions Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 1fa5219e97..2cbc91904a 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -204,7 +204,7 @@ func VerifyKey(ctx context.Context, logger slog.Logger, providerDataDir string, for _, provider := range providers { stepName := fmt.Sprintf("Key is used to sign the provider %s", provider) verifyStep.RunStep(stepName, func() error { - if err := keyVerification.VerifyKey(ctx, keyData, provider); err != nil { + if err := keyVerification.VerifyKey(ctx, keyData, provider, 10); err != nil { return err } return nil From 7f340d40d3ae43a80893a0cd642fe2861e38f1f3 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Sat, 25 Jan 2025 13:36:01 -0300 Subject: [PATCH 16/23] merge Signed-off-by: Diogenes Fernandes --- src/internal/provider/shasum.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/provider/shasum.go b/src/internal/provider/shasum.go index e453320b2f..9a97742541 100644 --- a/src/internal/provider/shasum.go +++ b/src/internal/provider/shasum.go @@ -7,7 +7,7 @@ import ( // GetSHASums will attempt to download the SHA checksums file from the given URL and return a // map of file names to SHA checksums. -func (p Provider) GetSHASums(shaFileDownloadUrl string) (map[string]string, error) { +func (p Provider) GetSHASums(shaFileDownloadUrl string, returnErr bool) (map[string]string, error) { contents, assetErr := p.Github.DownloadAssetContents(shaFileDownloadUrl) if assetErr != nil { return nil, fmt.Errorf("failed to download asset contents: %w", assetErr) From ed57b9c048e02f59ce7d3e3438bfdc47d472e1e2 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Sat, 25 Jan 2025 13:37:15 -0300 Subject: [PATCH 17/23] merge Signed-off-by: Diogenes Fernandes --- src/internal/provider/shasum.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/provider/shasum.go b/src/internal/provider/shasum.go index 9a97742541..e453320b2f 100644 --- a/src/internal/provider/shasum.go +++ b/src/internal/provider/shasum.go @@ -7,7 +7,7 @@ import ( // GetSHASums will attempt to download the SHA checksums file from the given URL and return a // map of file names to SHA checksums. -func (p Provider) GetSHASums(shaFileDownloadUrl string, returnErr bool) (map[string]string, error) { +func (p Provider) GetSHASums(shaFileDownloadUrl string) (map[string]string, error) { contents, assetErr := p.Github.DownloadAssetContents(shaFileDownloadUrl) if assetErr != nil { return nil, fmt.Errorf("failed to download asset contents: %w", assetErr) From 645ebe8681a8a02174e380db5028405abcb9cf34 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Sat, 25 Jan 2025 13:39:13 -0300 Subject: [PATCH 18/23] revert logger options Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 2cbc91904a..1ec5e71e9b 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -21,10 +21,7 @@ import ( ) func main() { - opts := &slog.HandlerOptions{ - Level: slog.LevelError, - } - logger := slog.New(slog.NewJSONHandler(os.Stdout, opts)) + logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) keyFile := flag.String("key-file", "", "Location of the GPG key to verify") username := flag.String("username", "", "Github username to verify the GPG key against") From 8933f467a503eb9012cd00bad63dd1a6acbadd9f Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Sat, 25 Jan 2025 15:09:06 -0300 Subject: [PATCH 19/23] removing parameter Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 2 +- src/cmd/verify-gpg-key/verify-key-in-providers.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 1ec5e71e9b..bc968842e7 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -201,7 +201,7 @@ func VerifyKey(ctx context.Context, logger slog.Logger, providerDataDir string, for _, provider := range providers { stepName := fmt.Sprintf("Key is used to sign the provider %s", provider) verifyStep.RunStep(stepName, func() error { - if err := keyVerification.VerifyKey(ctx, keyData, provider, 10); err != nil { + if err := keyVerification.VerifyKey(ctx, keyData, provider); err != nil { return err } return nil diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index 651d039236..ff17b7b8cb 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -7,14 +7,14 @@ import ( "net/http" "github.com/opentofu/libregistry/metadata" - "github.com/opentofu/libregistry/provider_verifier" + "github.com/opentofu/libregistry/provider_key_verifier" "github.com/opentofu/libregistry/types/provider" ) -func buildKeyVerifier(dataAPI metadata.API) (provider_verifier.KeyVerification, error) { - httpClient := http.Client{} +func buildKeyVerifier(dataAPI metadata.API) (provider_key_verifier.ProviderKeyVerifier, error) { + httpClient := &http.Client{} - keyVerification, err := provider_verifier.New(httpClient, dataAPI) + keyVerification, err := provider_key_verifier.New(httpClient, dataAPI) if err != nil { return nil, err } From b7f737222a0b3e882097fb8add36ebc8e9630c04 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Sat, 25 Jan 2025 15:11:25 -0300 Subject: [PATCH 20/23] moving provider data argument to the script Signed-off-by: Diogenes Fernandes --- .github/scripts/submit-provider-key.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/submit-provider-key.sh b/.github/scripts/submit-provider-key.sh index 9bea4e79ac..d6e9a90156 100755 --- a/.github/scripts/submit-provider-key.sh +++ b/.github/scripts/submit-provider-key.sh @@ -41,7 +41,7 @@ if [[ -n "${providername}" ]]; then fi set +e -go run ./cmd/verify-gpg-key -org "${namespace}" -provider-name "${providername}" -username "${GH_USER}" -key-file=tmp.key -output=./output.json +go run ./cmd/verify-gpg-key -org "${namespace}" -provider-data ".." -provider-name "${providername}" -username "${GH_USER}" -key-file=tmp.key -output=./output.json verification=$? set -euo pipefail From 7bc61df3afeef785b15fbf57602e29fb13bec88b Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Wed, 29 Jan 2025 09:36:57 -0300 Subject: [PATCH 21/23] Adding version to the verifyStep output Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 18 +++++++++++------- .../verify-gpg-key/verify-key-in-providers.go | 5 +---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index bc968842e7..46aa76a6b3 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -199,13 +199,17 @@ func VerifyKey(ctx context.Context, logger slog.Logger, providerDataDir string, } for _, provider := range providers { - stepName := fmt.Sprintf("Key is used to sign the provider %s", provider) - verifyStep.RunStep(stepName, func() error { - if err := keyVerification.VerifyKey(ctx, keyData, provider); err != nil { - return err - } - return nil - }) + versions, err := keyVerification.VerifyKey(ctx, keyData, provider) + if err != nil { + verifyStep.AddError(fmt.Errorf("failed to verify key: %w", err)) + verifyStep.Status = verification.StatusFailure + return verifyStep + } + + for _, version := range versions { + subName := fmt.Sprintf("Key is used to sign the provider %s v%s", provider, version) + verifyStep.AddStep(subName, verification.StatusSuccess) + } } emailStep.FailureToWarning() diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index ff17b7b8cb..f1357b0aec 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "log/slog" - "net/http" "github.com/opentofu/libregistry/metadata" "github.com/opentofu/libregistry/provider_key_verifier" @@ -12,9 +11,7 @@ import ( ) func buildKeyVerifier(dataAPI metadata.API) (provider_key_verifier.ProviderKeyVerifier, error) { - httpClient := &http.Client{} - - keyVerification, err := provider_key_verifier.New(httpClient, dataAPI) + keyVerification, err := provider_key_verifier.New(dataAPI) if err != nil { return nil, err } From 60ce3adae95f5dd004db1831d08ef9b28c5c5b7d Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Wed, 29 Jan 2025 11:23:34 -0300 Subject: [PATCH 22/23] updating method signature Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 4 ++-- src/cmd/verify-gpg-key/verify-key-in-providers.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 46aa76a6b3..3ff5e9f822 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -191,7 +191,7 @@ func VerifyKey(ctx context.Context, logger slog.Logger, providerDataDir string, return verifyStep } - keyVerification, err := buildKeyVerifier(dataAPI) + keyVerification, err := buildKeyVerifier(keyData, dataAPI) if err != nil { verifyStep.AddError(fmt.Errorf("failed to build key verifier: %w", err)) verifyStep.Status = verification.StatusFailure @@ -199,7 +199,7 @@ func VerifyKey(ctx context.Context, logger slog.Logger, providerDataDir string, } for _, provider := range providers { - versions, err := keyVerification.VerifyKey(ctx, keyData, provider) + versions, err := keyVerification.VerifyProvider(ctx, provider) if err != nil { verifyStep.AddError(fmt.Errorf("failed to verify key: %w", err)) verifyStep.Status = verification.StatusFailure diff --git a/src/cmd/verify-gpg-key/verify-key-in-providers.go b/src/cmd/verify-gpg-key/verify-key-in-providers.go index f1357b0aec..67a512298a 100644 --- a/src/cmd/verify-gpg-key/verify-key-in-providers.go +++ b/src/cmd/verify-gpg-key/verify-key-in-providers.go @@ -10,8 +10,8 @@ import ( "github.com/opentofu/libregistry/types/provider" ) -func buildKeyVerifier(dataAPI metadata.API) (provider_key_verifier.ProviderKeyVerifier, error) { - keyVerification, err := provider_key_verifier.New(dataAPI) +func buildKeyVerifier(keyData []byte, dataAPI metadata.API) (provider_key_verifier.ProviderKeyVerifier, error) { + keyVerification, err := provider_key_verifier.New(keyData, dataAPI) if err != nil { return nil, err } From 1953a2ef23fec68f5a437c6c95125c3bf8069ba2 Mon Sep 17 00:00:00 2001 From: Diogenes Fernandes Date: Wed, 29 Jan 2025 17:01:24 -0300 Subject: [PATCH 23/23] adjusting to new signature Signed-off-by: Diogenes Fernandes --- src/cmd/verify-gpg-key/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/verify-gpg-key/main.go b/src/cmd/verify-gpg-key/main.go index 3ff5e9f822..c5bd46337e 100644 --- a/src/cmd/verify-gpg-key/main.go +++ b/src/cmd/verify-gpg-key/main.go @@ -207,7 +207,7 @@ func VerifyKey(ctx context.Context, logger slog.Logger, providerDataDir string, } for _, version := range versions { - subName := fmt.Sprintf("Key is used to sign the provider %s v%s", provider, version) + subName := fmt.Sprintf("Key is used to sign the provider %s v%s", provider, version.Version) verifyStep.AddStep(subName, verification.StatusSuccess) } }