// ApplyTargets falls back to role that exists when adding or deleting a change
func TestApplyChangelistTargetsFallbackRoles(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)

	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	assert.NoError(t, err)

	cl := changelist.NewMemChangelist()
	assert.NoError(t, cl.Add(&changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       "targets/level1/level2/level3/level4",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))

	assert.NoError(t, applyChangelist(repo, cl))
	_, ok := repo.Targets[data.CanonicalTargetsRole].Signed.Targets["latest"]
	assert.True(t, ok)

	// now delete and assert it applies to
	cl = changelist.NewMemChangelist()
	assert.NoError(t, cl.Add(&changelist.TufChange{
		Actn:       changelist.ActionDelete,
		Role:       "targets/level1/level2/level3/level4",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       nil,
	}))

	assert.NoError(t, applyChangelist(repo, cl))
	assert.Empty(t, repo.Targets[data.CanonicalTargetsRole].Signed.Targets)
}
Exemple #2
0
// ApplyTargets fails when adding or deleting a change to a nonexistent delegation
func TestApplyChangelistTargetsFailsNonexistentRole(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	require.NoError(t, err)

	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	require.NoError(t, err)

	cl := changelist.NewMemChangelist()
	require.NoError(t, cl.Add(&changelist.TUFChange{
		Actn:       changelist.ActionCreate,
		Role:       "targets/level1/level2/level3/level4",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))
	err = applyChangelist(repo, nil, cl)
	require.Error(t, err)
	require.IsType(t, data.ErrInvalidRole{}, err)

	// now try a delete and assert the same error
	cl = changelist.NewMemChangelist()
	require.NoError(t, cl.Add(&changelist.TUFChange{
		Actn:       changelist.ActionDelete,
		Role:       "targets/level1/level2/level3/level4",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       nil,
	}))

	err = applyChangelist(repo, nil, cl)
	require.Error(t, err)
	require.IsType(t, data.ErrInvalidRole{}, err)
}
Exemple #3
0
// RotateKey removes all existing keys associated with the role, and either
// creates and adds one new key or delegates managing the key to the server.
// These changes are staged in a changelist until publish is called.
func (r *NotaryRepository) RotateKey(role string, serverManagesKey bool) error {
	// We currently support remotely managing timestamp and snapshot keys
	canBeRemoteKey := role == data.CanonicalTimestampRole || role == data.CanonicalSnapshotRole
	// And locally managing root, targets, and snapshot keys
	canBeLocalKey := (role == data.CanonicalSnapshotRole || role == data.CanonicalTargetsRole ||
		role == data.CanonicalRootRole)

	switch {
	case !data.ValidRole(role) || data.IsDelegation(role):
		return fmt.Errorf("notary does not currently permit rotating the %s key", role)
	case serverManagesKey && !canBeRemoteKey:
		return ErrInvalidRemoteRole{Role: role}
	case !serverManagesKey && !canBeLocalKey:
		return ErrInvalidLocalRole{Role: role}
	}

	var (
		pubKey    data.PublicKey
		err       error
		errFmtMsg string
	)
	switch serverManagesKey {
	case true:
		pubKey, err = getRemoteKey(r.baseURL, r.gun, role, r.roundTrip)
		errFmtMsg = "unable to rotate remote key: %s"
	default:
		pubKey, err = r.CryptoService.Create(role, r.gun, data.ECDSAKey)
		errFmtMsg = "unable to generate key: %s"
	}

	if err != nil {
		return fmt.Errorf(errFmtMsg, err)
	}

	// if this is a root role, generate a root cert for the public key
	if role == data.CanonicalRootRole {
		privKey, _, err := r.CryptoService.GetPrivateKey(pubKey.ID())
		if err != nil {
			return err
		}
		pubKey, err = rootCertKey(r.gun, privKey)
		if err != nil {
			return err
		}
	}

	cl := changelist.NewMemChangelist()
	if err := r.rootFileKeyChange(cl, role, changelist.ActionCreate, pubKey); err != nil {
		return err
	}
	return r.publish(cl)
}
Exemple #4
0
// Each change applies only to the role specified
func TestApplyChangelistTargetsToMultipleRoles(t *testing.T) {
	repo, cs, err := testutils.EmptyRepo("docker.com/notary")
	require.NoError(t, err)

	newKey, err := cs.Create("targets/level1", "docker.com/notary", data.ED25519Key)
	require.NoError(t, err)

	err = repo.UpdateDelegationKeys("targets/level1", []data.PublicKey{newKey}, []string{}, 1)
	require.NoError(t, err)
	err = repo.UpdateDelegationPaths("targets/level1", []string{""}, []string{}, false)
	require.NoError(t, err)

	err = repo.UpdateDelegationKeys("targets/level2", []data.PublicKey{newKey}, []string{}, 1)
	require.NoError(t, err)
	err = repo.UpdateDelegationPaths("targets/level2", []string{""}, []string{}, false)
	require.NoError(t, err)

	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	require.NoError(t, err)

	cl := changelist.NewMemChangelist()
	require.NoError(t, cl.Add(&changelist.TUFChange{
		Actn:       changelist.ActionCreate,
		Role:       "targets/level1",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))
	require.NoError(t, cl.Add(&changelist.TUFChange{
		Actn:       changelist.ActionDelete,
		Role:       "targets/level2",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       nil,
	}))

	require.NoError(t, applyChangelist(repo, nil, cl))
	_, ok := repo.Targets["targets/level1"].Signed.Targets["latest"]
	require.True(t, ok)
	_, ok = repo.Targets["targets/level2"]
	require.False(t, ok, "no change to targets/level2, so metadata not created")
}
Exemple #5
0
func TestApplyChangelist(t *testing.T) {
	kdb := keys.NewDB()
	role, err := data.NewRole("targets", 1, nil, nil, nil)
	assert.NoError(t, err)
	kdb.AddRole(role)

	repo := tuf.NewRepo(kdb, nil)
	err = repo.InitTargets()
	assert.NoError(t, err)
	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	assert.NoError(t, err)

	cl := changelist.NewMemChangelist()
	addChange := &changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       changelist.ScopeTargets,
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}
	cl.Add(addChange)
	err = applyChangelist(repo, cl)
	assert.NoError(t, err)
	assert.NotNil(t, repo.Targets["targets"].Signed.Targets["latest"])

	cl.Clear("")

	removeChange := &changelist.TufChange{
		Actn:       changelist.ActionDelete,
		Role:       changelist.ScopeTargets,
		ChangeType: "target",
		ChangePath: "latest",
		Data:       nil,
	}
	cl.Add(removeChange)
	err = applyChangelist(repo, cl)
	assert.NoError(t, err)
	_, ok := repo.Targets["targets"].Signed.Targets["latest"]
	assert.False(t, ok)
}
Exemple #6
0
// Each change applies only to the role specified
func TestApplyChangelistTargetsToMultipleRoles(t *testing.T) {
	_, repo, cs := testutils.EmptyRepo()

	newKey, err := cs.Create("targets/level1", data.ED25519Key)
	assert.NoError(t, err)

	r, err := data.NewRole("targets/level1", 1, []string{newKey.ID()}, []string{""}, nil)
	assert.NoError(t, err)
	repo.UpdateDelegations(r, []data.PublicKey{newKey})

	r, err = data.NewRole("targets/level2", 1, []string{newKey.ID()}, []string{""}, nil)
	assert.NoError(t, err)
	repo.UpdateDelegations(r, []data.PublicKey{newKey})

	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	assert.NoError(t, err)

	cl := changelist.NewMemChangelist()
	assert.NoError(t, cl.Add(&changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       "targets/level1",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))
	assert.NoError(t, cl.Add(&changelist.TufChange{
		Actn:       changelist.ActionDelete,
		Role:       "targets/level2",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       nil,
	}))

	assert.NoError(t, applyChangelist(repo, cl))
	_, ok := repo.Targets["targets/level1"].Signed.Targets["latest"]
	assert.True(t, ok)
	_, ok = repo.Targets["targets/level2"]
	assert.False(t, ok, "no change to targets/level2, so metadata not created")
}
Exemple #7
0
// RotateKey removes all existing keys associated with the role, and either
// creates and adds one new key or delegates managing the key to the server.
// These changes are staged in a changelist until publish is called.
func (r *NotaryRepository) RotateKey(role string, serverManagesKey bool) error {
	switch {
	// We currently support locally or remotely managing snapshot keys...
	case role == data.CanonicalSnapshotRole:
		break

	// locally managing targets keys only
	case role == data.CanonicalTargetsRole && !serverManagesKey:
		break
	case role == data.CanonicalTargetsRole && serverManagesKey:
		return ErrInvalidRemoteRole{Role: data.CanonicalTargetsRole}

	// and remotely managing timestamp keys only
	case role == data.CanonicalTimestampRole && serverManagesKey:
		break
	case role == data.CanonicalTimestampRole && !serverManagesKey:
		return ErrInvalidLocalRole{Role: data.CanonicalTimestampRole}

	default:
		return fmt.Errorf("notary does not currently permit rotating the %s key", role)
	}

	var (
		pubKey    data.PublicKey
		err       error
		errFmtMsg string
	)
	switch serverManagesKey {
	case true:
		pubKey, err = getRemoteKey(r.baseURL, r.gun, role, r.roundTrip)
		errFmtMsg = "unable to rotate remote key: %s"
	default:
		pubKey, err = r.CryptoService.Create(role, r.gun, data.ECDSAKey)
		errFmtMsg = "unable to generate key: %s"
	}

	if err != nil {
		return fmt.Errorf(errFmtMsg, err)
	}

	cl := changelist.NewMemChangelist()
	if err := r.rootFileKeyChange(cl, role, changelist.ActionCreate, pubKey); err != nil {
		return err
	}
	return r.publish(cl)
}
// Adding the same target twice doesn't actually add it.
func TestApplyAddTargetTwice(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	_, err = repo.InitTargets(data.CanonicalTargetsRole)
	assert.NoError(t, err)
	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	assert.NoError(t, err)

	cl := changelist.NewMemChangelist()
	assert.NoError(t, cl.Add(&changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       changelist.ScopeTargets,
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))
	assert.NoError(t, cl.Add(&changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       changelist.ScopeTargets,
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))

	assert.NoError(t, applyChangelist(repo, cl))
	assert.Len(t, repo.Targets["targets"].Signed.Targets, 1)
	assert.NotEmpty(t, repo.Targets["targets"].Signed.Targets["latest"])

	assert.NoError(t, applyTargetsChange(repo, &changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       changelist.ScopeTargets,
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))
	assert.Len(t, repo.Targets["targets"].Signed.Targets, 1)
	assert.NotEmpty(t, repo.Targets["targets"].Signed.Targets["latest"])
}
func TestApplyChangelist(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	_, err = repo.InitTargets(data.CanonicalTargetsRole)
	assert.NoError(t, err)
	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	assert.NoError(t, err)

	cl := changelist.NewMemChangelist()
	addChange := &changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       changelist.ScopeTargets,
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}
	cl.Add(addChange)
	err = applyChangelist(repo, cl)
	assert.NoError(t, err)
	assert.NotNil(t, repo.Targets["targets"].Signed.Targets["latest"])

	cl.Clear("")

	removeChange := &changelist.TufChange{
		Actn:       changelist.ActionDelete,
		Role:       changelist.ScopeTargets,
		ChangeType: "target",
		ChangePath: "latest",
		Data:       nil,
	}
	cl.Add(removeChange)
	err = applyChangelist(repo, cl)
	assert.NoError(t, err)
	_, ok := repo.Targets["targets"].Signed.Targets["latest"]
	assert.False(t, ok)
}
Exemple #10
0
// RotateKey removes all existing keys associated with the role, and either
// creates and adds one new key or delegates managing the key to the server.
// These changes are staged in a changelist until publish is called.
func (r *NotaryRepository) RotateKey(role string, serverManagesKey bool) error {
	if err := checkRotationInput(role, serverManagesKey); err != nil {
		return err
	}
	var (
		pubKey    data.PublicKey
		err       error
		errFmtMsg string
	)
	switch serverManagesKey {
	case true:
		pubKey, err = rotateRemoteKey(r.baseURL, r.gun, role, r.roundTrip)
		errFmtMsg = "unable to rotate remote key: %s"
	default:
		pubKey, err = r.CryptoService.Create(role, r.gun, data.ECDSAKey)
		errFmtMsg = "unable to generate key: %s"
	}

	if err != nil {
		return fmt.Errorf(errFmtMsg, err)
	}

	// if this is a root role, generate a root cert for the public key
	if role == data.CanonicalRootRole {
		privKey, _, err := r.CryptoService.GetPrivateKey(pubKey.ID())
		if err != nil {
			return err
		}
		pubKey, err = rootCertKey(r.gun, privKey)
		if err != nil {
			return err
		}
	}

	cl := changelist.NewMemChangelist()
	if err := r.rootFileKeyChange(cl, role, changelist.ActionCreate, pubKey); err != nil {
		return err
	}
	return r.publish(cl)
}
Exemple #11
0
// If there is no delegation target, ApplyTargets creates it
func TestApplyChangelistCreatesDelegation(t *testing.T) {
	repo, cs, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)

	newKey, err := cs.Create("targets/level1", data.ED25519Key)
	assert.NoError(t, err)

	r, err := data.NewRole("targets/level1", 1, []string{newKey.ID()}, []string{""})
	assert.NoError(t, err)
	repo.UpdateDelegations(r, []data.PublicKey{newKey})
	delete(repo.Targets, "targets/level1")

	hash := sha256.Sum256([]byte{})
	f := &data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	fjson, err := json.Marshal(f)
	assert.NoError(t, err)

	cl := changelist.NewMemChangelist()
	assert.NoError(t, cl.Add(&changelist.TufChange{
		Actn:       changelist.ActionCreate,
		Role:       "targets/level1",
		ChangeType: "target",
		ChangePath: "latest",
		Data:       fjson,
	}))

	assert.NoError(t, applyChangelist(repo, cl))
	_, ok := repo.Targets["targets/level1"]
	assert.True(t, ok, "Failed to create the delegation target")
	_, ok = repo.Targets["targets/level1"].Signed.Targets["latest"]
	assert.True(t, ok, "Failed to write change to delegation target")
}