Skip to content

Commit

Permalink
Merge branch 'master' into flattenKS
Browse files Browse the repository at this point in the history
  • Loading branch information
avaid96 authored Jul 26, 2016
2 parents a9668ac + c4f5da0 commit 79dbeb3
Show file tree
Hide file tree
Showing 18 changed files with 136 additions and 585 deletions.
19 changes: 19 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2325,6 +2325,25 @@ func TestPublishTargetsDelegationSuccessNeedsToDownloadRoles(t *testing.T) {
// delegation parents all get signed
ownerRec.requireAsked(t, []string{data.CanonicalTargetsRole, "targets/a"})

// assert both delegation roles appear to the other repo in a call to GetDelegationRoles
delgRoleList, err := delgRepo.GetDelegationRoles()
require.NoError(t, err)
require.Len(t, delgRoleList, 2)
// The walk is a pre-order so we can enforce ordering. Also check that canonical key IDs are reported from this walk
require.Equal(t, delgRoleList[0].Name, "targets/a")
require.NotContains(t, delgRoleList[0].KeyIDs, ownerRepo.tufRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles[0].KeyIDs)
canonicalAKeyID, err := utils.CanonicalKeyID(aKey)
require.NoError(t, err)
require.Contains(t, delgRoleList[0].KeyIDs, canonicalAKeyID)
require.Equal(t, delgRoleList[1].Name, "targets/a/b")
require.NotContains(t, delgRoleList[1].KeyIDs, ownerRepo.tufRepo.Targets["targets/a"].Signed.Delegations.Roles[0].KeyIDs)
canonicalBKeyID, err := utils.CanonicalKeyID(bKey)
require.NoError(t, err)
require.Contains(t, delgRoleList[1].KeyIDs, canonicalBKeyID)
// assert that the key ID data didn't somehow change between the two repos, since we translated to canonical key IDs
require.Equal(t, ownerRepo.tufRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles[0].KeyIDs, delgRepo.tufRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles[0].KeyIDs)
require.Equal(t, ownerRepo.tufRepo.Targets["targets/a"].Signed.Delegations.Roles[0].KeyIDs, delgRepo.tufRepo.Targets["targets/a"].Signed.Delegations.Roles[0].KeyIDs)

// delegated repo now publishes to delegated roles, but it will need
// to download those roles first, since it doesn't know about them
requirePublishToRolesSucceeds(t, delgRepo, []string{"targets/a/b"},
Expand Down
17 changes: 10 additions & 7 deletions client/delegations.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func newDeleteDelegationChange(name string, content []byte) *changelist.TUFChang

// GetDelegationRoles returns the keys and roles of the repository's delegations
// Also converts key IDs to canonical key IDs to keep consistent with signing prompts
func (r *NotaryRepository) GetDelegationRoles() ([]*data.Role, error) {
func (r *NotaryRepository) GetDelegationRoles() ([]data.Role, error) {
// Update state of the repo to latest
if err := r.Update(false); err != nil {
return nil, err
Expand All @@ -251,7 +251,7 @@ func (r *NotaryRepository) GetDelegationRoles() ([]*data.Role, error) {
}

// make a copy for traversing nested delegations
allDelegations := []*data.Role{}
allDelegations := []data.Role{}

// Define a visitor function to populate the delegations list and translate their key IDs to canonical IDs
delegationCanonicalListVisitor := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
Expand All @@ -271,20 +271,23 @@ func (r *NotaryRepository) GetDelegationRoles() ([]*data.Role, error) {
return allDelegations, nil
}

func translateDelegationsToCanonicalIDs(delegationInfo data.Delegations) ([]*data.Role, error) {
canonicalDelegations := make([]*data.Role, len(delegationInfo.Roles))
copy(canonicalDelegations, delegationInfo.Roles)
func translateDelegationsToCanonicalIDs(delegationInfo data.Delegations) ([]data.Role, error) {
canonicalDelegations := make([]data.Role, len(delegationInfo.Roles))
// Do a copy by value to ensure local delegation metadata is untouched
for idx, origRole := range delegationInfo.Roles {
canonicalDelegations[idx] = *origRole
}
delegationKeys := delegationInfo.Keys
for i, delegation := range canonicalDelegations {
canonicalKeyIDs := []string{}
for _, keyID := range delegation.KeyIDs {
pubKey, ok := delegationKeys[keyID]
if !ok {
return nil, fmt.Errorf("Could not translate canonical key IDs for %s", delegation.Name)
return []data.Role{}, fmt.Errorf("Could not translate canonical key IDs for %s", delegation.Name)
}
canonicalKeyID, err := utils.CanonicalKeyID(pubKey)
if err != nil {
return nil, fmt.Errorf("Could not translate canonical key IDs for %s: %v", delegation.Name, err)
return []data.Role{}, fmt.Errorf("Could not translate canonical key IDs for %s: %v", delegation.Name, err)
}
canonicalKeyIDs = append(canonicalKeyIDs, canonicalKeyID)
}
Expand Down
27 changes: 5 additions & 22 deletions cmd/notary-signer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"net"
"net/http"
"os"
"strings"
"time"
Expand Down Expand Up @@ -62,7 +61,7 @@ func parseSignerConfig(configFilePath string) (signer.Config, error) {
utils.SetUpBugsnag(bugsnagConf)

// parse server config
httpAddr, grpcAddr, tlsConfig, err := getAddrAndTLSConfig(config)
grpcAddr, tlsConfig, err := getAddrAndTLSConfig(config)
if err != nil {
return signer.Config{}, err
}
Expand All @@ -74,7 +73,6 @@ func parseSignerConfig(configFilePath string) (signer.Config, error) {
}

return signer.Config{
HTTPAddr: httpAddr,
GRPCAddr: grpcAddr,
TLSConfig: tlsConfig,
CryptoServices: cryptoServices,
Expand Down Expand Up @@ -213,33 +211,18 @@ func setupGRPCServer(grpcAddr string, tlsConfig *tls.Config,
return grpcServer, lis, nil
}

func setupHTTPServer(httpAddr string, tlsConfig *tls.Config,
cryptoServices signer.CryptoServiceIndex) *http.Server {

return &http.Server{
Addr: httpAddr,
Handler: api.Handlers(cryptoServices),
TLSConfig: tlsConfig,
}
}

func getAddrAndTLSConfig(configuration *viper.Viper) (string, string, *tls.Config, error) {
func getAddrAndTLSConfig(configuration *viper.Viper) (string, *tls.Config, error) {
tlsConfig, err := utils.ParseServerTLS(configuration, true)
if err != nil {
return "", "", nil, fmt.Errorf("unable to set up TLS: %s", err.Error())
return "", nil, fmt.Errorf("unable to set up TLS: %s", err.Error())
}

grpcAddr := configuration.GetString("server.grpc_addr")
if grpcAddr == "" {
return "", "", nil, fmt.Errorf("grpc listen address required for server")
}

httpAddr := configuration.GetString("server.http_addr")
if httpAddr == "" {
return "", "", nil, fmt.Errorf("http listen address required for server")
return "", nil, fmt.Errorf("grpc listen address required for server")
}

return httpAddr, grpcAddr, tlsConfig, nil
return grpcAddr, tlsConfig, nil
}

func bootstrap(s interface{}) error {
Expand Down
9 changes: 1 addition & 8 deletions cmd/notary-signer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,11 @@ func main() {
logrus.Fatal(err.Error())
}

httpServer := setupHTTPServer(signerConfig.HTTPAddr, signerConfig.TLSConfig, signerConfig.CryptoServices)

if debug {
log.Println("RPC server listening on", signerConfig.GRPCAddr)
log.Println("HTTP server listening on", signerConfig.HTTPAddr)
}

go grpcServer.Serve(lis)
err = httpServer.ListenAndServeTLS("", "")
if err != nil {
log.Fatal("HTTPS server failed to start:", err)
}
grpcServer.Serve(lis)
}

func usage() {
Expand Down
31 changes: 4 additions & 27 deletions cmd/notary-signer/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,24 @@ func configure(jsonConfig string) *viper.Viper {
// error is propagated.
func TestGetAddrAndTLSConfigInvalidTLS(t *testing.T) {
invalids := []string{
`{"server": {"http_addr": ":1234", "grpc_addr": ":2345"}}`,
`{"server": {"grpc_addr": ":2345"}}`,
`{"server": {
"http_addr": ":1234",
"grpc_addr": ":2345",
"tls_cert_file": "nope",
"tls_key_file": "nope"
}}`,
}
for _, configJSON := range invalids {
_, _, _, err := getAddrAndTLSConfig(configure(configJSON))
_, _, err := getAddrAndTLSConfig(configure(configJSON))
require.Error(t, err)
require.Contains(t, err.Error(), "unable to set up TLS")
}
}

// If a GRPC address is not provided, an error is returned.
func TestGetAddrAndTLSConfigNoGRPCAddr(t *testing.T) {
_, _, _, err := getAddrAndTLSConfig(configure(fmt.Sprintf(`{
_, _, err := getAddrAndTLSConfig(configure(fmt.Sprintf(`{
"server": {
"http_addr": ":1234",
"tls_cert_file": "%s",
"tls_key_file": "%s"
}
Expand All @@ -68,31 +66,16 @@ func TestGetAddrAndTLSConfigNoGRPCAddr(t *testing.T) {
require.Contains(t, err.Error(), "grpc listen address required for server")
}

// If an HTTP address is not provided, an error is returned.
func TestGetAddrAndTLSConfigNoHTTPAddr(t *testing.T) {
_, _, _, err := getAddrAndTLSConfig(configure(fmt.Sprintf(`{
"server": {
"grpc_addr": ":1234",
"tls_cert_file": "%s",
"tls_key_file": "%s"
}
}`, Cert, Key)))
require.Error(t, err)
require.Contains(t, err.Error(), "http listen address required for server")
}

// Success parsing a valid TLS config, HTTP address, and GRPC address.
func TestGetAddrAndTLSConfigSuccess(t *testing.T) {
httpAddr, grpcAddr, tlsConf, err := getAddrAndTLSConfig(configure(fmt.Sprintf(`{
grpcAddr, tlsConf, err := getAddrAndTLSConfig(configure(fmt.Sprintf(`{
"server": {
"http_addr": ":2345",
"grpc_addr": ":1234",
"tls_cert_file": "%s",
"tls_key_file": "%s"
}
}`, Cert, Key)))
require.NoError(t, err)
require.Equal(t, ":2345", httpAddr)
require.Equal(t, ":1234", grpcAddr)
require.NotNil(t, tlsConf)
}
Expand Down Expand Up @@ -241,12 +224,6 @@ func TestSetupCryptoServicesInvalidStore(t *testing.T) {
require.Equal(t, err.Error(), fmt.Sprintf("%s is not an allowed backend, must be one of: %s", "invalid_backend", []string{notary.SQLiteBackend, notary.MemoryBackend, notary.RethinkDBBackend}))
}

func TestSetupHTTPServer(t *testing.T) {
httpServer := setupHTTPServer(":4443", nil, make(signer.CryptoServiceIndex))
require.Equal(t, ":4443", httpServer.Addr)
require.Nil(t, httpServer.TLSConfig)
}

func TestSetupGRPCServerInvalidAddress(t *testing.T) {
_, _, err := setupGRPCServer("nope", nil, make(signer.CryptoServiceIndex))
require.Error(t, err)
Expand Down
52 changes: 52 additions & 0 deletions cmd/notary/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,58 @@ func TestClientDelegationsPublishing(t *testing.T) {
output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun", "--roles", "targets/releases")
require.NoError(t, err)
require.Contains(t, output, "targets/releases")

// Setup another certificate
tempFile2, err := ioutil.TempFile("", "pemfile2")
require.NoError(t, err)

privKey, err = utils.GenerateECDSAKey(rand.Reader)
startTime = time.Now()
endTime = startTime.AddDate(10, 0, 0)
cert, err = cryptoservice.GenerateCertificate(privKey, "gun", startTime, endTime)
require.NoError(t, err)

_, err = tempFile2.Write(utils.CertToPEM(cert))
require.NoError(t, err)
require.NoError(t, err)
tempFile2.Close()
defer os.Remove(tempFile2.Name())

rawPubBytes2, _ := ioutil.ReadFile(tempFile2.Name())
parsedPubKey2, _ := utils.ParsePEMPublicKey(rawPubBytes2)
keyID2, err := utils.CanonicalKeyID(parsedPubKey2)
require.NoError(t, err)

// add a nested delegation under this releases role
output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/releases/nested", tempFile2.Name(), "--paths", "nested/path")
require.NoError(t, err)
require.Contains(t, output, "Addition of delegation role")
require.Contains(t, output, keyID2)

// publish repo
_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
require.NoError(t, err)

// list delegations - we should see two roles
output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
require.NoError(t, err)
require.Contains(t, output, "targets/releases")
require.Contains(t, output, "targets/releases/nested")
require.Contains(t, output, canonicalKeyID)
require.Contains(t, output, keyID2)
require.Contains(t, output, "nested/path")
require.Contains(t, output, "\"\"")
require.Contains(t, output, "<all paths>")

// remove by force to delete the nested delegation entirely
output, err = runCommand(t, tempDir, "delegation", "remove", "gun", "targets/releases/nested", "-y")
require.NoError(t, err)
require.Contains(t, output, "Forced removal (including all keys and paths) of delegation role")

// publish repo
_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
require.NoError(t, err)

}

// Splits a string into lines, and returns any lines that are not empty (
Expand Down
4 changes: 2 additions & 2 deletions cmd/notary/prettyprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (t targetsSorter) Less(i, j int) bool {

// --- pretty printing roles ---

type roleSorter []*data.Role
type roleSorter []data.Role

func (r roleSorter) Len() int { return len(r) }
func (r roleSorter) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
Expand Down Expand Up @@ -173,7 +173,7 @@ func prettyPrintTargets(ts []*client.TargetWithRole, writer io.Writer) {
}

// Pretty-prints the list of provided Roles
func prettyPrintRoles(rs []*data.Role, writer io.Writer, roleType string) {
func prettyPrintRoles(rs []data.Role, writer io.Writer, roleType string) {
if len(rs) == 0 {
writer.Write([]byte(fmt.Sprintf("\nNo %s present in this repository.\n\n", roleType)))
return
Expand Down
4 changes: 2 additions & 2 deletions cmd/notary/prettyprint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func TestPrettyPrintSortedTargets(t *testing.T) {
// are no roles.
func TestPrettyPrintZeroRoles(t *testing.T) {
var b bytes.Buffer
prettyPrintRoles([]*data.Role{}, &b, "delegations")
prettyPrintRoles([]data.Role{}, &b, "delegations")
text, err := ioutil.ReadAll(&b)
require.NoError(t, err)

Expand All @@ -218,7 +218,7 @@ func TestPrettyPrintZeroRoles(t *testing.T) {
func TestPrettyPrintSortedRoles(t *testing.T) {
var err error

unsorted := []*data.Role{
unsorted := []data.Role{
{Name: "targets/zebra", Paths: []string{"stripes", "black", "white"}, RootRole: data.RootRole{KeyIDs: []string{"101"}, Threshold: 1}},
{Name: "targets/aardvark/unicorn/pony", Paths: []string{"rainbows"}, RootRole: data.RootRole{KeyIDs: []string{"135"}, Threshold: 1}},
{Name: "targets/bee", Paths: []string{"honey"}, RootRole: data.RootRole{KeyIDs: []string{"246"}, Threshold: 1}},
Expand Down
22 changes: 2 additions & 20 deletions docs/reference/signer-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ learn more about the configuration section corresponding to that key:

<pre><code class="language-json">{
<a href="#server-section-required">"server"</a>: {
"http_addr": ":4444",
"grpc_addr": ":7899",
"tls_cert_file": "./fixtures/notary-signer.crt",
"tls_key_file": "./fixtures/notary-signer.key",
Expand Down Expand Up @@ -57,7 +56,6 @@ Example:

```json
"server": {
"http_addr": ":4444",
"grpc_addr": ":7899",
"tls_cert_file": "./fixtures/notary-signer.crt",
"tls_key_file": "./fixtures/notary-signer.key",
Expand All @@ -71,22 +69,6 @@ Example:
<th>Required</th>
<th>Description</th>
</tr>
<tr>
<td valign="top"><code>http_addr</code></td>
<td valign="top">yes</td>
<td valign="top">The TCP address (IP and port) to listen for HTTP
traffic on. Examples:
<ul>
<li><code>":4444"</code> means listen on port 4444 on all IPs (and
hence all interfaces, such as those listed when you run
<code>ifconfig</code>)</li>
<li><code>"127.0.0.1:4444"</code> means listen on port 4444 on
localhost only. That means that the server will not be
accessible except locally (via SSH tunnel, or just on a local
terminal)</li>
</ul>
</td>
</tr>
<tr>
<td valign="top"><code>grpc_addr</code></td>
<td valign="top">yes</td>
Expand All @@ -107,14 +89,14 @@ Example:
<td valign="top"><code>tls_key_file</code></td>
<td valign="top">yes</td>
<td valign="top">The path to the private key to use for
HTTPS. The path is relative to the directory of the
GRPC TLS. The path is relative to the directory of the
configuration file.</td>
</tr>
<tr>
<td valign="top"><code>tls_cert_file</code></td>
<td valign="top">yes</td>
<td valign="top">The path to the certificate to use for
HTTPS. The path is relative to the directory of the
GRPC TLS. The path is relative to the directory of the
configuration file.</td>
</tr>
<tr>
Expand Down
1 change: 0 additions & 1 deletion fixtures/signer-config-local.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"server": {
"http_addr": ":4444",
"grpc_addr": ":7899",
"tls_cert_file": "./notary-signer.crt",
"tls_key_file": "./notary-signer.key",
Expand Down
1 change: 0 additions & 1 deletion fixtures/signer-config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"server": {
"http_addr": ":4444",
"grpc_addr": ":7899",
"tls_cert_file": "./notary-signer.crt",
"tls_key_file": "./notary-signer.key",
Expand Down
Loading

0 comments on commit 79dbeb3

Please sign in to comment.