-
Notifications
You must be signed in to change notification settings - Fork 40k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate SHA/Tag when checking docker images #30366
Conversation
@@ -184,7 +185,27 @@ func (d *kubeDockerClient) InspectImage(image string) (*dockertypes.ImageInspect | |||
} | |||
return nil, err | |||
} | |||
return &resp, nil | |||
parts := strings.SplitN(image, ":", 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could probably reuse/share the logic in applyDefaultImageTag
kubernetes/pkg/kubelet/dockertools/docker.go
Line 161 in 9f1c3a4
_, isDigested := named.(dockerref.Digested) |
Could you add a unit test for this? Thanks! /cc @Random-Liu |
@yujuhong I don't see ANY tests for anything in this file !! |
That's not a very good reason to not add a test, is it? :-) The |
@yujuhong LOL, of course :) |
@@ -184,6 +184,10 @@ func (d *kubeDockerClient) InspectImage(image string) (*dockertypes.ImageInspect | |||
} | |||
return nil, err | |||
} | |||
if !matchImageTagOrSHA(resp, image) { | |||
err = imageNotFoundError{ID: image} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: just return nil, imageNotFoundError{ID: image}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// Check if the inspected image matches what we are looking for | ||
func matchImageTagOrSHA(inspected dockertypes.ImageInspect, image string) bool { | ||
parts := strings.SplitN(image, ":", 2) | ||
if len(parts) == 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reuse the same dockerref code for parsing the given string?
kubernetes/pkg/kubelet/dockertools/docker.go
Line 161 in 9f1c3a4
_, isDigested := named.(dockerref.Digested) |
|
Docker API does not validate the tag/sha, for example, all the following calls work say for a alpine image with short SHA "4e38e38c8ce0" echo -e "GET /images/alpine:4e38e38c8ce0/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock echo -e "GET /images/alpine:4e38e38c/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock echo -e "GET /images/alpine:4/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock So we should check the response from the Docker API and look for the tags or SHA explicitly. Fixes kubernetes#30355
GCE e2e build/test passed for commit 875fd16. |
@k8s-bot test this [submit-queue is verifying that this PR is safe to merge] |
GCE e2e build/test passed for commit 875fd16. |
Automatic merge from submit-queue |
It looks correct on the Red Hat 1.10 I have but I don't think it was supported in Docker 1.9. Did we make a formal statement that we dropped 1.9? |
I'm much less confident in RepoDigests being correct on every Docker variant version - probably couldn't say without trying a fair number of them. |
I just checked 1.9 on my desktop and it reported correct RepoDigest nonetheless:
|
Tomorrow I'll have someone look at the various 1.10 versions and make sure they're correct against schema 1.10. If i can prove that RepoDigest is correct I'll change the patch to prefer RepoDigests for a prefix match and then fall back to ID. The prefix match seemed slightly questionable, but I assume we validated there was no security risk in that? |
@smarterclayton thanks! Should we hold on to the PR #32627 for now until this is verified? |
The motivation of adding this check is because docker's image inspection syntax is too loose and may mix up tags and digests. This is merely a sanity check to make sure docker has the right image. What security risk do you have in mind? |
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
The prefix matching wasn't bounded, so you could get partial matches on tags by specifying part of a name that didn't end on a boundary: pull "foo/bar:latest" would match "server/foo/bar:latest" as well as "superfoo/bar:latest" |
Yes, I had that in the comment and also in the comment from the PR #30789 (comment). There will be false positives. The alternative is to hard code the docker default registry ( |
That's not enough because the default registry can be remapped. Basically, no tag prefix checking is really safe or accurate. |
Only a SHA and a force verification can help |
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
Yes, it's a best effort check, which is better than nothing IMO. |
But if it fails, you've broken a user who is doing something the container On Wed, Sep 14, 2016 at 12:33 PM, Yu-Ju Hong notifications@github.com
|
The tag check in this case fails closed (safer) but breaks allowed
On Wed, Sep 14, 2016 at 12:57 PM, Clayton Coleman ccoleman@redhat.com
|
@smarterclayton I meant the current check (which checks only the suffix matches) allow false positive matches, so that it's not as strict, but would still catch some cases.
That's why I didn't hard code the registry name to enforce a more strict check. |
Given that a prefix match against the inspected image's ID will match the
|
@ncdc I was talking about the "tag" check, not the digest check :-) |
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
Automatic merge from submit-queue Docker digest validation is too strict Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of #30366 cannot be pulled by Kube from a Docker 1.10 system. This partially reverts commit 875fd16.
Automatic merge from submit-queue Docker digest validation is too strict Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. This partially reverts commit 875fd16. (cherry picked from commit b841a8b)
Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. Instead, use RepoDigests field as the primary match, validating the digest, and then fall back to ID (also validating the match). Adds more restrictive matching.
Automatic merge from submit-queue Docker digest validation is too strict Docker 1.10 does not guarantee that the pulled digest matches the digest on disk when dealing with v1 schemas stored in a Docker registry. This is the case for images like centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf which as a result of kubernetes#30366 cannot be pulled by Kube from a Docker 1.10 system. This partially reverts commit 875fd16. (cherry picked from commit b841a8b)
Docker API does not validate the tag/sha, for example, all the following
calls work say for a alpine image with short SHA "4e38e38c8ce0"
echo -e "GET /images/alpine:4e38e38c8ce0/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock
echo -e "GET /images/alpine:4e38e38c/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock
echo -e "GET /images/alpine:4/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock
So we should check the response from the Docker API and look for the tags or SHA explicitly.
Fixes #30355
This change is