From 9ea484428a3a122a42d432c2633bc94a71cd8b5f Mon Sep 17 00:00:00 2001 From: Luke Kingland Date: Fri, 20 Sep 2024 14:12:12 +0900 Subject: [PATCH] fix: make image digest check more permissive --- cmd/deploy.go | 30 +++++------------------------- cmd/deploy_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index e986eff99c..2957d39b64 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -794,42 +794,22 @@ func isDigested(v string) (validDigest bool, err error) { var digest string vv := strings.Split(v, "@") if len(vv) < 2 { - // image does NOT have a digest, validate further - if v == "" { - err = fmt.Errorf("provided image is empty, cannot validate") - return - } - vvv := strings.Split(v, ":") - if len(vvv) < 2 { - // assume user knows what hes doing - return - } else if len(vvv) > 2 { - err = fmt.Errorf("image '%v' contains an invalid tag (extra ':')", v) - return - } - tag := vvv[1] - if tag == "" { - err = fmt.Errorf("image '%v' has an empty tag", v) - return - } - return - } else if len(vv) > 2 { - // image is invalid - err = fmt.Errorf("image '%v' contains an invalid digest (extra '@')", v) - return + return // can not be digested without an @ } - // image has a digest, validate further - digest = vv[1] + // Ensure it has the static string prefix + digest = vv[len(vv)-1] if !strings.HasPrefix(digest, "sha256:") { err = fmt.Errorf("image digest '%s' requires 'sha256:' prefix", digest) return } + // Ensure it has the exact right length if len(digest[7:]) != 64 { err = fmt.Errorf("image digest '%v' has an invalid sha256 hash length of %v when it should be 64", digest, len(digest[7:])) } + // It's likely a valid digest (at least syntactically) validDigest = true return } diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index 50d49d28a6..9c11876565 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -2140,3 +2140,39 @@ func TestDeploy_CorrectImageDeployed(t *testing.T) { }) } } + +func Test_isDigested(t *testing.T) { + // Simple references are not digested + var tests = []struct { + Name string + Image string + Digested bool + Error bool + }{ + {Name: "simple", Image: "alpine", Digested: false, Error: false}, + {Name: "tagged", Image: "alpine:latest", Digested: false, Error: false}, + {Name: "domain", Image: "registry.example.com/alice/alpine", Digested: false, Error: false}, + {Name: "domain-tagged", Image: "registry.example.com/alice/alpine:latest", Digested: false, Error: false}, + {Name: "domain-port", Image: "registry.example.com:5001/alice/alpine", Digested: false, Error: false}, + {Name: "domain-port-tagged", Image: "registry.example.com:5001/alice/alpine:latest", Digested: false, Error: false}, + {Name: "domain-port-tagged-digested", Image: "registry.example.com:5001/alice/alpine@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Digested: true, Error: false}, + {Name: "user-domain-port-tagged-digested", Image: "user@registry.example.com:5001/alice/alpine@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Digested: true, Error: false}, + {Name: "error-missing-prefix", Image: "registry.example.com/alice/alpine@e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Digested: false, Error: true}, + {Name: "error-invalid-length", Image: "registry.example.com/alice/alpine@sha256:invalid-hash-value", Digested: false, Error: true}, + } + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + digested, err := isDigested(test.Image) + if err != nil { + if test.Error == true { + return // an error was expected + } + t.Fatal(err) + } + if digested != test.Digested { + t.Fatalf("expected image '%v' be digested==%v", test.Image, test.Digested) + } + }) + } + +}