diff --git a/daemon/daemon.go b/daemon/daemon.go index a3f2dace73..e07a011798 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -35,7 +35,6 @@ import ( "github.com/docker/docker/pkg/truncindex" "github.com/docker/docker/registry" "github.com/docker/docker/runconfig" - "github.com/docker/docker/trust" "github.com/docker/libnetwork" "github.com/opencontainers/runc/libcontainer/netlink" ) @@ -670,10 +669,6 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo if err := system.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) { return nil, err } - trustService, err := trust.NewTrustStore(trustDir) - if err != nil { - return nil, fmt.Errorf("could not create trust store: %s", err) - } eventsService := events.New() logrus.Debug("Creating repository list") @@ -682,7 +677,6 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo Key: trustKey, Registry: registryService, Events: eventsService, - Trust: trustService, } repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg) if err != nil { diff --git a/graph/pull.go b/graph/pull.go index 56f226e5cc..736c5add97 100644 --- a/graph/pull.go +++ b/graph/pull.go @@ -86,12 +86,6 @@ func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConf for _, endpoint := range endpoints { logrus.Debugf("Trying to pull %s from %s %s", repoInfo.LocalName, endpoint.URL, endpoint.Version) - if !endpoint.Mirror && (endpoint.Official || endpoint.Version == registry.APIVersion2) { - if repoInfo.Official { - s.trustService.UpdateBase() - } - } - puller, err := NewPuller(s, endpoint, repoInfo, imagePullConfig, sf) if err != nil { lastErr = err diff --git a/graph/tags.go b/graph/tags.go index a96ad94bfe..7e16abac52 100644 --- a/graph/tags.go +++ b/graph/tags.go @@ -19,7 +19,6 @@ import ( "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/registry" - "github.com/docker/docker/trust" "github.com/docker/docker/utils" "github.com/docker/libtrust" ) @@ -38,7 +37,6 @@ type TagStore struct { pushingPool map[string]chan struct{} registryService *registry.Service eventsService *events.Events - trustService *trust.TrustStore } type Repository map[string]string @@ -66,7 +64,6 @@ type TagStoreConfig struct { Key libtrust.PrivateKey Registry *registry.Service Events *events.Events - Trust *trust.TrustStore } func NewTagStore(path string, cfg *TagStoreConfig) (*TagStore, error) { @@ -84,7 +81,6 @@ func NewTagStore(path string, cfg *TagStoreConfig) (*TagStore, error) { pushingPool: make(map[string]chan struct{}), registryService: cfg.Registry, eventsService: cfg.Events, - trustService: cfg.Trust, } // Load the json file if it exists, otherwise create it. if err := store.reload(); os.IsNotExist(err) { diff --git a/graph/tags_unit_test.go b/graph/tags_unit_test.go index 32e9246036..c5f2ed11c8 100644 --- a/graph/tags_unit_test.go +++ b/graph/tags_unit_test.go @@ -12,7 +12,6 @@ import ( "github.com/docker/docker/daemon/graphdriver" _ "github.com/docker/docker/daemon/graphdriver/vfs" // import the vfs driver so it is used in the tests "github.com/docker/docker/image" - "github.com/docker/docker/trust" "github.com/docker/docker/utils" ) @@ -62,15 +61,9 @@ func mkTestTagStore(root string, t *testing.T) *TagStore { t.Fatal(err) } - trust, err := trust.NewTrustStore(root + "/trust") - if err != nil { - t.Fatal(err) - } - tagCfg := &TagStoreConfig{ Graph: graph, Events: events.New(), - Trust: trust, } store, err := NewTagStore(path.Join(root, "tags"), tagCfg) if err != nil { diff --git a/trust/service.go b/trust/service.go deleted file mode 100644 index 6a804faf52..0000000000 --- a/trust/service.go +++ /dev/null @@ -1,53 +0,0 @@ -package trust - -import ( - "fmt" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/libtrust" -) - -type NotVerifiedError string - -func (e NotVerifiedError) Error() string { - return string(e) -} - -func (t *TrustStore) CheckKey(ns string, key []byte, perm uint16) (bool, error) { - if len(key) == 0 { - return false, fmt.Errorf("Missing PublicKey") - } - pk, err := libtrust.UnmarshalPublicKeyJWK(key) - if err != nil { - return false, fmt.Errorf("Error unmarshalling public key: %v", err) - } - - if perm == 0 { - perm = 0x03 - } - - t.RLock() - defer t.RUnlock() - if t.graph == nil { - return false, NotVerifiedError("no graph") - } - - // Check if any expired grants - verified, err := t.graph.Verify(pk, ns, perm) - if err != nil { - return false, fmt.Errorf("Error verifying key to namespace: %s", ns) - } - if !verified { - logrus.Debugf("Verification failed for %s using key %s", ns, pk.KeyID()) - return false, NotVerifiedError("not verified") - } - if t.expiration.Before(time.Now()) { - return false, NotVerifiedError("expired") - } - return true, nil -} - -func (t *TrustStore) UpdateBase() { - t.fetch() -} diff --git a/trust/trusts.go b/trust/trusts.go deleted file mode 100644 index 885127ee5d..0000000000 --- a/trust/trusts.go +++ /dev/null @@ -1,195 +0,0 @@ -package trust - -import ( - "crypto/x509" - "errors" - "io/ioutil" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "sync" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/libtrust/trustgraph" -) - -type TrustStore struct { - path string - caPool *x509.CertPool - graph trustgraph.TrustGraph - expiration time.Time - fetcher *time.Timer - fetchTime time.Duration - autofetch bool - httpClient *http.Client - baseEndpoints map[string]*url.URL - - sync.RWMutex -} - -// defaultFetchtime represents the starting duration to wait between -// fetching sections of the graph. Unsuccessful fetches should -// increase time between fetching. -const defaultFetchtime = 45 * time.Second - -var baseEndpoints = map[string]string{"official": "https://dvjy3tqbc323p.cloudfront.net/trust/official.json"} - -func NewTrustStore(path string) (*TrustStore, error) { - abspath, err := filepath.Abs(path) - if err != nil { - return nil, err - } - - // Create base graph url map - endpoints := map[string]*url.URL{} - for name, endpoint := range baseEndpoints { - u, err := url.Parse(endpoint) - if err != nil { - return nil, err - } - endpoints[name] = u - } - - // Load grant files - t := &TrustStore{ - path: abspath, - caPool: nil, - httpClient: &http.Client{}, - fetchTime: time.Millisecond, - baseEndpoints: endpoints, - } - - if err := t.reload(); err != nil { - return nil, err - } - - return t, nil -} - -func (t *TrustStore) reload() error { - t.Lock() - defer t.Unlock() - - matches, err := filepath.Glob(filepath.Join(t.path, "*.json")) - if err != nil { - return err - } - statements := make([]*trustgraph.Statement, len(matches)) - for i, match := range matches { - f, err := os.Open(match) - if err != nil { - return err - } - statements[i], err = trustgraph.LoadStatement(f, nil) - if err != nil { - f.Close() - return err - } - f.Close() - } - if len(statements) == 0 { - if t.autofetch { - logrus.Debugf("No grants, fetching") - t.fetcher = time.AfterFunc(t.fetchTime, t.fetch) - } - return nil - } - - grants, expiration, err := trustgraph.CollapseStatements(statements, true) - if err != nil { - return err - } - - t.expiration = expiration - t.graph = trustgraph.NewMemoryGraph(grants) - logrus.Debugf("Reloaded graph with %d grants expiring at %s", len(grants), expiration) - - if t.autofetch { - nextFetch := expiration.Sub(time.Now()) - if nextFetch < 0 { - nextFetch = defaultFetchtime - } else { - nextFetch = time.Duration(0.8 * (float64)(nextFetch)) - } - t.fetcher = time.AfterFunc(nextFetch, t.fetch) - } - - return nil -} - -func (t *TrustStore) fetchBaseGraph(u *url.URL) (*trustgraph.Statement, error) { - req := &http.Request{ - Method: "GET", - URL: u, - Proto: "HTTP/1.1", - ProtoMajor: 1, - ProtoMinor: 1, - Header: make(http.Header), - Body: nil, - Host: u.Host, - } - - resp, err := t.httpClient.Do(req) - if err != nil { - return nil, err - } - if resp.StatusCode == 404 { - return nil, errors.New("base graph does not exist") - } - - defer resp.Body.Close() - - return trustgraph.LoadStatement(resp.Body, t.caPool) -} - -// fetch retrieves updated base graphs. This function cannot error, it -// should only log errors -func (t *TrustStore) fetch() { - t.Lock() - defer t.Unlock() - - if t.autofetch && t.fetcher == nil { - // Do nothing ?? - return - } - - fetchCount := 0 - for bg, ep := range t.baseEndpoints { - statement, err := t.fetchBaseGraph(ep) - if err != nil { - logrus.Infof("Trust graph fetch failed: %s", err) - continue - } - b, err := statement.Bytes() - if err != nil { - logrus.Infof("Bad trust graph statement: %s", err) - continue - } - // TODO check if value differs - if err := ioutil.WriteFile(path.Join(t.path, bg+".json"), b, 0600); err != nil { - logrus.Infof("Error writing trust graph statement: %s", err) - } - fetchCount++ - } - logrus.Debugf("Fetched %d base graphs at %s", fetchCount, time.Now()) - - if fetchCount > 0 { - go func() { - if err := t.reload(); err != nil { - logrus.Infof("Reload of trust graph failed: %s", err) - } - }() - t.fetchTime = defaultFetchtime - t.fetcher = nil - } else if t.autofetch { - maxTime := 10 * defaultFetchtime - t.fetchTime = time.Duration(1.5 * (float64)(t.fetchTime+time.Second)) - if t.fetchTime > maxTime { - t.fetchTime = maxTime - } - t.fetcher = time.AfterFunc(t.fetchTime, t.fetch) - } -} diff --git a/vendor/src/github.com/docker/libtrust/trustgraph/graph.go b/vendor/src/github.com/docker/libtrust/trustgraph/graph.go deleted file mode 100644 index 72b0fc3664..0000000000 --- a/vendor/src/github.com/docker/libtrust/trustgraph/graph.go +++ /dev/null @@ -1,50 +0,0 @@ -package trustgraph - -import "github.com/docker/libtrust" - -// TrustGraph represents a graph of authorization mapping -// public keys to nodes and grants between nodes. -type TrustGraph interface { - // Verifies that the given public key is allowed to perform - // the given action on the given node according to the trust - // graph. - Verify(libtrust.PublicKey, string, uint16) (bool, error) - - // GetGrants returns an array of all grant chains which are used to - // allow the requested permission. - GetGrants(libtrust.PublicKey, string, uint16) ([][]*Grant, error) -} - -// Grant represents a transfer of permission from one part of the -// trust graph to another. This is the only way to delegate -// permission between two different sub trees in the graph. -type Grant struct { - // Subject is the namespace being granted - Subject string - - // Permissions is a bit map of permissions - Permission uint16 - - // Grantee represents the node being granted - // a permission scope. The grantee can be - // either a namespace item or a key id where namespace - // items will always start with a '/'. - Grantee string - - // statement represents the statement used to create - // this object. - statement *Statement -} - -// Permissions -// Read node 0x01 (can read node, no sub nodes) -// Write node 0x02 (can write to node object, cannot create subnodes) -// Read subtree 0x04 (delegates read to each sub node) -// Write subtree 0x08 (delegates write to each sub node, included create on the subject) -// -// Permission shortcuts -// ReadItem = 0x01 -// WriteItem = 0x03 -// ReadAccess = 0x07 -// WriteAccess = 0x0F -// Delegate = 0x0F diff --git a/vendor/src/github.com/docker/libtrust/trustgraph/memory_graph.go b/vendor/src/github.com/docker/libtrust/trustgraph/memory_graph.go deleted file mode 100644 index 247bfa7aa6..0000000000 --- a/vendor/src/github.com/docker/libtrust/trustgraph/memory_graph.go +++ /dev/null @@ -1,133 +0,0 @@ -package trustgraph - -import ( - "strings" - - "github.com/docker/libtrust" -) - -type grantNode struct { - grants []*Grant - children map[string]*grantNode -} - -type memoryGraph struct { - roots map[string]*grantNode -} - -func newGrantNode() *grantNode { - return &grantNode{ - grants: []*Grant{}, - children: map[string]*grantNode{}, - } -} - -// NewMemoryGraph returns a new in memory trust graph created from -// a static list of grants. This graph is immutable after creation -// and any alterations should create a new instance. -func NewMemoryGraph(grants []*Grant) TrustGraph { - roots := map[string]*grantNode{} - for _, grant := range grants { - parts := strings.Split(grant.Grantee, "/") - nodes := roots - var node *grantNode - var nodeOk bool - for _, part := range parts { - node, nodeOk = nodes[part] - if !nodeOk { - node = newGrantNode() - nodes[part] = node - } - if part != "" { - node.grants = append(node.grants, grant) - } - nodes = node.children - } - } - return &memoryGraph{roots} -} - -func (g *memoryGraph) getGrants(name string) []*Grant { - nameParts := strings.Split(name, "/") - nodes := g.roots - var node *grantNode - var nodeOk bool - for _, part := range nameParts { - node, nodeOk = nodes[part] - if !nodeOk { - return nil - } - nodes = node.children - } - return node.grants -} - -func isSubName(name, sub string) bool { - if strings.HasPrefix(name, sub) { - if len(name) == len(sub) || name[len(sub)] == '/' { - return true - } - } - return false -} - -type walkFunc func(*Grant, []*Grant) bool - -func foundWalkFunc(*Grant, []*Grant) bool { - return true -} - -func (g *memoryGraph) walkGrants(start, target string, permission uint16, f walkFunc, chain []*Grant, visited map[*Grant]bool, collect bool) bool { - if visited == nil { - visited = map[*Grant]bool{} - } - grants := g.getGrants(start) - subGrants := make([]*Grant, 0, len(grants)) - for _, grant := range grants { - if visited[grant] { - continue - } - visited[grant] = true - if grant.Permission&permission == permission { - if isSubName(target, grant.Subject) { - if f(grant, chain) { - return true - } - } else { - subGrants = append(subGrants, grant) - } - } - } - for _, grant := range subGrants { - var chainCopy []*Grant - if collect { - chainCopy = make([]*Grant, len(chain)+1) - copy(chainCopy, chain) - chainCopy[len(chainCopy)-1] = grant - } else { - chainCopy = nil - } - - if g.walkGrants(grant.Subject, target, permission, f, chainCopy, visited, collect) { - return true - } - } - return false -} - -func (g *memoryGraph) Verify(key libtrust.PublicKey, node string, permission uint16) (bool, error) { - return g.walkGrants(key.KeyID(), node, permission, foundWalkFunc, nil, nil, false), nil -} - -func (g *memoryGraph) GetGrants(key libtrust.PublicKey, node string, permission uint16) ([][]*Grant, error) { - grants := [][]*Grant{} - collect := func(grant *Grant, chain []*Grant) bool { - grantChain := make([]*Grant, len(chain)+1) - copy(grantChain, chain) - grantChain[len(grantChain)-1] = grant - grants = append(grants, grantChain) - return false - } - g.walkGrants(key.KeyID(), node, permission, collect, nil, nil, true) - return grants, nil -} diff --git a/vendor/src/github.com/docker/libtrust/trustgraph/statement.go b/vendor/src/github.com/docker/libtrust/trustgraph/statement.go deleted file mode 100644 index 7a74b553cd..0000000000 --- a/vendor/src/github.com/docker/libtrust/trustgraph/statement.go +++ /dev/null @@ -1,227 +0,0 @@ -package trustgraph - -import ( - "crypto/x509" - "encoding/json" - "io" - "io/ioutil" - "sort" - "strings" - "time" - - "github.com/docker/libtrust" -) - -type jsonGrant struct { - Subject string `json:"subject"` - Permission uint16 `json:"permission"` - Grantee string `json:"grantee"` -} - -type jsonRevocation struct { - Subject string `json:"subject"` - Revocation uint16 `json:"revocation"` - Grantee string `json:"grantee"` -} - -type jsonStatement struct { - Revocations []*jsonRevocation `json:"revocations"` - Grants []*jsonGrant `json:"grants"` - Expiration time.Time `json:"expiration"` - IssuedAt time.Time `json:"issuedAt"` -} - -func (g *jsonGrant) Grant(statement *Statement) *Grant { - return &Grant{ - Subject: g.Subject, - Permission: g.Permission, - Grantee: g.Grantee, - statement: statement, - } -} - -// Statement represents a set of grants made from a verifiable -// authority. A statement has an expiration associated with it -// set by the authority. -type Statement struct { - jsonStatement - - signature *libtrust.JSONSignature -} - -// IsExpired returns whether the statement has expired -func (s *Statement) IsExpired() bool { - return s.Expiration.Before(time.Now().Add(-10 * time.Second)) -} - -// Bytes returns an indented json representation of the statement -// in a byte array. This value can be written to a file or stream -// without alteration. -func (s *Statement) Bytes() ([]byte, error) { - return s.signature.PrettySignature("signatures") -} - -// LoadStatement loads and verifies a statement from an input stream. -func LoadStatement(r io.Reader, authority *x509.CertPool) (*Statement, error) { - b, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - js, err := libtrust.ParsePrettySignature(b, "signatures") - if err != nil { - return nil, err - } - payload, err := js.Payload() - if err != nil { - return nil, err - } - var statement Statement - err = json.Unmarshal(payload, &statement.jsonStatement) - if err != nil { - return nil, err - } - - if authority == nil { - _, err = js.Verify() - if err != nil { - return nil, err - } - } else { - _, err = js.VerifyChains(authority) - if err != nil { - return nil, err - } - } - statement.signature = js - - return &statement, nil -} - -// CreateStatements creates and signs a statement from a stream of grants -// and revocations in a JSON array. -func CreateStatement(grants, revocations io.Reader, expiration time.Duration, key libtrust.PrivateKey, chain []*x509.Certificate) (*Statement, error) { - var statement Statement - err := json.NewDecoder(grants).Decode(&statement.jsonStatement.Grants) - if err != nil { - return nil, err - } - err = json.NewDecoder(revocations).Decode(&statement.jsonStatement.Revocations) - if err != nil { - return nil, err - } - statement.jsonStatement.Expiration = time.Now().UTC().Add(expiration) - statement.jsonStatement.IssuedAt = time.Now().UTC() - - b, err := json.MarshalIndent(&statement.jsonStatement, "", " ") - if err != nil { - return nil, err - } - - statement.signature, err = libtrust.NewJSONSignature(b) - if err != nil { - return nil, err - } - err = statement.signature.SignWithChain(key, chain) - if err != nil { - return nil, err - } - - return &statement, nil -} - -type statementList []*Statement - -func (s statementList) Len() int { - return len(s) -} - -func (s statementList) Less(i, j int) bool { - return s[i].IssuedAt.Before(s[j].IssuedAt) -} - -func (s statementList) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// CollapseStatements returns a single list of the valid statements as well as the -// time when the next grant will expire. -func CollapseStatements(statements []*Statement, useExpired bool) ([]*Grant, time.Time, error) { - sorted := make(statementList, 0, len(statements)) - for _, statement := range statements { - if useExpired || !statement.IsExpired() { - sorted = append(sorted, statement) - } - } - sort.Sort(sorted) - - var minExpired time.Time - var grantCount int - roots := map[string]*grantNode{} - for i, statement := range sorted { - if statement.Expiration.Before(minExpired) || i == 0 { - minExpired = statement.Expiration - } - for _, grant := range statement.Grants { - parts := strings.Split(grant.Grantee, "/") - nodes := roots - g := grant.Grant(statement) - grantCount = grantCount + 1 - - for _, part := range parts { - node, nodeOk := nodes[part] - if !nodeOk { - node = newGrantNode() - nodes[part] = node - } - node.grants = append(node.grants, g) - nodes = node.children - } - } - - for _, revocation := range statement.Revocations { - parts := strings.Split(revocation.Grantee, "/") - nodes := roots - - var node *grantNode - var nodeOk bool - for _, part := range parts { - node, nodeOk = nodes[part] - if !nodeOk { - break - } - nodes = node.children - } - if node != nil { - for _, grant := range node.grants { - if isSubName(grant.Subject, revocation.Subject) { - grant.Permission = grant.Permission &^ revocation.Revocation - } - } - } - } - } - - retGrants := make([]*Grant, 0, grantCount) - for _, rootNodes := range roots { - retGrants = append(retGrants, rootNodes.grants...) - } - - return retGrants, minExpired, nil -} - -// FilterStatements filters the statements to statements including the given grants. -func FilterStatements(grants []*Grant) ([]*Statement, error) { - statements := map[*Statement]bool{} - for _, grant := range grants { - if grant.statement != nil { - statements[grant.statement] = true - } - } - retStatements := make([]*Statement, len(statements)) - var i int - for statement := range statements { - retStatements[i] = statement - i++ - } - return retStatements, nil -}