mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #20523 from cyli/vendor-notary-version-for-docker-1.10.2
Bump the notary version to one that fixes a bug with delegation path traversal
This commit is contained in:
commit
1bfaf317a9
9 changed files with 155 additions and 31 deletions
|
@ -88,7 +88,7 @@ RUN cd /usr/local/lvm2 \
|
|||
|
||||
# Install Go
|
||||
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
|
||||
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
|
||||
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
|
||||
# with a heads-up.
|
||||
ENV GO_VERSION 1.5.3
|
||||
RUN curl -fsSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||||
|
@ -168,7 +168,7 @@ RUN set -x \
|
|||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install notary server
|
||||
ENV NOTARY_VERSION docker-v1.10-5
|
||||
ENV NOTARY_VERSION docker-v1.10.2-1
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
|
|
|
@ -145,7 +145,7 @@ RUN set -x \
|
|||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install notary server
|
||||
ENV NOTARY_VERSION docker-v1.10-5
|
||||
ENV NOTARY_VERSION docker-v1.10.2-1
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
|
|
|
@ -116,7 +116,7 @@ RUN set -x \
|
|||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install notary server
|
||||
#ENV NOTARY_VERSION docker-v1.10-5
|
||||
#ENV NOTARY_VERSION docker-v1.10.2-1
|
||||
#RUN set -x \
|
||||
# && export GOPATH="$(mktemp -d)" \
|
||||
# && git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
|
|
|
@ -116,7 +116,7 @@ RUN set -x \
|
|||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install notary server
|
||||
ENV NOTARY_VERSION docker-v1.10-5
|
||||
ENV NOTARY_VERSION docker-v1.10.2-1
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
|
|
|
@ -50,7 +50,7 @@ clone git github.com/docker/distribution 0f2d99b13ae0cfbcf118eff103e6e680b726b47
|
|||
clone git github.com/vbatts/tar-split v0.9.11
|
||||
|
||||
# get desired notary commit, might also need to be updated in Dockerfile
|
||||
clone git github.com/docker/notary docker-v1.10-5
|
||||
clone git github.com/docker/notary docker-v1.10.2-1
|
||||
|
||||
clone git google.golang.org/grpc 174192fc93efcb188fc8f46ca447f0da606b6885 https://github.com/grpc/grpc-go.git
|
||||
clone git github.com/miekg/pkcs11 80f102b5cac759de406949c47f0928b99bd64cdf
|
||||
|
|
100
vendor/src/github.com/docker/notary/client/client.go
vendored
100
vendor/src/github.com/docker/notary/client/client.go
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
|
@ -451,11 +452,48 @@ func (r *NotaryRepository) ListTargets(roles ...string) ([]*TargetWithRole, erro
|
|||
roles = []string{data.CanonicalTargetsRole}
|
||||
}
|
||||
targets := make(map[string]*TargetWithRole)
|
||||
|
||||
for _, role := range roles {
|
||||
var foundRole *data.Role
|
||||
walkRoles := []*data.Role{}
|
||||
if role == data.CanonicalTargetsRole {
|
||||
foundRole = &data.Role{
|
||||
Name: data.CanonicalTargetsRole,
|
||||
Paths: []string{""},
|
||||
PathHashPrefixes: []string{""},
|
||||
}
|
||||
}
|
||||
|
||||
walkRoles = append(walkRoles, r.tufRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles...)
|
||||
for len(walkRoles) > 0 && foundRole == nil {
|
||||
currRole := walkRoles[0]
|
||||
walkRoles = walkRoles[1:]
|
||||
if currRole.Name == role {
|
||||
foundRole = currRole
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(role, currRole.Name+"/") {
|
||||
targetMeta, ok := r.tufRepo.Targets[currRole.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, childRole := range targetMeta.Signed.Delegations.Roles {
|
||||
restricted, err := data.Restrict(*currRole, *childRole)
|
||||
if err == nil {
|
||||
walkRoles = append(walkRoles, restricted)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if foundRole == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// we don't need to do anything special with removing role from
|
||||
// roles because listSubtree always processes role and only excludes
|
||||
// descendant delegations that appear in roles.
|
||||
r.listSubtree(targets, role, roles...)
|
||||
r.listSubtree(targets, foundRole, roles...)
|
||||
}
|
||||
|
||||
var targetList []*TargetWithRole
|
||||
|
@ -466,29 +504,32 @@ func (r *NotaryRepository) ListTargets(roles ...string) ([]*TargetWithRole, erro
|
|||
return targetList, nil
|
||||
}
|
||||
|
||||
func (r *NotaryRepository) listSubtree(targets map[string]*TargetWithRole, role string, exclude ...string) {
|
||||
func (r *NotaryRepository) listSubtree(targets map[string]*TargetWithRole, role *data.Role, exclude ...string) {
|
||||
excl := make(map[string]bool)
|
||||
for _, r := range exclude {
|
||||
excl[r] = true
|
||||
}
|
||||
roles := []string{role}
|
||||
roles := []*data.Role{role}
|
||||
for len(roles) > 0 {
|
||||
role = roles[0]
|
||||
roles = roles[1:]
|
||||
tgts, ok := r.tufRepo.Targets[role]
|
||||
tgts, ok := r.tufRepo.Targets[role.Name]
|
||||
if !ok {
|
||||
// not every role has to exist
|
||||
continue
|
||||
}
|
||||
for name, meta := range tgts.Signed.Targets {
|
||||
if _, ok := targets[name]; !ok {
|
||||
if _, ok := targets[name]; !ok && role.CheckPaths(name) {
|
||||
targets[name] = &TargetWithRole{
|
||||
Target: Target{Name: name, Hashes: meta.Hashes, Length: meta.Length}, Role: role}
|
||||
Target: Target{Name: name, Hashes: meta.Hashes, Length: meta.Length}, Role: role.Name}
|
||||
}
|
||||
}
|
||||
for _, d := range tgts.Signed.Delegations.Roles {
|
||||
if !excl[d.Name] {
|
||||
roles = append(roles, d.Name)
|
||||
for _, child := range tgts.Signed.Delegations.Roles {
|
||||
if !excl[child.Name] {
|
||||
child, err := data.Restrict(*role, *child)
|
||||
if err == nil {
|
||||
roles = append(roles, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -511,10 +552,47 @@ func (r *NotaryRepository) GetTargetByName(name string, roles ...string) (*Targe
|
|||
roles = append(roles, data.CanonicalTargetsRole)
|
||||
}
|
||||
for _, role := range roles {
|
||||
meta, foundRole := c.TargetMeta(role, name, roles...)
|
||||
|
||||
var foundRole *data.Role
|
||||
walkRoles := []*data.Role{}
|
||||
if role == data.CanonicalTargetsRole {
|
||||
foundRole = &data.Role{
|
||||
Name: data.CanonicalTargetsRole,
|
||||
Paths: []string{""},
|
||||
PathHashPrefixes: []string{""},
|
||||
}
|
||||
}
|
||||
|
||||
walkRoles = append(walkRoles, r.tufRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles...)
|
||||
for len(walkRoles) > 0 && foundRole == nil {
|
||||
currRole := walkRoles[0]
|
||||
walkRoles = walkRoles[1:]
|
||||
if currRole.Name == role {
|
||||
foundRole = currRole
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(role, currRole.Name+"/") {
|
||||
targetMeta, ok := r.tufRepo.Targets[currRole.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, childRole := range targetMeta.Signed.Delegations.Roles {
|
||||
restricted, err := data.Restrict(*currRole, *childRole)
|
||||
if err == nil && restricted.CheckPaths(name) {
|
||||
walkRoles = append(walkRoles, restricted)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if foundRole == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
meta, ownerName := c.TargetMeta(foundRole, name, roles...)
|
||||
if meta != nil {
|
||||
return &TargetWithRole{
|
||||
Target: Target{Name: name, Hashes: meta.Hashes, Length: meta.Length}, Role: foundRole}, nil
|
||||
Target: Target{Name: name, Hashes: meta.Hashes, Length: meta.Length}, Role: ownerName}, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("No trust data for %s", name)
|
||||
|
|
|
@ -526,39 +526,44 @@ func (c Client) RoleTargetsPath(role string, hashSha256 string, consistent bool)
|
|||
|
||||
// TargetMeta ensures the repo is up to date. It assumes downloadTargets
|
||||
// has already downloaded all delegated roles
|
||||
func (c Client) TargetMeta(role, path string, excludeRoles ...string) (*data.FileMeta, string) {
|
||||
func (c Client) TargetMeta(role *data.Role, path string, excludeRoles ...string) (*data.FileMeta, string) {
|
||||
excl := make(map[string]bool)
|
||||
for _, r := range excludeRoles {
|
||||
excl[r] = true
|
||||
}
|
||||
|
||||
pathDigest := sha256.Sum256([]byte(path))
|
||||
pathHex := hex.EncodeToString(pathDigest[:])
|
||||
|
||||
// FIFO list of targets delegations to inspect for target
|
||||
roles := []string{role}
|
||||
roles := []*data.Role{role}
|
||||
var (
|
||||
meta *data.FileMeta
|
||||
curr string
|
||||
curr *data.Role
|
||||
)
|
||||
for len(roles) > 0 {
|
||||
// have to do these lines here because of order of execution in for statement
|
||||
curr = roles[0]
|
||||
roles = roles[1:]
|
||||
|
||||
meta = c.local.TargetMeta(curr, path)
|
||||
meta = c.local.TargetMeta(curr.Name, path)
|
||||
if meta != nil {
|
||||
// we found the target!
|
||||
return meta, curr
|
||||
return meta, curr.Name
|
||||
}
|
||||
delegations := c.local.TargetDelegations(curr, path, pathHex)
|
||||
for _, d := range delegations {
|
||||
if !excl[d.Name] {
|
||||
roles = append(roles, d.Name)
|
||||
tgts, ok := c.local.Targets[curr.Name]
|
||||
if !ok {
|
||||
// not every role has to exist
|
||||
continue
|
||||
}
|
||||
|
||||
for _, child := range tgts.Signed.Delegations.Roles {
|
||||
if !excl[child.Name] {
|
||||
child, err := data.Restrict(*curr, *child)
|
||||
if err == nil && child.CheckPaths(path) {
|
||||
roles = append(roles, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return meta, ""
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
// DownloadTarget downloads the target to dst from the remote
|
||||
|
|
|
@ -2,10 +2,11 @@ package data
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Canonical base role names
|
||||
|
@ -244,3 +245,40 @@ func subtractStrSlices(orig, remove []string) []string {
|
|||
}
|
||||
return keep
|
||||
}
|
||||
|
||||
// Restrict restricts the paths and path hash prefixes for the passed in delegation role,
|
||||
// returning a copy of the role with validated paths as if it was a direct child
|
||||
func Restrict(parent, child Role) (*Role, error) {
|
||||
if path.Dir(child.Name) != parent.Name {
|
||||
return nil, fmt.Errorf("%s is not a parent of %s", parent.Name, child.Name)
|
||||
}
|
||||
return &Role{
|
||||
RootRole: child.RootRole,
|
||||
Name: child.Name,
|
||||
Paths: RestrictDelegationPathPrefixes(parent.Paths, child.Paths),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RestrictDelegationPathPrefixes returns the list of valid delegationPaths that are prefixed by parentPaths
|
||||
func RestrictDelegationPathPrefixes(parentPaths, delegationPaths []string) []string {
|
||||
validPaths := []string{}
|
||||
if len(delegationPaths) == 0 {
|
||||
return validPaths
|
||||
}
|
||||
|
||||
// Validate each individual delegation path
|
||||
for _, delgPath := range delegationPaths {
|
||||
isPrefixed := false
|
||||
for _, parentPath := range parentPaths {
|
||||
if strings.HasPrefix(delgPath, parentPath) {
|
||||
isPrefixed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// If the delegation path did not match prefix against any parent path, it is not valid
|
||||
if isPrefixed {
|
||||
validPaths = append(validPaths, delgPath)
|
||||
}
|
||||
}
|
||||
return validPaths
|
||||
}
|
||||
|
|
|
@ -459,6 +459,9 @@ func (tr *Repo) SetTargets(role string, s *data.SignedTargets) error {
|
|||
tr.keysDB.AddKey(k)
|
||||
}
|
||||
for _, r := range s.Signed.Delegations.Roles {
|
||||
if path.Dir(r.Name) != role || tr.keysDB.GetRole(r.Name) != nil {
|
||||
continue
|
||||
}
|
||||
tr.keysDB.AddRole(r)
|
||||
}
|
||||
tr.Targets[role] = s
|
||||
|
|
Loading…
Reference in a new issue