Merge pull request #30366 from dims/fix-issue-30355

Automatic merge from submit-queue

Validate SHA/Tag when checking docker images

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
pull/6/head
Kubernetes Submit Queue 2016-08-12 23:42:40 -07:00 committed by GitHub
commit 8a35d4c97c
3 changed files with 84 additions and 0 deletions

View File

@ -150,6 +150,44 @@ func filterHTTPError(err error, image string) error {
}
}
// Check if the inspected image matches what we are looking for
func matchImageTagOrSHA(inspected dockertypes.ImageInspect, image string) bool {
// The image string follows the grammar specified here
// https://github.com/docker/distribution/blob/master/reference/reference.go#L4
named, err := dockerref.ParseNamed(image)
if err != nil {
glog.V(4).Infof("couldn't parse image reference %q: %v", image, err)
return false
}
_, isTagged := named.(dockerref.Tagged)
digest, isDigested := named.(dockerref.Digested)
if !isTagged && !isDigested {
// No Tag or SHA specified, so just return what we have
return true
}
if isTagged {
// Check the RepoTags for an exact match
for _, tag := range inspected.RepoTags {
if tag == image {
// We found a specific tag that we were looking for
return true
}
}
}
if isDigested {
algo := digest.Digest().Algorithm().String()
sha := digest.Digest().Hex()
// Look specifically for short and long sha(s)
if strings.Contains(inspected.ID, algo+":"+sha) {
// We found the short or long SHA requested
return true
}
}
glog.V(4).Infof("Inspected image (%q) does not match %s", inspected.ID, image)
return false
}
// applyDefaultImageTag parses a docker image string, if it doesn't contain any tag or digest,
// a default tag will be applied.
func applyDefaultImageTag(image string) (string, error) {

View File

@ -157,6 +157,49 @@ func TestContainerNaming(t *testing.T) {
}
}
func TestMatchImageTagOrSHA(t *testing.T) {
for _, testCase := range []struct {
Inspected dockertypes.ImageInspect
Image string
Output bool
}{
{
Inspected: dockertypes.ImageInspect{RepoTags: []string{"ubuntu:latest"}},
Image: "ubuntu",
Output: true,
},
{
Inspected: dockertypes.ImageInspect{RepoTags: []string{"ubuntu:14.04"}},
Image: "ubuntu:latest",
Output: false,
},
{
Inspected: dockertypes.ImageInspect{
ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d",
},
Image: "myimage@sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d",
Output: true,
},
{
Inspected: dockertypes.ImageInspect{
ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d",
},
Image: "myimage@sha256:2208f7a29005",
Output: false,
},
{
Inspected: dockertypes.ImageInspect{
ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d",
},
Image: "myimage@sha256:2208",
Output: false,
},
} {
match := matchImageTagOrSHA(testCase.Inspected, testCase.Image)
assert.Equal(t, testCase.Output, match, testCase.Image+" is not a match")
}
}
func TestApplyDefaultImageTag(t *testing.T) {
for _, testCase := range []struct {
Input string

View File

@ -184,6 +184,9 @@ func (d *kubeDockerClient) InspectImage(image string) (*dockertypes.ImageInspect
}
return nil, err
}
if !matchImageTagOrSHA(resp, image) {
return nil, imageNotFoundError{ID: image}
}
return &resp, nil
}