diff --git a/.gitignore b/.gitignore index 1a5bec0b6..e4845295f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,8 @@ .vscode/* /cli logid -!rekor-cli/ rekor-cli +!rekor-cli/ rekor-server !rekor-server/ /tests/rekor-server diff --git a/cmd/rekor-cli/get_e2e_test.go b/cmd/rekor-cli/get_e2e_test.go new file mode 100644 index 000000000..3929551a0 --- /dev/null +++ b/cmd/rekor-cli/get_e2e_test.go @@ -0,0 +1,35 @@ +// +// Copyright 2022 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build e2e + +package main + +import ( + "testing" + + "github.com/sigstore/rekor/pkg/util" +) + +func TestGetNonExistentIndex(t *testing.T) { + // this index is extremely likely to not exist + out := util.RunCliErr(t, "get", "--log-index", "100000000") + util.OutputContains(t, out, "404") +} +func TestGetNonExistentUUID(t *testing.T) { + // this uuid is extremely likely to not exist + out := util.RunCliErr(t, "get", "--uuid", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + util.OutputContains(t, out, "404") +} diff --git a/cmd/rekor-cli/loginfo_e2e_test.go b/cmd/rekor-cli/loginfo_e2e_test.go new file mode 100644 index 000000000..04989b110 --- /dev/null +++ b/cmd/rekor-cli/loginfo_e2e_test.go @@ -0,0 +1,38 @@ +// +// Copyright 2022 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build e2e + +package main + +import ( + "sync" + "testing" + + "github.com/sigstore/rekor/pkg/util" +) + +var ( + once sync.Once +) + +func TestLogInfo(t *testing.T) { + once.Do(func() { + util.SetupTestData(t) + }) + // TODO: figure out some way to check the length, add something, and make sure the length increments! + out := util.RunCli(t, "loginfo") + util.OutputContains(t, out, "Verification Successful!") +} diff --git a/cmd/rekor-cli/verify_e2e_test.go b/cmd/rekor-cli/verify_e2e_test.go new file mode 100644 index 000000000..61525122b --- /dev/null +++ b/cmd/rekor-cli/verify_e2e_test.go @@ -0,0 +1,30 @@ +// +// Copyright 2022 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build e2e + +package main + +import ( + "testing" + + "github.com/sigstore/rekor/pkg/util" +) + +func TestVerifyNonExistentIndex(t *testing.T) { + // this index is extremely likely to not exist + out := util.RunCliErr(t, "verify", "--log-index", "100000000") + util.OutputContains(t, out, "entry in log cannot be located") +} diff --git a/cmd/rekor-server/e2e_test.go b/cmd/rekor-server/e2e_test.go index 765fd8409..7fac3aae8 100644 --- a/cmd/rekor-server/e2e_test.go +++ b/cmd/rekor-server/e2e_test.go @@ -19,11 +19,11 @@ package main import ( "bufio" + "bytes" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" - "github.com/sigstore/rekor/pkg/sharding" "io/ioutil" "net/http" "os" @@ -33,6 +33,8 @@ import ( "strings" "testing" + "github.com/sigstore/rekor/pkg/sharding" + "github.com/sigstore/rekor/pkg/util" ) @@ -206,7 +208,6 @@ func TestGetCLI(t *testing.T) { } out = util.RunCli(t, "get", "--format=json", "--uuid", entryID.ReturnEntryIDString()) } - func getTreeID(t *testing.T) int64 { t.Helper() out := util.RunCli(t, "loginfo") @@ -221,3 +222,139 @@ func getTreeID(t *testing.T) int64 { func TestSearchNoEntriesRC1(t *testing.T) { util.RunCliErr(t, "search", "--email", "noone@internetz.com") } +func TestHostnameInSTH(t *testing.T) { + // get ID of container + rekorContainerID := strings.Trim(util.Run(t, "", "docker", "ps", "-q", "-f", "name=rekor-server"), "\n") + resp, err := http.Get(fmt.Sprintf("%s/api/v1/log", rekorServer())) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + if !strings.Contains(string(body), fmt.Sprintf(" %s ", rekorContainerID)) { + t.Errorf("logInfo does not contain the hostname (%v) of the rekor-server container: %v", rekorContainerID, string(body)) + } + if strings.Contains(string(body), "rekor.sigstore.dev") { + t.Errorf("logInfo contains rekor.sigstore.dev which should not be set by default") + } +} +func rekorServer() string { + if s := os.Getenv("REKOR_SERVER"); s != "" { + return s + } + return "http://localhost:3000" +} +func TestSearchSHA512(t *testing.T) { + sha512 := "c7694a1112ea1404a3c5852bdda04c2cc224b3567ef6ceb8204dbf2b382daacfc6837ee2ed9d5b82c90b880a3c7289778dbd5a8c2c08193459bcf7bd44581ed0" + var out string + out = util.RunCli(t, "upload", "--type", "intoto:0.0.2", + "--artifact", "tests/envelope.sha512", + "--pki-format", "x509", + "--public-key", "tests/test_sha512.pub") + util.OutputContains(t, out, "Created entry at") + uuid := util.GetUUIDFromTimestampOutput(t, out) + out = util.RunCli(t, "search", "--sha", fmt.Sprintf("sha512:%s", sha512)) + util.OutputContains(t, out, uuid) +} +func TestVerifyNonExistentUUID(t *testing.T) { + // this uuid is extremely likely to not exist + out := util.RunCliErr(t, "verify", "--uuid", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + util.OutputContains(t, out, "entry in log cannot be located") + + // Check response code + tid := getTreeID(t) + h := sha256.Sum256([]byte("123")) + entryID, err := sharding.CreateEntryIDFromParts(fmt.Sprintf("%x", tid), + hex.EncodeToString(h[:])) + if err != nil { + t.Fatal(err) + } + body := fmt.Sprintf("{\"entryUUIDs\":[\"%s\"]}", entryID.ReturnEntryIDString()) + resp, err := http.Post(fmt.Sprintf("%s/api/v1/log/entries/retrieve", rekorServer()), + "application/json", + bytes.NewReader([]byte(body))) + if err != nil { + t.Fatal(err) + } + c, _ := ioutil.ReadAll(resp.Body) + if resp.StatusCode != 200 { + t.Fatalf("expected status 200, got %d instead", resp.StatusCode) + } + if strings.TrimSpace(string(c)) != "[]" { + t.Fatalf("expected empty JSON array as response, got %s instead", string(c)) + } +} +func TestSearchQueryLimit(t *testing.T) { + tests := []struct { + description string + limit int + shouldErr bool + }{ + { + description: "request 6 entries", + limit: 6, + }, { + description: "request 10 entries", + limit: 10, + }, { + description: "request more than max", + limit: 12, + shouldErr: true, + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + b := bytes.NewReader(getBody(t, test.limit)) + resp, err := http.Post(fmt.Sprintf("%s/api/v1/log/entries/retrieve", rekorServer()), "application/json", b) + if err != nil { + t.Fatal(err) + } + c, _ := ioutil.ReadAll(resp.Body) + t.Log(string(c)) + if resp.StatusCode != 200 && !test.shouldErr { + t.Fatalf("expected test to pass but it failed") + } + if resp.StatusCode != 422 && test.shouldErr { + t.Fatal("expected test to fail but it passed") + } + if test.shouldErr && !strings.Contains(string(c), "logIndexes in body should have at most 10 items") { + t.Fatal("expected max limit error but didn't get it") + } + }) + } +} +func getBody(t *testing.T, limit int) []byte { + t.Helper() + s := fmt.Sprintf("{\"logIndexes\": [%d", limit) + for i := 1; i < limit; i++ { + s = fmt.Sprintf("%s, %d", s, i) + } + s += "]}" + return []byte(s) +} +func TestSearchQueryMalformedEntry(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + b, err := ioutil.ReadFile(filepath.Join(wd, "tests/rekor.json")) + if err != nil { + t.Fatal(err) + } + body := fmt.Sprintf("{\"entries\":[\"%s\"]}", b) + resp, err := http.Post(fmt.Sprintf("%s/api/v1/log/entries/retrieve", rekorServer()), + "application/json", + bytes.NewBuffer([]byte(body))) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != 400 { + t.Fatalf("expected status 400, got %d instead", resp.StatusCode) + } +} diff --git a/tests/envelope.sha512 b/cmd/rekor-server/tests/envelope.sha512 similarity index 100% rename from tests/envelope.sha512 rename to cmd/rekor-server/tests/envelope.sha512 diff --git a/cmd/rekor-server/tests/rekor.json b/cmd/rekor-server/tests/rekor.json new file mode 100644 index 000000000..793e5bb9b --- /dev/null +++ b/cmd/rekor-server/tests/rekor.json @@ -0,0 +1,20 @@ +{ + "kind": "rekord", + "apiVersion": "0.0.1", + "spec": { + "signature": { + "format": "pgp", + "content": "iQHKBAABCAA0FiEEcgCUXG78adj6hGUJJrfBoJ04pHoFAl+86RwWHGxoaW5kc0Bwcm90b25tYWlsLmNvbQAKCRAmt8GgnTikejcHC/9yyGEPh2D+MnNR8I8w0sfWChc6pGAQoS6qk/sfC/9GvF4OC7RIy6OwLr/lxyEZbOP2ngYjh/s5KjKxhZyApwwg13LmcbazGnXc3E76J55LoTfwoRa9fupH/M6HI56VFKwnu+AbMNW1s+DM47r7i5nIN6IX9kMpDe3B9XTUULff/yNUv0XtXU+VAf8ndF1w117YVWxf8TnU/HWvX74URQPN+syuyqK/NO1H1KhBVTzcIYd5H6kJu300jgkDypyyqQpd/pJYVwfeY8fCOaeCpfIPjKQ/4enCsAeBgKsAwfIbor8WiE86KoANYqROaW7uqiN+VPadbWVeN6bMpRIdEq8+NKQGlepSCRqbkVg4VKGOPgB3h5WbY9U1O1FVDnXyt7kWdEPEZjBX+V4DawshvNe5LIyqH5hJ1QNAFd0UStqKQt8EUZ/gAtQiXSGbxM1ACoYL9HblKW5b+kj/onKghekFoCoAfhMwRRqR5g/TS/Pc2/ztwYTIuhpQQfMXziTm64g=", + "publicKey": { + "content":"LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgptUUdOQkYrY0lNMEJEQUNhOEc3UkQydjNtaXdNdHhWYVppM0pCVnVlVkFxSEtDNGVLb01TNUhNQ1JvK0haVlJBCjcwWG1zVHBYMVoxZ1pRdXVDMEdEWTI2aEJoZWpBcTNoeDJydjYvOHE5MEJ2V0dIOXRWZUdwTDFzYUltNTJnRVIKWHlWZ2d6NWtBQzBTNnZNbjdkcjJldEJrV1dQK09qMDVTMDJZWkJUWWd4cE9ieWVjVVNjcUtOVGpzbFpRQkgyZApTSHVrM28yWjdoTTQ5VTBsN3piV3c0b0lUK2xBUmNzYWpRVHdXamxpYVBEL0hSalQyblJPaEloaXRlZC93Z3l6CnlkSXE1ZTZzMThWTGNUNzVxV25yWlhOUFdGd2YyNVJYWTN1dGtXK0dXNW5RZU44MFEya1JFZ2t4RnM1QWQ1V1oKdkU3dDgvaHg1em1zbFo0dGZGNHNpM1FaZUlRQmFjWWJ3eE1QU0RmOW9GR3hkR0ZUODg5d0pMR2dXbXIxVGtQTQpjTjA2d3hBUkd0eE4wejYxRkpUaWpMV1JialczdW5JOWhjUWNVbE4vUSsxNm90SHBlS1ZnNG9XMDBDcnZXT0Q2CnFrTGNNRDQ5eVVEOGZTR0IrUkVuaUJhODlDOWtRVTRTS2Rnc0xML1ErSksrU3k5S21JRHJtMWE0RGZQMXBzZmUKTGphcnpzVlpmS1VIZndjQUVRRUFBYlFpVEhWclpTQklhVzVrY3lBOGJHaHBibVJ6UUhCeWIzUnZibTFoYVd3dQpZMjl0UG9rQjFBUVRBUWdBUGhZaEJISUFsRnh1L0duWStvUmxDU2Ezd2FDZE9LUjZCUUpmbkNETkFoc0RCUWtECndtY0FCUXNKQ0FjQ0JoVUtDUWdMQWdRV0FnTUJBaDRCQWhlQUFBb0pFQ2Ezd2FDZE9LUjZaMWtMLzFJSzB2ZGUKWlg1cjVTZWJOeFRJTlNBQXZZa3JLUnlKNWY3bE9NOWdMR0l1YzJGb05VbmpWUVQwcklHOTAxOWg0OHBDeTkxZgpYakREUk1ZOWd6RldXQ2dHblhoMWhXSTNNN0JKRjZZRTZ1NkRYR3N2dVVwR3JOZVpBRzZra2F6QXVBbm5WMGtDCjA4em9SckFaQ3ZscGFacnlkOGl0YityVitRS3A3QXcybEFJSDFlNmR3TTRSTEZqdmZrOExKWHhqSkFvUG13NmwKTHcxOGM3b1c2UkxPOVFYUThlTTZyMnZISHBtMFR1ZHZaeWFmTnVDMzJHRGxNWTR1MFYxRGI4THN5bVBzQWh1QQoySno0L0tQcTZ1S3dJdG1WSzRwbmRmRUR1NkQxVG9vRFlYaXB0WWFmZHZVMzNwVVF4d0hvZlRUZkU1elp3MlBlCmxIM25aZHNnSFhHUHhKTExNcU9wVzRDL2NNNlpRVmdZU3RWcjBudlU2NitRalF2c2tVWlIwNmRkRXpuQnBHSnMKdHBtajlBZS9HUlk4RU5uTjkvMkdmRXVydHozZEtOVVpvak15MTUzamNHMFUxenpoMTE1V0o3dDh3SEJ1NFM0cAowZ0UrUkFxeXRBY0laRGQyTlNOcno4VnI5RkU5eCtmYXQ5RVJsYm5kQUJFNWlWOHNLMCtGYW5Xd2dia0JqUVJmCm5DRE5BUXdBdEJvdGhmY1J6cjN4cjNQOXA3UUNNd0t1aW9udk1DbThXZ3dOUzRDcGhxbzVOT3IyaU1qa0xQMEoKb21nSkxWWDVOK2Jydjh5NEg4cllQd0tCMTZvL2hBOEliR2JwWXltM0ZjeWtUd2NiV2J0UFRMRXRkQ1VQTFlURApOQzVMR0pwZzNlODZZZlF0QU42L01uWnlZT21sRHgyV0d0dExkbXNBU0dWdXg2QVZKcUl2K3gwNlVLSkVtSzN0CmpsRVZLeWcxMlJFenllNUlUNnFFU0dwT3pvMllsV1VxSVR3L0FhUFEyWnhVYXh2WUZvVU9jd2djZG5Ia2dzaEkKT245aC9OSFVtUDMyV1F2cWtRTXVVYVBJTlJzQzgzS3ZUREdseWZTSFZGek1hNGhETWhFY1h6NGFjaW5kNVdUZQp6eUxnWmhPYjdjTmVDeDR4Y3J0UEI2VTdCUi9GVkx6TEJsQXp1emppRWhZd0pvM0FPTXFGb1I1bUFxaGx1dE5PCnNzeW9mYnFUZ0diU0xkamJYUC9hRXRnejJNVjluL29jMVNCOEhlWk8vMTdKeWduenJ1SUt5Ky9sT1dPenQralYKVkZwVnloMXVlOGxGN3ltS1I0dHNsK2lJVmJxblB2cE1oTE9JQnFYRm4yZ01Da0dvSkx5N09IbzJXQUVKR2x0MwpTd3BicmpqMUFCRUJBQUdKQWJ3RUdBRUlBQ1lXSVFSeUFKUmNidnhwMlBxRVpRa210OEdnblRpa2VnVUNYNXdnCnpRSWJEQVVKQThKbkFBQUtDUkFtdDhHZ25UaWtlaW5pREFDRUFma1pxLzRScDJhTkE0ZGJvSjdVRlhET2FSa1YKOU1Lb0VaRnFUTU5vdkRMNXhoTWxnbFBQdS9sK2RoVGd4ZGVKOUVWSG9lenRiODk2VS9wT3VCUnNuOVZ0VzRZLwpqZWlXN0V5TlhBZC9PcnZuRmJ4KzdpWExxdXBaSkpGVGkvajlSaFZZTnNtbDdzZWJUUGVCbkdEQTkxcWJDNHhICnBRVkRDdWp4NjlWeE81RTFMU29oQ00rTy81dkxCbThpMW8vbmJGbWJ5N1ZDeUtlUkRmaHRmOW5DODRxc0U5R3EKVTcvTFNpazliZnhNV2JwcTh5a250bVMzYTBzemM0YlZGcGV6QnBtTmIwQVZjQitUbTlnV21FemhpTHM2RktBTgpJbnFOdVh1Qkw5UENhYzcrbVUrYzJtQmdHT1JHZDFkWk8zUkM4OXpGM3hCQlluQ09lNWNBTUZsYzFYR3NsbHNJCmR6ZHJkWHZiTkJ6L2o3MXB1TjhvRlltL1hiVmNpZU8wVGZRaURjVHQ4S2lpUjlUQUQ5L1A1OTNSTWxMT0dTOHAKaHZKYmlGb1pmWEhjbHNaRkhtOERRUWE5NElad1RCOG00Z0JWME0yWFN2ZEhvMzBsc3FqdFphWmlTclJoNHJzaApuMTRwYkFhVGRhS0VQY3Z0dWZiVXVXMElqWWQya3BJVC90Zz0KPU9naHIKLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLQo=" + } + }, + "data": { + "url": "https://raw.githubusercontent.com/sigstore/rekor/main/tests/test_file.txt", + "hash": { + "algorithm": "sha256", + "value": "45c7b11fcbf07dec1694adecd8c5b85770a12a6c8dfdcf2580a2db0c47c31779" + } + } + } +} diff --git a/tests/test_sha512.pub b/cmd/rekor-server/tests/test_sha512.pub similarity index 100% rename from tests/test_sha512.pub rename to cmd/rekor-server/tests/test_sha512.pub diff --git a/pkg/pki/pgp/pgp.go b/pkg/pki/pgp/pgp.go index f966fd078..79ae5f6b1 100644 --- a/pkg/pki/pgp/pgp.go +++ b/pkg/pki/pgp/pgp.go @@ -34,7 +34,7 @@ import ( sigsig "github.com/sigstore/sigstore/pkg/signature" ) -// Signature Signature that follows the PGP standard; supports both armored & binary detached signatures +// Signature that follows the PGP standard; supports both armored & binary detached signatures type Signature struct { isArmored bool signature []byte diff --git a/pkg/util/util.go b/pkg/util/util.go index 1661e382e..fa0e82336 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -14,7 +14,6 @@ // limitations under the License. //go:build e2e -// +build e2e package util @@ -22,24 +21,25 @@ import ( "bytes" "encoding/base64" "fmt" - "golang.org/x/crypto/openpgp" "io/ioutil" "math/rand" "os" "os/exec" "path" + "path/filepath" "strings" "testing" "time" + "golang.org/x/crypto/openpgp" + "github.com/sigstore/rekor/pkg/generated/models" ) var ( - cli = "rekor-cli" - server = "rekor-server" - nodeDataDir = "node" - keys openpgp.EntityList + cli = "rekor-cli" + server = "rekor-server" + keys openpgp.EntityList ) type GetOut struct { @@ -308,24 +308,6 @@ func RunCli(t *testing.T, arg ...string) string { return Run(t, "", cli, arg...) } -func RunCliStdout(t *testing.T, arg ...string) string { - t.Helper() - arg = append([]string{coverageFlag()}, arg...) - arg = append(arg, rekorServerFlag()) - c := exec.Command(cli, arg...) - - if os.Getenv("REKORTMPDIR") != "" { - // ensure that we use a clean state.json file for each Run - c.Env = append(c.Env, "HOME="+os.Getenv("REKORTMPDIR")) - } - b, err := c.Output() - if err != nil { - t.Log(string(b)) - t.Fatal(err) - } - return stripCoverageOutput(string(b)) -} - func RunCliErr(t *testing.T, arg ...string) string { t.Helper() arg = append([]string{coverageFlag()}, arg...) @@ -362,14 +344,6 @@ func stripCoverageOutput(out string) string { return strings.Split(strings.Split(out, "PASS")[0], "FAIL")[0] } -func readFile(t *testing.T, p string) string { - b, err := ioutil.ReadFile(p) - if err != nil { - t.Fatal(err) - } - return strings.TrimSpace(string(b)) -} - // RandomSuffix returns a random string of the given length. func RandomSuffix(n int) string { const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -459,3 +433,29 @@ func CreatedPGPSignedArtifact(t *testing.T, artifactPath, sigPath string) { t.Fatal(err) } } + +func GetUUIDFromTimestampOutput(t *testing.T, out string) string { + t.Helper() + // Output looks like "Created entry at index X, available at $URL/UUID", so grab the UUID: + urlTokens := strings.Split(strings.TrimSpace(out), "\n") + return GetUUIDFromUploadOutput(t, urlTokens[len(urlTokens)-1]) +} + +// SetupTestData is a helper function to setups the test data +func SetupTestData(t *testing.T) { + // create a temp directory + artifactPath := filepath.Join(t.TempDir(), "artifact") + // create a temp file + sigPath := filepath.Join(t.TempDir(), "signature.asc") + CreatedPGPSignedArtifact(t, artifactPath, sigPath) + + // Write the public key to a file + pubPath := filepath.Join(t.TempDir(), "pubKey.asc") + if err := ioutil.WriteFile(pubPath, []byte(PubKey), 0644); err != nil { //nolint:gosec + t.Fatal(err) + } + + // Now upload to rekor! + out := RunCli(t, "upload", "--artifact", artifactPath, "--signature", sigPath, "--public-key", pubPath) + OutputContains(t, out, "Created entry at") +} diff --git a/tests/e2e_test.go b/tests/e2e_test.go index ac1330e8b..6ec8f7868 100644 --- a/tests/e2e_test.go +++ b/tests/e2e_test.go @@ -78,13 +78,6 @@ func getLogIndexFromUploadOutput(t *testing.T, out string) int { return i } -func getUUIDFromTimestampOutput(t *testing.T, out string) string { - t.Helper() - // Output looks like "Created entry at index X, available at $URL/UUID", so grab the UUID: - urlTokens := strings.Split(strings.TrimSpace(out), "\n") - return getUUIDFromUploadOutput(t, urlTokens[len(urlTokens)-1]) -} - func TestEnvVariableValidation(t *testing.T) { os.Setenv("REKOR_FORMAT", "bogus") defer os.Unsetenv("REKOR_FORMAT") @@ -118,12 +111,6 @@ func TestDuplicates(t *testing.T) { outputContains(t, out, "Created entry at") } -func TestLogInfo(t *testing.T) { - // TODO: figure out some way to check the length, add something, and make sure the length increments! - out := runCli(t, "loginfo") - outputContains(t, out, "Verification Successful!") -} - type getOut struct { Attestation string AttestationType string @@ -191,19 +178,7 @@ func TestGetCLI(t *testing.T) { if err != nil { t.Error(err) } - out = runCli(t, "get", "--format=json", "--uuid", entryID.ReturnEntryIDString()) -} -func TestSearchSHA512(t *testing.T) { - sha512 := "c7694a1112ea1404a3c5852bdda04c2cc224b3567ef6ceb8204dbf2b382daacfc6837ee2ed9d5b82c90b880a3c7289778dbd5a8c2c08193459bcf7bd44581ed0" - var out string - out = runCli(t, "upload", "--type", "intoto:0.0.2", - "--artifact", "envelope.sha512", - "--pki-format", "x509", - "--public-key", "test_sha512.pub") - outputContains(t, out, "Created entry at") - uuid := getUUIDFromTimestampOutput(t, out) - out = runCli(t, "search", "--sha", fmt.Sprintf("sha512:%s", sha512)) - outputContains(t, out, uuid) + runCli(t, "get", "--format=json", "--uuid", entryID.ReturnEntryIDString()) } func TestWatch(t *testing.T) { @@ -312,53 +287,6 @@ func TestSignedEntryTimestamp(t *testing.T) { } } -func TestGetNonExistentIndex(t *testing.T) { - // this index is extremely likely to not exist - out := runCliErr(t, "get", "--log-index", "100000000") - outputContains(t, out, "404") -} - -func TestVerifyNonExistentIndex(t *testing.T) { - // this index is extremely likely to not exist - out := runCliErr(t, "verify", "--log-index", "100000000") - outputContains(t, out, "entry in log cannot be located") -} - -func TestGetNonExistentUUID(t *testing.T) { - // this uuid is extremely likely to not exist - out := runCliErr(t, "get", "--uuid", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - outputContains(t, out, "404") -} - -func TestVerifyNonExistentUUID(t *testing.T) { - // this uuid is extremely likely to not exist - out := runCliErr(t, "verify", "--uuid", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - outputContains(t, out, "entry in log cannot be located") - - // Check response code - tid := getTreeID(t) - h := sha256.Sum256([]byte("123")) - entryID, err := sharding.CreateEntryIDFromParts(fmt.Sprintf("%x", tid), - hex.EncodeToString(h[:])) - if err != nil { - t.Fatal(err) - } - body := fmt.Sprintf("{\"entryUUIDs\":[\"%s\"]}", entryID.ReturnEntryIDString()) - resp, err := http.Post(fmt.Sprintf("%s/api/v1/log/entries/retrieve", rekorServer()), - "application/json", - bytes.NewReader([]byte(body))) - if err != nil { - t.Fatal(err) - } - c, _ := ioutil.ReadAll(resp.Body) - if resp.StatusCode != 200 { - t.Fatalf("expected status 200, got %d instead", resp.StatusCode) - } - if strings.TrimSpace(string(c)) != "[]" { - t.Fatalf("expected empty JSON array as response, got %s instead", string(c)) - } -} - func TestEntryUpload(t *testing.T) { artifactPath := filepath.Join(t.TempDir(), "artifact") sigPath := filepath.Join(t.TempDir(), "signature.asc") @@ -468,90 +396,6 @@ func TestInclusionProofRace(t *testing.T) { } } -func TestHostnameInSTH(t *testing.T) { - // get ID of container - rekorContainerID := strings.Trim(run(t, "", "docker", "ps", "-q", "-f", "name=rekor-server"), "\n") - resp, err := http.Get(fmt.Sprintf("%s/api/v1/log", rekorServer())) - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - - if !strings.Contains(string(body), fmt.Sprintf(" %s ", rekorContainerID)) { - t.Errorf("logInfo does not contain the hostname (%v) of the rekor-server container: %v", rekorContainerID, string(body)) - } - if strings.Contains(string(body), "rekor.sigstore.dev") { - t.Errorf("logInfo contains rekor.sigstore.dev which should not be set by default") - } -} - -func TestSearchQueryLimit(t *testing.T) { - tests := []struct { - description string - limit int - shouldErr bool - }{ - { - description: "request 6 entries", - limit: 6, - }, { - description: "request 10 entries", - limit: 10, - }, { - description: "request more than max", - limit: 12, - shouldErr: true, - }, - } - - for _, test := range tests { - t.Run(test.description, func(t *testing.T) { - b := bytes.NewReader(getBody(t, test.limit)) - resp, err := http.Post(fmt.Sprintf("%s/api/v1/log/entries/retrieve", rekorServer()), "application/json", b) - if err != nil { - t.Fatal(err) - } - c, _ := ioutil.ReadAll(resp.Body) - t.Log(string(c)) - if resp.StatusCode != 200 && !test.shouldErr { - t.Fatalf("expected test to pass but it failed") - } - if resp.StatusCode != 422 && test.shouldErr { - t.Fatal("expected test to fail but it passed") - } - if test.shouldErr && !strings.Contains(string(c), "logIndexes in body should have at most 10 items") { - t.Fatal("expected max limit error but didn't get it") - } - }) - } -} - -func TestSearchQueryMalformedEntry(t *testing.T) { - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - b, err := ioutil.ReadFile(filepath.Join(wd, "rekor.json")) - if err != nil { - t.Fatal(err) - } - body := fmt.Sprintf("{\"entries\":[\"%s\"]}", b) - resp, err := http.Post(fmt.Sprintf("%s/api/v1/log/entries/retrieve", rekorServer()), - "application/json", - bytes.NewBuffer([]byte(body))) - if err != nil { - t.Fatal(err) - } - if resp.StatusCode != 400 { - t.Fatalf("expected status 400, got %d instead", resp.StatusCode) - } -} - func TestSearchQueryNonExistentEntry(t *testing.T) { // Nonexistent but well-formed entry results in 404 not found. wd, err := os.Getwd() @@ -579,16 +423,6 @@ func TestSearchQueryNonExistentEntry(t *testing.T) { } } -func getBody(t *testing.T, limit int) []byte { - t.Helper() - s := fmt.Sprintf("{\"logIndexes\": [%d", limit) - for i := 1; i < limit; i++ { - s = fmt.Sprintf("%s, %d", s, i) - } - s += "]}" - return []byte(s) -} - func getTreeID(t *testing.T) int64 { out := runCli(t, "loginfo") tidStr := strings.TrimSpace(strings.Split(out, "TreeID: ")[1])