diff --git a/registry-automation/pkg/validate/connector_packaging.go b/registry-automation/pkg/validate/connector_packaging.go index 988d1335..862c589d 100644 --- a/registry-automation/pkg/validate/connector_packaging.go +++ b/registry-automation/pkg/validate/connector_packaging.go @@ -1,7 +1,11 @@ package validate import ( + "crypto/sha256" "fmt" + "hash" + "io" + "net/http" "strings" "github.com/hasura/ndc-hub/registry-automation/pkg/ndchub" @@ -10,12 +14,68 @@ import ( func ConnectorPackaging(cp *ndchub.ConnectorPackaging) error { // validate version field - if !strings.HasPrefix(cp.Version, "v") { - return fmt.Errorf("version must start with 'v': but got %s", cp.Version) + if err := checkVersion(cp.Version); err != nil { + return err } - if !semver.IsValid(cp.Version) { - return fmt.Errorf("invalid semantic version: %s", cp.Version) + + // validate uri and checksum fields + if err := checkConnectorTarball(cp); err != nil { + return err + } + + return nil +} + +func checkVersion(version string) error { + if !strings.HasPrefix(version, "v") { + return fmt.Errorf("version must start with 'v': but got %s", version) + } + if !semver.IsValid(version) { + return fmt.Errorf("invalid semantic version: %s", version) + } + return nil +} + +func checkConnectorTarball(cp *ndchub.ConnectorPackaging) error { + var checksumFuncs map[string]hash.Hash = map[string]hash.Hash{ + "sha256": sha256.New(), + } + + fileContents, err := downloadFile(cp.URI) + if err != nil { + return err + } + + hashFunc, ok := checksumFuncs[cp.Checksum.Type] + if !ok { + return fmt.Errorf("unsupported checksum type: %s", cp.Checksum.Type) + } + + _, err = io.Copy(hashFunc, fileContents) + if err != nil { + return err + } + defer fileContents.Close() + + checksum := fmt.Sprintf("%x", hashFunc.Sum(nil)) + if checksum != cp.Checksum.Value { + return fmt.Errorf("checksum mismatch: checksum of downloaded file: %s, but checksum in connector-packaging.json: %s", checksum, cp.Checksum.Value) } return nil } + +func downloadFile(uri string) (io.ReadCloser, error) { + var err error + + resp, err := http.Get(uri) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("error downloading: status code %d", resp.StatusCode) + } + + return resp.Body, nil +} diff --git a/registry-automation/pkg/validate/connector_packaging_test.go b/registry-automation/pkg/validate/connector_packaging_test.go index 143a8b05..07afd7ec 100644 --- a/registry-automation/pkg/validate/connector_packaging_test.go +++ b/registry-automation/pkg/validate/connector_packaging_test.go @@ -1,6 +1,10 @@ package validate import ( + "crypto/sha256" + "fmt" + "net/http" + "net/http/httptest" "testing" "github.com/hasura/ndc-hub/registry-automation/pkg/ndchub" @@ -37,3 +41,70 @@ func TestConnectorPackaging(t *testing.T) { }) } } + +func TestCheckConnectorTarball(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("dummy content")) + })) + defer server.Close() + + tests := []struct { + name string + cp *ndchub.ConnectorPackaging + expectError bool + }{ + { + name: "Valid tarball", + cp: &ndchub.ConnectorPackaging{ + URI: server.URL, + Checksum: ndchub.Checksum{ + Type: "sha256", + Value: fmt.Sprintf("%x", sha256.Sum256([]byte("dummy content"))), + }, + }, + expectError: false, + }, + { + name: "Invalid checksum", + cp: &ndchub.ConnectorPackaging{ + URI: server.URL, + Checksum: ndchub.Checksum{ + Type: "sha256", + Value: "invalid_checksum", + }, + }, + expectError: true, + }, + { + name: "Unsupported checksum type", + cp: &ndchub.ConnectorPackaging{ + URI: server.URL, + Checksum: ndchub.Checksum{ + Type: "md5", + Value: "some_value", + }, + }, + expectError: true, + }, + { + name: "Invalid URI", + cp: &ndchub.ConnectorPackaging{ + URI: "invalid_url", + Checksum: ndchub.Checksum{ + Type: "sha256", + Value: "some_value", + }, + }, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := checkConnectorTarball(tt.cp) + if (err != nil) != tt.expectError { + t.Errorf("checkConnectorTarball() error = %v, expectError %v", err, tt.expectError) + } + }) + } +} diff --git a/registry/hasura/duckduckapi/releases/v0.4.0/connector-packaging.json b/registry/hasura/duckduckapi/releases/v0.4.0/connector-packaging.json index 7352ab0f..f049429a 100644 --- a/registry/hasura/duckduckapi/releases/v0.4.0/connector-packaging.json +++ b/registry/hasura/duckduckapi/releases/v0.4.0/connector-packaging.json @@ -1,6 +1,6 @@ { "version": "v0.4.0", - "uri": "https://github.com/hasura/ndc-duckduckapi/releases/download/v0.3.1/connector-definition.tgz", + "uri": "https://github.com/hasura/ndc-duckduckapi/releases/download/v0.4.0/connector-definition.tgz", "checksum": { "type": "sha256", "value": "d120f8816b590a9e537d6f0a6fce2b2e6e15dcbbf9f9e45338993df55b74e0ca" diff --git a/registry/hasura/mongodb/releases/v1.5.0/connector-packaging.json b/registry/hasura/mongodb/releases/v1.5.0/connector-packaging.json index ccaf835a..ecb0fb61 100644 --- a/registry/hasura/mongodb/releases/v1.5.0/connector-packaging.json +++ b/registry/hasura/mongodb/releases/v1.5.0/connector-packaging.json @@ -3,10 +3,9 @@ "uri": "https://github.com/hasura/ndc-mongodb/releases/download/v1.5.0/connector-definition.tgz", "checksum": { "type": "sha256", - "value": "7821513fcdc1a2689a546f20a18cdc2cce9fe218dc8506adc86eb6a2a3b256a9" + "value": "b14a335e6e5c65f5c109e24b09ecf03ea036c13f4bd3c9b79de3fa76290e96c9" }, "source": { "hash": "b95da1815a9b686e517aa78f677752e36e0bfda0" } } -