From e9ad2d0481c09a4fe3cae8b0e299ffe91ead19d5 Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Thu, 9 Aug 2018 18:59:41 +0000 Subject: [PATCH] Update cri to v1.11.1. Signed-off-by: Lantao Liu --- vendor.conf | 2 +- .../containerd/cri/pkg/config/config.go | 31 +- .../cri/pkg/containerd/resolver/auth.go | 202 ------ .../cri/pkg/containerd/resolver/fetcher.go | 172 ----- .../pkg/containerd/resolver/httpreadseeker.go | 148 ----- .../cri/pkg/containerd/resolver/resolver.go | 622 ------------------ .../cri/pkg/containerd/resolver/scope.go | 80 --- .../cri/pkg/containerd/resolver/status.go | 71 -- .../cri/pkg/server/container_start.go | 6 +- .../containerd/cri/pkg/server/helpers.go | 10 + .../containerd/cri/pkg/server/image_pull.go | 71 +- .../containerd/cri/pkg/server/sandbox_run.go | 26 +- vendor/github.com/containerd/cri/vendor.conf | 20 +- 13 files changed, 126 insertions(+), 1335 deletions(-) delete mode 100644 vendor/github.com/containerd/cri/pkg/containerd/resolver/auth.go delete mode 100644 vendor/github.com/containerd/cri/pkg/containerd/resolver/fetcher.go delete mode 100644 vendor/github.com/containerd/cri/pkg/containerd/resolver/httpreadseeker.go delete mode 100644 vendor/github.com/containerd/cri/pkg/containerd/resolver/resolver.go delete mode 100644 vendor/github.com/containerd/cri/pkg/containerd/resolver/scope.go delete mode 100644 vendor/github.com/containerd/cri/pkg/containerd/resolver/status.go diff --git a/vendor.conf b/vendor.conf index 99f3b7b16..84db92d03 100644 --- a/vendor.conf +++ b/vendor.conf @@ -43,7 +43,7 @@ gotest.tools v2.1.0 github.com/google/go-cmp v0.1.0 # cri dependencies -github.com/containerd/cri 661f3b0377db409fe0e5677115f02ce7b89fd17d https://github.com/dmcgowan/cri-containerd +github.com/containerd/cri v1.11.1 github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534 github.com/blang/semver v3.1.0 github.com/containernetworking/cni v0.6.0 diff --git a/vendor/github.com/containerd/cri/pkg/config/config.go b/vendor/github.com/containerd/cri/pkg/config/config.go index 8ec2be834..6919ce6b8 100644 --- a/vendor/github.com/containerd/cri/pkg/config/config.go +++ b/vendor/github.com/containerd/cri/pkg/config/config.go @@ -37,6 +37,8 @@ type ContainerdConfig struct { DefaultRuntime Runtime `toml:"default_runtime" json:"defaultRuntime"` // UntrustedWorkloadRuntime is a runtime to run untrusted workloads on it. UntrustedWorkloadRuntime Runtime `toml:"untrusted_workload_runtime" json:"untrustedWorkloadRuntime"` + // NoPivot disables pivot-root (linux only), required when running a container in a RamDisk with runc + NoPivot bool `toml:"no_pivot" json:"noPivot"` } // CniConfig contains toml config related to cni @@ -61,16 +63,32 @@ type CniConfig struct { // Mirror contains the config related to the registry mirror type Mirror struct { // Endpoints are endpoints for a namespace. CRI plugin will try the endpoints - // one by one until a working one is found. + // one by one until a working one is found. The endpoint must be a valid url + // with host specified. Endpoints []string `toml:"endpoint" json:"endpoint"` - // TODO (Abhi) We might need to add auth per namespace. Looks like - // image auth information is passed by kube itself. +} + +// AuthConfig contains the config related to authentication to a specific registry +type AuthConfig struct { + // Username is the username to login the registry. + Username string `toml:"username" json:"username"` + // Password is the password to login the registry. + Password string `toml:"password" json:"password"` + // Auth is a base64 encoded string from the concatenation of the username, + // a colon, and the password. + Auth string `toml:"auth" json:"auth"` + // IdentityToken is used to authenticate the user and get + // an access token for the registry. + IdentityToken string `toml:"identitytoken" json:"identitytoken"` } // Registry is registry settings configured type Registry struct { // Mirrors are namespace to mirror mapping for all namespaces. Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"` + // Auths are registry endpoint to auth config mapping. The registry endpoint must + // be a valid url with host specified. + Auths map[string]AuthConfig `toml:"auths" json:"auths"` } // PluginConfig contains toml config related to CRI plugin, @@ -81,7 +99,7 @@ type PluginConfig struct { // CniConfig contains config related to cni CniConfig `toml:"cni" json:"cni"` // Registry contains config related to the registry - Registry `toml:"registry" json:"registry"` + Registry Registry `toml:"registry" json:"registry"` // StreamServerAddress is the ip address streaming server is listening on. StreamServerAddress string `toml:"stream_server_address" json:"streamServerAddress"` // StreamServerPort is the port streaming server is listening on. @@ -132,9 +150,10 @@ func DefaultConfig() PluginConfig { Engine: "", Root: "", }, + NoPivot: false, }, - StreamServerAddress: "", - StreamServerPort: "10010", + StreamServerAddress: "127.0.0.1", + StreamServerPort: "0", EnableSelinux: false, EnableTLSStreaming: false, SandboxImage: "k8s.gcr.io/pause:3.1", diff --git a/vendor/github.com/containerd/cri/pkg/containerd/resolver/auth.go b/vendor/github.com/containerd/cri/pkg/containerd/resolver/auth.go deleted file mode 100644 index 15d406a93..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/resolver/auth.go +++ /dev/null @@ -1,202 +0,0 @@ -/* -Copyright 2018 The Containerd Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// The corresponding file is in containerd/remote/docker/ -// This package can be removed once a more feasible and hollistic resolver -// is finalized in containerd. - -package resolver - -import ( - "net/http" - "sort" - "strings" -) - -type authenticationScheme byte - -const ( - basicAuth authenticationScheme = 1 << iota // Defined in RFC 7617 - digestAuth // Defined in RFC 7616 - bearerAuth // Defined in RFC 6750 -) - -// challenge carries information from a WWW-Authenticate response header. -// See RFC 2617. -type challenge struct { - // scheme is the auth-scheme according to RFC 2617 - scheme authenticationScheme - - // parameters are the auth-params according to RFC 2617 - parameters map[string]string -} - -type byScheme []challenge - -func (bs byScheme) Len() int { return len(bs) } -func (bs byScheme) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] } - -// Sort in priority order: token > digest > basic -func (bs byScheme) Less(i, j int) bool { return bs[i].scheme > bs[j].scheme } - -// Octet types from RFC 2616. -type octetType byte - -var octetTypes [256]octetType - -const ( - isToken octetType = 1 << iota - isSpace -) - -func init() { - // OCTET = - // CHAR = - // CTL = - // CR = - // LF = - // SP = - // HT = - // <"> = - // CRLF = CR LF - // LWS = [CRLF] 1*( SP | HT ) - // TEXT = - // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT - // token = 1* - // qdtext = > - - for c := 0; c < 256; c++ { - var t octetType - isCtl := c <= 31 || c == 127 - isChar := 0 <= c && c <= 127 - isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) - if strings.ContainsRune(" \t\r\n", rune(c)) { - t |= isSpace - } - if isChar && !isCtl && !isSeparator { - t |= isToken - } - octetTypes[c] = t - } -} - -func parseAuthHeader(header http.Header) []challenge { - challenges := []challenge{} - for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] { - v, p := parseValueAndParams(h) - var s authenticationScheme - switch v { - case "basic": - s = basicAuth - case "digest": - s = digestAuth - case "bearer": - s = bearerAuth - default: - continue - } - challenges = append(challenges, challenge{scheme: s, parameters: p}) - } - sort.Stable(byScheme(challenges)) - return challenges -} - -func parseValueAndParams(header string) (value string, params map[string]string) { - params = make(map[string]string) - value, s := expectToken(header) - if value == "" { - return - } - value = strings.ToLower(value) - for { - var pkey string - pkey, s = expectToken(skipSpace(s)) - if pkey == "" { - return - } - if !strings.HasPrefix(s, "=") { - return - } - var pvalue string - pvalue, s = expectTokenOrQuoted(s[1:]) - if pvalue == "" { - return - } - pkey = strings.ToLower(pkey) - params[pkey] = pvalue - s = skipSpace(s) - if !strings.HasPrefix(s, ",") { - return - } - s = s[1:] - } -} - -func skipSpace(s string) (rest string) { - i := 0 - for ; i < len(s); i++ { - if octetTypes[s[i]]&isSpace == 0 { - break - } - } - return s[i:] -} - -func expectToken(s string) (token, rest string) { - i := 0 - for ; i < len(s); i++ { - if octetTypes[s[i]]&isToken == 0 { - break - } - } - return s[:i], s[i:] -} - -func expectTokenOrQuoted(s string) (value string, rest string) { - if !strings.HasPrefix(s, "\"") { - return expectToken(s) - } - s = s[1:] - for i := 0; i < len(s); i++ { - switch s[i] { - case '"': - return s[:i], s[i+1:] - case '\\': - p := make([]byte, len(s)-1) - j := copy(p, s[:i]) - escape := true - for i = i + 1; i < len(s); i++ { - b := s[i] - switch { - case escape: - escape = false - p[j] = b - j++ - case b == '\\': - escape = true - case b == '"': - return string(p[:j]), s[i+1:] - default: - p[j] = b - j++ - } - } - return "", "" - } - } - return "", "" -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/resolver/fetcher.go b/vendor/github.com/containerd/cri/pkg/containerd/resolver/fetcher.go deleted file mode 100644 index 4e01c3c4b..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/resolver/fetcher.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2018 The Containerd Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// The corresponding file is in containerd/remote/docker/ -// This package can be removed once a more feasible and hollistic resolver -// is finalized in containerd. - -package resolver - -import ( - "context" - "fmt" - "io" - "io/ioutil" - "net/http" - "path" - "strings" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/log" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -type dockerFetcher struct { - *dockerBase -} - -func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) { - var bases []string - for _, b := range r.base { - bases = append(bases, b.String()) - } - ctx = log.WithLogger(ctx, log.G(ctx).WithFields( - logrus.Fields{ - "base": bases, - "digest": desc.Digest, - }, - )) - - urls, err := r.getV2URLPaths(ctx, desc) - if err != nil { - return nil, err - } - - ctx, err = contextWithRepositoryScope(ctx, r.refspec, false) - if err != nil { - return nil, err - } - - return newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) { - for _, u := range urls { - rc, err := r.open(ctx, u, desc.MediaType, offset) - if err != nil { - if errdefs.IsNotFound(err) { - continue // try one of the other urls. - } - - return nil, err - } - - return rc, nil - } - - return nil, errors.Wrapf(errdefs.ErrNotFound, - "could not fetch content descriptor %v (%v) from remote", - desc.Digest, desc.MediaType) - - }) -} - -func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int64) (io.ReadCloser, error) { - req, err := http.NewRequest(http.MethodGet, u, nil) - if err != nil { - return nil, err - } - - req.Header.Set("Accept", strings.Join([]string{mediatype, `*`}, ", ")) - - if offset > 0 { - // Note: "Accept-Ranges: bytes" cannot be trusted as some endpoints - // will return the header without supporting the range. The content - // range must always be checked. - req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset)) - } - - resp, err := r.doRequestWithRetries(ctx, req, nil) - if err != nil { - return nil, err - } - - if resp.StatusCode > 299 { - // TODO(stevvooe): When doing a offset specific request, we should - // really distinguish between a 206 and a 200. In the case of 200, we - // can discard the bytes, hiding the seek behavior from the - // implementation. - - resp.Body.Close() - if resp.StatusCode == http.StatusNotFound { - return nil, errors.Wrapf(errdefs.ErrNotFound, "content at %v not found", u) - } - return nil, errors.Errorf("unexpected status code %v: %v", u, resp.Status) - } - if offset > 0 { - cr := resp.Header.Get("content-range") - if cr != "" { - if !strings.HasPrefix(cr, fmt.Sprintf("bytes %d-", offset)) { - return nil, errors.Errorf("unhandled content range in response: %v", cr) - - } - } else { - // TODO: Should any cases where use of content range - // without the proper header be considerd? - // 206 responses? - - // Discard up to offset - // Could use buffer pool here but this case should be rare - n, err := io.Copy(ioutil.Discard, io.LimitReader(resp.Body, offset)) - if err != nil { - return nil, errors.Wrap(err, "failed to discard to offset") - } - if n != offset { - return nil, errors.Errorf("unable to discard to offset") - } - - } - } - - return resp.Body, nil -} - -// getV2URLPaths generates the candidate urls paths for the object based on the -// set of hints and the provided object id. URLs are returned in the order of -// most to least likely succeed. -func (r *dockerFetcher) getV2URLPaths(ctx context.Context, desc ocispec.Descriptor) ([]string, error) { - var urls []string - - if len(desc.URLs) > 0 { - // handle fetch via external urls. - for _, u := range desc.URLs { - log.G(ctx).WithField("url", u).Debug("adding alternative url") - urls = append(urls, u) - } - } - - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList, - images.MediaTypeDockerSchema1Manifest, - ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex: - urls = append(urls, r.urls(path.Join("manifests", desc.Digest.String()))...) - } - - // always fallback to attempting to get the object out of the blobs store. - urls = append(urls, r.urls(path.Join("blobs", desc.Digest.String()))...) - - return urls, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/resolver/httpreadseeker.go b/vendor/github.com/containerd/cri/pkg/containerd/resolver/httpreadseeker.go deleted file mode 100644 index 16af3d7e4..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/resolver/httpreadseeker.go +++ /dev/null @@ -1,148 +0,0 @@ -/* -Copyright 2018 The Containerd Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// The corresponding file is in containerd/remote/docker/. -// This package can be removed once a more feasible and hollistic resolver -// is finalized in containerd. - -package resolver - -import ( - "bytes" - "io" - "io/ioutil" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/pkg/errors" -) - -type httpReadSeeker struct { - size int64 - offset int64 - rc io.ReadCloser - open func(offset int64) (io.ReadCloser, error) - closed bool -} - -func newHTTPReadSeeker(size int64, open func(offset int64) (io.ReadCloser, error)) (io.ReadCloser, error) { - return &httpReadSeeker{ - size: size, - open: open, - }, nil -} - -func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) { - if hrs.closed { - return 0, io.EOF - } - - rd, err := hrs.reader() - if err != nil { - return 0, err - } - - n, err = rd.Read(p) - hrs.offset += int64(n) - return -} - -func (hrs *httpReadSeeker) Close() error { - if hrs.closed { - return nil - } - hrs.closed = true - if hrs.rc != nil { - return hrs.rc.Close() - } - - return nil -} - -func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) { - if hrs.closed { - return 0, errors.Wrap(errdefs.ErrUnavailable, "Fetcher.Seek: closed") - } - - abs := hrs.offset - switch whence { - case io.SeekStart: - abs = offset - case io.SeekCurrent: - abs += offset - case io.SeekEnd: - if hrs.size == -1 { - return 0, errors.Wrap(errdefs.ErrUnavailable, "Fetcher.Seek: unknown size, cannot seek from end") - } - abs = hrs.size + offset - default: - return 0, errors.Wrap(errdefs.ErrInvalidArgument, "Fetcher.Seek: invalid whence") - } - - if abs < 0 { - return 0, errors.Wrapf(errdefs.ErrInvalidArgument, "Fetcher.Seek: negative offset") - } - - if abs != hrs.offset { - if hrs.rc != nil { - if err := hrs.rc.Close(); err != nil { - log.L.WithError(err).Errorf("Fetcher.Seek: failed to close ReadCloser") - } - - hrs.rc = nil - } - - hrs.offset = abs - } - - return hrs.offset, nil -} - -func (hrs *httpReadSeeker) reader() (io.Reader, error) { - if hrs.rc != nil { - return hrs.rc, nil - } - - if hrs.size == -1 || hrs.offset < hrs.size { - // only try to reopen the body request if we are seeking to a value - // less than the actual size. - if hrs.open == nil { - return nil, errors.Wrapf(errdefs.ErrNotImplemented, "cannot open") - } - - rc, err := hrs.open(hrs.offset) - if err != nil { - return nil, errors.Wrapf(err, "httpReaderSeeker: failed open") - } - - if hrs.rc != nil { - if err := hrs.rc.Close(); err != nil { - log.L.WithError(err).Errorf("httpReadSeeker: failed to close ReadCloser") - } - } - hrs.rc = rc - } else { - // There is an edge case here where offset == size of the content. If - // we seek, we will probably get an error for content that cannot be - // sought (?). In that case, we should err on committing the content, - // as the length is already satisified but we just return the empty - // reader instead. - - hrs.rc = ioutil.NopCloser(bytes.NewReader([]byte{})) - } - - return hrs.rc, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/resolver/resolver.go b/vendor/github.com/containerd/cri/pkg/containerd/resolver/resolver.go deleted file mode 100644 index 3130b7876..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/resolver/resolver.go +++ /dev/null @@ -1,622 +0,0 @@ -/* -Copyright 2018 The Containerd Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package resolver - -import ( - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "path" - "strconv" - "strings" - "sync" - "time" - - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" - digest "github.com/opencontainers/go-digest" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context/ctxhttp" -) - -// This file is a modified copy of containerd/remote/docker/resolver.go. -// The changes carried over by this file includes support for image ref -// resolution and fetching image using multiple registry mirror urls. A new -// ResolverOption called Registry is added. Registry will contain a map -// of namespace relevant mirror urls. The client will use the ResolverOptions -// to set the urls associated with the namespace of the image reference. -// This package can be removed once a more feasible and hollistic resolver -// is finalized in containerd. The specific changes are made to the base -// function to calculate the base urls for the image location. urls() is -// added to fetch the mirror urls associated with the namespace of the image -// ResolverOptions are changed for client to set the namespace and mirror urls -// for to pull the image. - -var ( - // ErrNoToken is returned if a request is successful but the body does not - // contain an authorization token. - ErrNoToken = errors.New("authorization server did not include a token in the response") - - // ErrInvalidAuthorization is used when credentials are passed to a server but - // those credentials are rejected. - ErrInvalidAuthorization = errors.New("authorization failed") -) - -type containerdResolver struct { - credentials func(string) (string, string, error) - plainHTTP bool - client *http.Client - tracker StatusTracker - registry map[string][]string -} - -// Options are used to configured a new Docker register resolver -type Options struct { - // Credentials provides username and secret given a host. - // If username is empty but a secret is given, that secret - // is interpretted as a long lived token. - Credentials func(string) (string, string, error) - - // PlainHTTP specifies to use plain http and not https - PlainHTTP bool - - // Client is the http client to used when making registry requests - Client *http.Client - - // Tracker is used to track uploads to the registry. This is used - // since the registry does not have upload tracking and the existing - // mechanism for getting blob upload status is expensive. - Tracker StatusTracker - - Registry map[string][]string -} - -// NewResolver returns a new resolver to a Docker registry -func NewResolver(options Options) remotes.Resolver { - tracker := options.Tracker - if tracker == nil { - tracker = NewInMemoryTracker() - } - - return &containerdResolver{ - credentials: options.Credentials, - plainHTTP: options.PlainHTTP, - client: options.Client, - tracker: tracker, - registry: options.Registry, - } -} - -var _ remotes.Resolver = &containerdResolver{} - -func (r *containerdResolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) { - refspec, err := reference.Parse(ref) - if err != nil { - return "", ocispec.Descriptor{}, err - } - - if refspec.Object == "" { - return "", ocispec.Descriptor{}, reference.ErrObjectRequired - } - - base, err := r.base(refspec) - if err != nil { - return "", ocispec.Descriptor{}, err - } - - fetcher := dockerFetcher{ - dockerBase: base, - } - - var ( - urls []string - dgst = refspec.Digest() - ) - - if dgst != "" { - if err := dgst.Validate(); err != nil { - // need to fail here, since we can't actually resolve the invalid - // digest. - return "", ocispec.Descriptor{}, err - } - - // turns out, we have a valid digest, make a url. - urls = append(urls, fetcher.urls("manifests", dgst.String())...) - - // fallback to blobs on not found. - urls = append(urls, fetcher.urls("blobs", dgst.String())...) - } else { - urls = append(urls, fetcher.urls("manifests", refspec.Object)...) - } - - ctx, err = contextWithRepositoryScope(ctx, refspec, false) - if err != nil { - return "", ocispec.Descriptor{}, err - } - for _, u := range urls { - log.G(ctx).WithFields(logrus.Fields{ - "url": u, - }).Debug("Trying to fetch from url") - req, err := http.NewRequest(http.MethodHead, u, nil) - if err != nil { - return "", ocispec.Descriptor{}, err - } - - // set headers for all the types we support for resolution. - req.Header.Set("Accept", strings.Join([]string{ - images.MediaTypeDockerSchema2Manifest, - images.MediaTypeDockerSchema2ManifestList, - ocispec.MediaTypeImageManifest, - ocispec.MediaTypeImageIndex, "*"}, ", ")) - - log.G(ctx).Info("resolving") - resp, err := fetcher.doRequestWithRetries(ctx, req, nil) - if err != nil { - return "", ocispec.Descriptor{}, err - } - resp.Body.Close() // don't care about body contents. - - if resp.StatusCode > 299 { - if resp.StatusCode == http.StatusNotFound { - continue - } - return "", ocispec.Descriptor{}, errors.Errorf("unexpected status code %v: %v", u, resp.Status) - } - - // this is the only point at which we trust the registry. we use the - // content headers to assemble a descriptor for the name. when this becomes - // more robust, we mostly get this information from a secure trust store. - dgstHeader := digest.Digest(resp.Header.Get("Docker-Content-Digest")) - - if dgstHeader != "" { - if err := dgstHeader.Validate(); err != nil { - return "", ocispec.Descriptor{}, errors.Wrapf(err, "%q in header not a valid digest", dgstHeader) - } - dgst = dgstHeader - } - - if dgst == "" { - return "", ocispec.Descriptor{}, errors.Errorf("could not resolve digest for %v", ref) - } - - var ( - size int64 - sizeHeader = resp.Header.Get("Content-Length") - ) - - size, err = strconv.ParseInt(sizeHeader, 10, 64) - if err != nil { - - return "", ocispec.Descriptor{}, errors.Wrapf(err, "invalid size header: %q", sizeHeader) - } - if size < 0 { - return "", ocispec.Descriptor{}, errors.Errorf("%q in header not a valid size", sizeHeader) - } - - desc := ocispec.Descriptor{ - Digest: dgst, - MediaType: resp.Header.Get("Content-Type"), // need to strip disposition? - Size: size, - } - - log.G(ctx).WithField("desc.digest", desc.Digest).Debug("resolved") - return ref, desc, nil - } - - return "", ocispec.Descriptor{}, errors.Errorf("%v not found", ref) -} - -func (r *containerdResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) { - refspec, err := reference.Parse(ref) - if err != nil { - return nil, err - } - - base, err := r.base(refspec) - if err != nil { - return nil, err - } - - return dockerFetcher{ - dockerBase: base, - }, nil -} - -func (r *containerdResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) { - return nil, nil -} - -type dockerBase struct { - refspec reference.Spec - base []url.URL - - client *http.Client - useBasic bool - username, secret string - token string - mu sync.Mutex -} - -func (r *containerdResolver) base(refspec reference.Spec) (*dockerBase, error) { - var ( - err error - base []url.URL - username, secret string - ) - - host := refspec.Hostname() - prefix := strings.TrimPrefix(refspec.Locator, host+"/") - - if urls, ok := r.registry[host]; ok { - urls, err := r.getV2Urls(urls, prefix) - if err != nil { - return nil, errors.Wrap(err, "failed to fetch v2 urls") - } - base = append(base, urls...) - } else if host == "docker.io" { - base = append(base, []url.URL{{Host: "registry-1.docker.io", Scheme: "https", Path: path.Join("/v2", prefix)}}...) - } else { - scheme := "https" - if r.plainHTTP || strings.HasPrefix(host, "localhost:") { - scheme = "http" - } - base = append(base, []url.URL{{Host: host, Scheme: scheme, Path: path.Join("/v2", prefix)}}...) - } - - if r.credentials != nil { - username, secret, err = r.credentials(base[0].Host) - if err != nil { - return nil, err - } - } - - return &dockerBase{ - refspec: refspec, - base: base, - client: r.client, - username: username, - secret: secret, - }, nil -} - -func (r *dockerBase) getToken() string { - r.mu.Lock() - defer r.mu.Unlock() - - return r.token -} - -func (r *dockerBase) setToken(token string) bool { - r.mu.Lock() - defer r.mu.Unlock() - - changed := r.token != token - r.token = token - - return changed -} - -func (r *dockerBase) urls(ps ...string) []string { - urls := []string{} - for _, url := range r.base { - url.Path = path.Join(url.Path, path.Join(ps...)) - urls = append(urls, url.String()) - } - return urls -} - -func (r *dockerBase) authorize(req *http.Request) { - token := r.getToken() - if r.useBasic { - req.SetBasicAuth(r.username, r.secret) - } else if token != "" { - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) - } -} - -func (r *dockerBase) doRequest(ctx context.Context, req *http.Request) (*http.Response, error) { - ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", req.URL.String())) - log.G(ctx).WithField("request.headers", req.Header).WithField("request.method", req.Method).Debug("do request") - r.authorize(req) - resp, err := ctxhttp.Do(ctx, r.client, req) - if err != nil { - return nil, errors.Wrap(err, "failed to do request") - } - log.G(ctx).WithFields(logrus.Fields{ - "status": resp.Status, - "response.headers": resp.Header, - }).Debug("fetch response received") - return resp, nil -} - -func (r *dockerBase) doRequestWithRetries(ctx context.Context, req *http.Request, responses []*http.Response) (*http.Response, error) { - resp, err := r.doRequest(ctx, req) - if err != nil { - return nil, err - } - - responses = append(responses, resp) - req, err = r.retryRequest(ctx, req, responses) - if err != nil { - resp.Body.Close() - return nil, err - } - if req != nil { - resp.Body.Close() - return r.doRequestWithRetries(ctx, req, responses) - } - return resp, err -} - -func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, responses []*http.Response) (*http.Request, error) { - if len(responses) > 5 { - return nil, nil - } - last := responses[len(responses)-1] - if last.StatusCode == http.StatusUnauthorized { - log.G(ctx).WithField("header", last.Header.Get("WWW-Authenticate")).Debug("Unauthorized") - for _, c := range parseAuthHeader(last.Header) { - if c.scheme == bearerAuth { - if err := invalidAuthorization(c, responses); err != nil { - r.setToken("") - return nil, err - } - if err := r.setTokenAuth(ctx, c.parameters); err != nil { - return nil, err - } - return copyRequest(req) - } else if c.scheme == basicAuth { - if r.username != "" && r.secret != "" { - r.useBasic = true - } - return copyRequest(req) - } - } - return nil, nil - } else if last.StatusCode == http.StatusMethodNotAllowed && req.Method == http.MethodHead { - // Support registries which have not properly implemented the HEAD method for - // manifests endpoint - if strings.Contains(req.URL.Path, "/manifests/") { - // TODO: copy request? - req.Method = http.MethodGet - return copyRequest(req) - } - } - - // TODO: Handle 50x errors accounting for attempt history - return nil, nil -} - -func invalidAuthorization(c challenge, responses []*http.Response) error { - errStr := c.parameters["error"] - if errStr == "" { - return nil - } - - n := len(responses) - if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) { - return nil - } - - return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr) -} - -func sameRequest(r1, r2 *http.Request) bool { - if r1.Method != r2.Method { - return false - } - if *r1.URL != *r2.URL { - return false - } - return true -} - -func copyRequest(req *http.Request) (*http.Request, error) { - ireq := *req - if ireq.GetBody != nil { - var err error - ireq.Body, err = ireq.GetBody() - if err != nil { - return nil, err - } - } - return &ireq, nil -} - -func (r *dockerBase) setTokenAuth(ctx context.Context, params map[string]string) error { - realm, ok := params["realm"] - if !ok { - return errors.New("no realm specified for token auth challenge") - } - - realmURL, err := url.Parse(realm) - if err != nil { - return errors.Wrap(err, "invalid token auth challenge realm") - } - - to := tokenOptions{ - realm: realmURL.String(), - service: params["service"], - } - - to.scopes = getTokenScopes(ctx, params) - if len(to.scopes) == 0 { - return errors.New("no scope specified for token auth challenge") - } - - var token string - if r.secret != "" { - // Credential information is provided, use oauth POST endpoint - token, err = r.fetchTokenWithOAuth(ctx, to) - if err != nil { - return errors.Wrap(err, "failed to fetch oauth token") - } - } else { - // Do request anonymously - token, err = r.fetchToken(ctx, to) - if err != nil { - return errors.Wrap(err, "failed to fetch anonymous token") - } - } - r.setToken(token) - - return nil -} - -type tokenOptions struct { - realm string - service string - scopes []string -} - -type postTokenResponse struct { - AccessToken string `json:"access_token"` - RefreshToken string `json:"refresh_token"` - ExpiresIn int `json:"expires_in"` - IssuedAt time.Time `json:"issued_at"` - Scope string `json:"scope"` -} - -func (r *dockerBase) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) { - form := url.Values{} - form.Set("scope", strings.Join(to.scopes, " ")) - form.Set("service", to.service) - // TODO: Allow setting client_id - form.Set("client_id", "containerd-dist-tool") - - if r.username == "" { - form.Set("grant_type", "refresh_token") - form.Set("refresh_token", r.secret) - } else { - form.Set("grant_type", "password") - form.Set("username", r.username) - form.Set("password", r.secret) - } - - resp, err := ctxhttp.PostForm(ctx, r.client, to.realm, form) - if err != nil { - return "", err - } - defer resp.Body.Close() - - // Registries without support for POST may return 404 for POST /v2/token. - // As of September 2017, GCR is known to return 404. - if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 { - return r.fetchToken(ctx, to) - } else if resp.StatusCode < 200 || resp.StatusCode >= 400 { - b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB - log.G(ctx).WithFields(logrus.Fields{ - "status": resp.Status, - "body": string(b), - }).Debugf("token request failed") - // TODO: handle error body and write debug output - return "", errors.Errorf("unexpected status: %s", resp.Status) - } - - decoder := json.NewDecoder(resp.Body) - - var tr postTokenResponse - if err = decoder.Decode(&tr); err != nil { - return "", errors.Wrap(err, "unable to decode token response") - } - - return tr.AccessToken, nil -} - -type getTokenResponse struct { - Token string `json:"token"` - AccessToken string `json:"access_token"` - ExpiresIn int `json:"expires_in"` - IssuedAt time.Time `json:"issued_at"` - RefreshToken string `json:"refresh_token"` -} - -// fetchToken fetches a token using a GET request -func (r *dockerBase) fetchToken(ctx context.Context, to tokenOptions) (string, error) { - req, err := http.NewRequest("GET", to.realm, nil) - if err != nil { - return "", err - } - - reqParams := req.URL.Query() - - if to.service != "" { - reqParams.Add("service", to.service) - } - - for _, scope := range to.scopes { - reqParams.Add("scope", scope) - } - - if r.secret != "" { - req.SetBasicAuth(r.username, r.secret) - } - - req.URL.RawQuery = reqParams.Encode() - - resp, err := ctxhttp.Do(ctx, r.client, req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 400 { - // TODO: handle error body and write debug output - return "", errors.Errorf("unexpected status: %s", resp.Status) - } - - decoder := json.NewDecoder(resp.Body) - - var tr getTokenResponse - if err = decoder.Decode(&tr); err != nil { - return "", errors.Wrap(err, "unable to decode token response") - } - - // `access_token` is equivalent to `token` and if both are specified - // the choice is undefined. Canonicalize `access_token` by sticking - // things in `token`. - if tr.AccessToken != "" { - tr.Token = tr.AccessToken - } - - if tr.Token == "" { - return "", ErrNoToken - } - - return tr.Token, nil -} - -func (r *containerdResolver) getV2Urls(urls []string, imagePath string) ([]url.URL, error) { - v2Urls := []url.URL{} - for _, u := range urls { - v2Url, err := url.Parse(u) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse url during getv2 urls: %+v", u) - } - v2Url.Path = path.Join("/v2", imagePath) - v2Urls = append(v2Urls, *v2Url) - } - return v2Urls, nil -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/resolver/scope.go b/vendor/github.com/containerd/cri/pkg/containerd/resolver/scope.go deleted file mode 100644 index c8ced9179..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/resolver/scope.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2018 The Containerd Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// The corresponding file is in containerd/remote/docker/. -// This package can be removed once a more feasible and hollistic resolver -// is finalized in containerd. - -package resolver - -import ( - "context" - "net/url" - "sort" - "strings" - - "github.com/containerd/containerd/reference" -) - -// repositoryScope returns a repository scope string such as "repository:foo/bar:pull" -// for "host/foo/bar:baz". -// When push is true, both pull and push are added to the scope. -func repositoryScope(refspec reference.Spec, push bool) (string, error) { - u, err := url.Parse("dummy://" + refspec.Locator) - if err != nil { - return "", err - } - s := "repository:" + strings.TrimPrefix(u.Path, "/") + ":pull" - if push { - s += ",push" - } - return s, nil -} - -// tokenScopesKey is used for the key for context.WithValue(). -// value: []string (e.g. {"registry:foo/bar:pull"}) -type tokenScopesKey struct{} - -// contextWithRepositoryScope returns a context with tokenScopesKey{} and the repository scope value. -func contextWithRepositoryScope(ctx context.Context, refspec reference.Spec, push bool) (context.Context, error) { - s, err := repositoryScope(refspec, push) - if err != nil { - return nil, err - } - return context.WithValue(ctx, tokenScopesKey{}, []string{s}), nil -} - -// getTokenScopes returns deduplicated and sorted scopes from ctx.Value(tokenScopesKey{}) and params["scope"]. -func getTokenScopes(ctx context.Context, params map[string]string) []string { - var scopes []string - if x := ctx.Value(tokenScopesKey{}); x != nil { - scopes = append(scopes, x.([]string)...) - } - if scope, ok := params["scope"]; ok { - for _, s := range scopes { - // Note: this comparison is unaware of the scope grammar (https://docs.docker.com/registry/spec/auth/scope/) - // So, "repository:foo/bar:pull,push" != "repository:foo/bar:push,pull", although semantically they are equal. - if s == scope { - // already appended - goto Sort - } - } - scopes = append(scopes, scope) - } -Sort: - sort.Strings(scopes) - return scopes -} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/resolver/status.go b/vendor/github.com/containerd/cri/pkg/containerd/resolver/status.go deleted file mode 100644 index 5ffcdaec0..000000000 --- a/vendor/github.com/containerd/cri/pkg/containerd/resolver/status.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2018 The Containerd Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// The corresponding file is in containerd/remote/docker/. -// This package can be removed once a more feasible and hollistic resolver -// is finalized in containerd. - -package resolver - -import ( - "sync" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/pkg/errors" -) - -// Status of a content operation -type Status struct { - content.Status - - // UploadUUID is used by the Docker registry to reference blob uploads - UploadUUID string -} - -// StatusTracker to track status of operations -type StatusTracker interface { - GetStatus(string) (Status, error) - SetStatus(string, Status) -} - -type memoryStatusTracker struct { - statuses map[string]Status - m sync.Mutex -} - -// NewInMemoryTracker returns a StatusTracker that tracks content status in-memory -func NewInMemoryTracker() StatusTracker { - return &memoryStatusTracker{ - statuses: map[string]Status{}, - } -} - -func (t *memoryStatusTracker) GetStatus(ref string) (Status, error) { - t.m.Lock() - defer t.m.Unlock() - status, ok := t.statuses[ref] - if !ok { - return Status{}, errors.Wrapf(errdefs.ErrNotFound, "status for ref %v", ref) - } - return status, nil -} - -func (t *memoryStatusTracker) SetStatus(ref string, status Status) { - t.m.Lock() - t.statuses[ref] = status - t.m.Unlock() -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_start.go b/vendor/github.com/containerd/cri/pkg/server/container_start.go index ed4b8b43f..a4467c4bd 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_start.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_start.go @@ -108,7 +108,11 @@ func (c *criService) startContainer(ctx context.Context, return cntr.IO, nil } - task, err := container.NewTask(ctx, ioCreation) + var taskOpts []containerd.NewTaskOpts + if c.config.NoPivot { + taskOpts = append(taskOpts, containerd.WithNoPivotRoot) + } + task, err := container.NewTask(ctx, ioCreation, taskOpts...) if err != nil { return errors.Wrap(err, "failed to create containerd task") } diff --git a/vendor/github.com/containerd/cri/pkg/server/helpers.go b/vendor/github.com/containerd/cri/pkg/server/helpers.go index 5bfdb8205..29f2f9ba4 100644 --- a/vendor/github.com/containerd/cri/pkg/server/helpers.go +++ b/vendor/github.com/containerd/cri/pkg/server/helpers.go @@ -444,3 +444,13 @@ func getRuntimeConfigFromContainerInfo(c containers.Container) (criconfig.Runtim r.Root = runtimeOpts.RuntimeRoot return r, nil } + +// toRuntimeAuthConfig converts cri plugin auth config to runtime auth config. +func toRuntimeAuthConfig(a criconfig.AuthConfig) *runtime.AuthConfig { + return &runtime.AuthConfig{ + Username: a.Username, + Password: a.Password, + Auth: a.Auth, + IdentityToken: a.IdentityToken, + } +} diff --git a/vendor/github.com/containerd/cri/pkg/server/image_pull.go b/vendor/github.com/containerd/cri/pkg/server/image_pull.go index 67acddf0f..a25d8285e 100644 --- a/vendor/github.com/containerd/cri/pkg/server/image_pull.go +++ b/vendor/github.com/containerd/cri/pkg/server/image_pull.go @@ -19,18 +19,21 @@ package server import ( "encoding/base64" "net/http" + "net/url" "strings" "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" containerdimages "github.com/containerd/containerd/images" + "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/remotes/docker" imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" - containerdresolver "github.com/containerd/cri/pkg/containerd/resolver" imagestore "github.com/containerd/cri/pkg/store/image" "github.com/containerd/cri/pkg/util" ) @@ -87,12 +90,7 @@ func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest) if ref != imageRef { logrus.Debugf("PullImage using normalized image ref: %q", ref) } - resolver := containerdresolver.NewResolver(containerdresolver.Options{ - Credentials: func(string) (string, string, error) { return ParseAuth(r.GetAuth()) }, - Client: http.DefaultClient, - Registry: c.getResolverOptions(), - }) - _, desc, err := resolver.Resolve(ctx, ref) + resolver, desc, err := c.getResolver(ctx, ref, c.credentials(r.GetAuth())) if err != nil { return nil, errors.Wrapf(err, "failed to resolve image %q", ref) } @@ -206,10 +204,59 @@ func (c *criService) createImageReference(ctx context.Context, name string, desc return err } -func (c *criService) getResolverOptions() map[string][]string { - options := make(map[string][]string) - for ns, mirror := range c.config.Mirrors { - options[ns] = append(options[ns], mirror.Endpoints...) +// credentials returns a credential function for docker resolver to use. +func (c *criService) credentials(auth *runtime.AuthConfig) func(string) (string, string, error) { + return func(host string) (string, string, error) { + if auth == nil { + // Get default auth from config. + for h, ac := range c.config.Registry.Auths { + u, err := url.Parse(h) + if err != nil { + return "", "", errors.Wrapf(err, "parse auth host %q", h) + } + if u.Host == host { + auth = toRuntimeAuthConfig(ac) + break + } + } + } + return ParseAuth(auth) } - return options +} + +// getResolver tries registry mirrors and the default registry, and returns the resolver and descriptor +// from the first working registry. +func (c *criService) getResolver(ctx context.Context, ref string, cred func(string) (string, string, error)) (remotes.Resolver, imagespec.Descriptor, error) { + refspec, err := reference.Parse(ref) + if err != nil { + return nil, imagespec.Descriptor{}, errors.Wrap(err, "parse image reference") + } + // Try mirrors in order first, and then try default host name. + for _, e := range c.config.Registry.Mirrors[refspec.Hostname()].Endpoints { + u, err := url.Parse(e) + if err != nil { + return nil, imagespec.Descriptor{}, errors.Wrapf(err, "parse registry endpoint %q", e) + } + resolver := docker.NewResolver(docker.ResolverOptions{ + Credentials: cred, + Client: http.DefaultClient, + Host: func(string) (string, error) { return u.Host, nil }, + // By default use "https". + PlainHTTP: u.Scheme == "http", + }) + _, desc, err := resolver.Resolve(ctx, ref) + if err == nil { + return resolver, desc, nil + } + // Continue to try next endpoint + } + resolver := docker.NewResolver(docker.ResolverOptions{ + Credentials: cred, + Client: http.DefaultClient, + }) + _, desc, err := resolver.Resolve(ctx, ref) + if err != nil { + return nil, imagespec.Descriptor{}, errors.Wrap(err, "no available registry endpoint") + } + return resolver, desc, nil } diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go index c47b22670..38f763223 100644 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go +++ b/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go @@ -293,8 +293,13 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox // Create sandbox task in containerd. log.Tracef("Create sandbox container (id=%q, name=%q).", id, name) + + var taskOpts []containerd.NewTaskOpts + if c.config.NoPivot { + taskOpts = append(taskOpts, containerd.WithNoPivotRoot) + } // We don't need stdio for sandbox container. - task, err := container.NewTask(ctx, containerdio.NullIO) + task, err := container.NewTask(ctx, containerdio.NullIO, taskOpts...) if err != nil { return status, errors.Wrap(err, "failed to create containerd task") } @@ -578,13 +583,10 @@ func untrustedWorkload(config *runtime.PodSandboxConfig) bool { return config.GetAnnotations()[annotations.UntrustedWorkload] == "true" } -// hostPrivilegedSandbox returns true if the sandbox configuration -// requires additional host privileges for the sandbox. -func hostPrivilegedSandbox(config *runtime.PodSandboxConfig) bool { +// hostAccessingSandbox returns true if the sandbox configuration +// requires additional host access for the sandbox. +func hostAccessingSandbox(config *runtime.PodSandboxConfig) bool { securityContext := config.GetLinux().GetSecurityContext() - if securityContext.GetPrivileged() { - return true - } namespaceOptions := securityContext.GetNamespaceOptions() if namespaceOptions.GetNetwork() == runtime.NamespaceMode_NODE || @@ -602,9 +604,13 @@ func hostPrivilegedSandbox(config *runtime.PodSandboxConfig) bool { func (c *criService) getSandboxRuntime(config *runtime.PodSandboxConfig) (criconfig.Runtime, error) { untrusted := false if untrustedWorkload(config) { - // TODO(random-liu): Figure out we should return error or not. - if hostPrivilegedSandbox(config) { - return criconfig.Runtime{}, errors.New("untrusted workload with host privilege is not allowed") + // If the untrusted workload is requesting access to the host/node, this request will fail. + // + // Note: If the workload is marked untrusted but requests privileged, this can be granted, as the + // runtime may support this. For example, in a virtual-machine isolated runtime, privileged + // is a supported option, granting the workload to access the entire guest VM instead of host. + if hostAccessingSandbox(config) { + return criconfig.Runtime{}, errors.New("untrusted workload with host access is not allowed") } untrusted = true } diff --git a/vendor/github.com/containerd/cri/vendor.conf b/vendor/github.com/containerd/cri/vendor.conf index 521dc47f3..3d3a7a314 100644 --- a/vendor/github.com/containerd/cri/vendor.conf +++ b/vendor/github.com/containerd/cri/vendor.conf @@ -2,14 +2,15 @@ github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 github.com/blang/semver v3.1.0 github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 -github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130 -github.com/containerd/console 9290d21dc56074581f619579c43d970b4514bc08 -github.com/containerd/containerd 84bebdd91d347c99069d1705b7d4e6d6f746160c +github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 +github.com/containerd/console 4d8a41f4ce5b9bae77c41786ea2458330f43f081 +github.com/containerd/containerd b9eeaa1ce83dd9970605ddbd0b35d4d3fa5f87bd github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c -github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534 -github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5 -github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788 +github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534 +github.com/containerd/go-runc edcf3de1f4971445c42d61f20d506b30612aa031 +github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d +github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containernetworking/cni v0.6.0 github.com/containernetworking/plugins v0.7.0 github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6 @@ -35,12 +36,12 @@ github.com/json-iterator/go f2b4162afba35581b6d4a50d3b8f34e33c144682 github.com/matttproud/golang_protobuf_extensions v1.0.0 github.com/Microsoft/go-winio v0.4.7 github.com/Microsoft/hcsshim v0.6.11 -github.com/modern-go/reflect2 05fbef0ca5da472bbf96c9322b84a53edc03c9fd github.com/modern-go/concurrent 1.0.3 +github.com/modern-go/reflect2 05fbef0ca5da472bbf96c9322b84a53edc03c9fd github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340 -github.com/opencontainers/runtime-spec v1.0.1 +github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce github.com/opencontainers/runtime-tools v0.6.0 github.com/opencontainers/selinux 4a2974bf1ee960774ffd517717f1f45325af0206 github.com/pkg/errors v0.8.0 @@ -51,7 +52,6 @@ github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563 github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 github.com/sirupsen/logrus v1.0.0 -github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577 github.com/stretchr/testify v1.1.4 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc @@ -62,7 +62,7 @@ github.com/xeipuuv/gojsonschema 1d523034197ff1f222f6429836dd36a2457a1874 golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067 golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c -golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys +golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 https://github.com/golang/sys golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944