mirror of https://github.com/docker/docs.git
142 lines
5.1 KiB
Go
142 lines
5.1 KiB
Go
package client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/notary/keystoremanager"
|
|
"github.com/endophage/gotuf/data"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var passphraseRetriever = func(string, string, bool, int) (string, bool, error) { return "passphrase", false, nil }
|
|
|
|
// TestValidateRoot through the process of initializing a repository and makes
|
|
// sure the repository looks correct on disk.
|
|
// We test this with both an RSA and ECDSA root key
|
|
func TestValidateRoot(t *testing.T) {
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
validateRootSuccessfully(t, data.ECDSAKey)
|
|
if !testing.Short() {
|
|
validateRootSuccessfully(t, data.RSAKey)
|
|
}
|
|
}
|
|
|
|
func validateRootSuccessfully(t *testing.T, rootType data.KeyAlgorithm) {
|
|
// Temporary directory where test files will be created
|
|
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
|
defer os.RemoveAll(tempBaseDir)
|
|
|
|
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
|
|
|
gun := "docker.com/notary"
|
|
|
|
ts, mux := createTestServer(t)
|
|
defer ts.Close()
|
|
|
|
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever)
|
|
assert.NoError(t, err, "error creating repository: %s", err)
|
|
|
|
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType.String())
|
|
assert.NoError(t, err, "error generating root key: %s", err)
|
|
|
|
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
|
|
assert.NoError(t, err, "error retrieving root key: %s", err)
|
|
|
|
err = repo.Initialize(rootCryptoService)
|
|
assert.NoError(t, err, "error creating repository: %s", err)
|
|
|
|
// tests need to manually boostrap timestamp as client doesn't generate it
|
|
err = repo.tufRepo.InitTimestamp()
|
|
assert.NoError(t, err, "error creating repository: %s", err)
|
|
|
|
// Initialize is supposed to have created new certificate for this repository
|
|
// Lets check for it and store it for later use
|
|
allCerts := repo.KeyStoreManager.TrustedCertificateStore().GetCertificates()
|
|
assert.Len(t, allCerts, 1)
|
|
|
|
// Now test ListTargets. In preparation, we need to expose some signed
|
|
// metadata files on the internal HTTP server.
|
|
var tempKey data.TUFKey
|
|
json.Unmarshal([]byte(timestampECDSAKeyJSON), &tempKey)
|
|
|
|
repo.KeyStoreManager.KeyStore.AddKey(filepath.Join(filepath.FromSlash(gun), tempKey.ID()), "root", &tempKey)
|
|
|
|
// Because ListTargets will clear this
|
|
savedTUFRepo := repo.tufRepo
|
|
|
|
rootJSONFile := filepath.Join(tempBaseDir, "tuf", filepath.FromSlash(gun), "metadata", "root.json")
|
|
rootFileBytes, err := ioutil.ReadFile(rootJSONFile)
|
|
|
|
signedTargets, err := savedTUFRepo.SignTargets("targets", data.DefaultExpires("targets"), nil)
|
|
assert.NoError(t, err)
|
|
|
|
signedSnapshot, err := savedTUFRepo.SignSnapshot(data.DefaultExpires("snapshot"), nil)
|
|
assert.NoError(t, err)
|
|
|
|
signedTimestamp, err := savedTUFRepo.SignTimestamp(data.DefaultExpires("timestamp"), nil)
|
|
assert.NoError(t, err)
|
|
|
|
mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/root.json", func(w http.ResponseWriter, r *http.Request) {
|
|
assert.NoError(t, err)
|
|
fmt.Fprint(w, string(rootFileBytes))
|
|
})
|
|
|
|
mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/timestamp.json", func(w http.ResponseWriter, r *http.Request) {
|
|
timestampJSON, _ := json.Marshal(signedTimestamp)
|
|
fmt.Fprint(w, string(timestampJSON))
|
|
})
|
|
|
|
mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/snapshot.json", func(w http.ResponseWriter, r *http.Request) {
|
|
snapshotJSON, _ := json.Marshal(signedSnapshot)
|
|
fmt.Fprint(w, string(snapshotJSON))
|
|
})
|
|
|
|
mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/targets.json", func(w http.ResponseWriter, r *http.Request) {
|
|
targetsJSON, _ := json.Marshal(signedTargets)
|
|
fmt.Fprint(w, string(targetsJSON))
|
|
})
|
|
|
|
_, err = repo.ListTargets()
|
|
assert.NoError(t, err)
|
|
|
|
//
|
|
// Test TOFUS logic. We remove all certs and expect a new one to be added after ListTargets
|
|
//
|
|
err = repo.KeyStoreManager.TrustedCertificateStore().RemoveAll()
|
|
assert.NoError(t, err)
|
|
assert.Len(t, repo.KeyStoreManager.TrustedCertificateStore().GetCertificates(), 0)
|
|
|
|
// This list targets is expected to succeed and the certificate store to have the new certificate
|
|
_, err = repo.ListTargets()
|
|
assert.NoError(t, err)
|
|
assert.Len(t, repo.KeyStoreManager.TrustedCertificateStore().GetCertificates(), 1)
|
|
|
|
//
|
|
// Test certificate mismatch logic. We remove all certs, add a different cert to the
|
|
// same CN, and expect ValidateRoot to fail
|
|
//
|
|
|
|
// First, remove all certs
|
|
err = repo.KeyStoreManager.TrustedCertificateStore().RemoveAll()
|
|
assert.NoError(t, err)
|
|
assert.Len(t, repo.KeyStoreManager.TrustedCertificateStore().GetCertificates(), 0)
|
|
|
|
// Add a previously generated certificate with CN=docker.com/notary
|
|
err = repo.KeyStoreManager.TrustedCertificateStore().AddCertFromFile("../fixtures/self-signed_docker.com-notary.crt")
|
|
assert.NoError(t, err)
|
|
|
|
// This list targets is expected to fail, since there already exists a certificate
|
|
// in the store for the dnsName docker.com/notary, so TOFUS doesn't apply
|
|
_, err = repo.ListTargets()
|
|
if assert.Error(t, err, "An error was expected") {
|
|
assert.Equal(t, err, &keystoremanager.ErrValidationFail{Reason: "failed to validate data with current trusted certificates"})
|
|
}
|
|
}
|