# ECR Public and CloudFront ## Goal Given > ECR Public caches image layers in Amazon CloudFront is meantioned in https://aws.amazon.com/blogs/aws/amazon-ecr-public-a-new-public-container-registry/ and sig-k8s-infra is wanting to use the backend behind ECR (public?) of CloudFront or s3. Let's discover information about a published container image on ECR Public to determine the relations to CloudFront. ## The manifest ``` crane manifest public.ecr.aws/eks-distro/kubernetes/pause:v1.21.5-eks-1-21-8 ``` ``` { "mediaType": "application/vnd.oci.image.index.v1+json", "schemaVersion": 2, "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:973abfd68897472315efb17392416548fde9340b66bf6be3f9d1cdaa1fa9916f", "size": 504, "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:c0b9b2c32396000d47d360b4eae1e70c976aa225c87b11f9d411d27777f9c75d", "size": 504, "platform": { "architecture": "arm64", "os": "linux" } } ] } ``` ## The manifest for linux/amd64, showing blobs ``` crane manifest public.ecr.aws/eks-distro/kubernetes/pause:v1.21.5-eks-1-21-8@sha256:973abfd68897472315efb17392416548fde9340b66bf6be3f9d1cdaa1fa9916f ``` ``` { "mediaType": "application/vnd.oci.image.manifest.v1+json", "schemaVersion": 2, "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "digest": "sha256:511e5006c68619289ded4b246ee199cbd7a5be1009a47b4c60f2aefa5419a53a", "size": 612 }, "layers": [ { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "digest": "sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf", "size": 304537 } ] } ``` ## Viewing the pull requests with `crane` ```shell crane pull --verbose public.ecr.aws/eks-distro/kubernetes/pause:v1.21.5-eks-1-21-8 /dev/null 2>&1 | tee ~/aws-public-pull.log ``` ``` 2022/01/28 16:18:37 --> GET https://public.ecr.aws/v2/ 2022/01/28 16:18:37 GET /v2/ HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Accept-Encoding: gzip 2022/01/28 16:18:37 <-- 401 https://public.ecr.aws/v2/ (310.795379ms) 2022/01/28 16:18:37 HTTP/2.0 401 Unauthorized Content-Length: 58 Content-Type: application/json; charset=utf-8 Date: Fri, 28 Jan 2022 03:18:37 GMT Docker-Distribution-Api-Version: registry/2.0 Www-Authenticate: Bearer realm="https://public.ecr.aws/token/",service="public.ecr.aws",scope="aws" {"errors":[{"code":"DENIED","message":"Not Authorized"}]} 2022/01/28 16:18:37 --> GET https://public.ecr.aws/token/?scope=repository%3Aeks-distro%2Fkubernetes%2Fpause%3Apull&service=public.ecr.aws [body redacted: basic token response contains credentials] 2022/01/28 16:18:37 GET /token/?scope=repository%3Aeks-distro%2Fkubernetes%2Fpause%3Apull&service=public.ecr.aws HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Authorization: <redacted> Accept-Encoding: gzip 2022/01/28 16:18:37 <-- 200 https://public.ecr.aws/token/?scope=repository%3Aeks-distro%2Fkubernetes%2Fpause%3Apull&service=public.ecr.aws (64.748802ms) [body redacted: basic token response contains credentials] 2022/01/28 16:18:37 HTTP/2.0 200 OK Connection: close Content-Type: application/json; charset=utf-8 Date: Fri, 28 Jan 2022 03:18:37 GMT Docker-Distribution-Api-Version: registry/2.0 2022/01/28 16:18:37 --> GET https://public.ecr.aws/v2/eks-distro/kubernetes/pause/manifests/v1.21.5-eks-1-21-8 2022/01/28 16:18:37 GET /v2/eks-distro/kubernetes/pause/manifests/v1.21.5-eks-1-21-8 HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Accept: application/vnd.docker.distribution.manifest.v1+json,application/vnd.docker.distribution.manifest.v1+prettyjws,application/vnd.docker.distribution.manifest.v2+json,application/vnd.oci.image.manifest.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.index.v1+json Authorization: <redacted> Accept-Encoding: gzip 2022/01/28 16:18:38 <-- 200 https://public.ecr.aws/v2/eks-distro/kubernetes/pause/manifests/v1.21.5-eks-1-21-8 (119.184722ms) 2022/01/28 16:18:38 HTTP/2.0 200 OK Content-Length: 703 Content-Type: application/vnd.oci.image.index.v1+json Date: Fri, 28 Jan 2022 03:18:38 GMT Docker-Distribution-Api-Version: registry/2.0 { "mediaType": "application/vnd.oci.image.index.v1+json", "schemaVersion": 2, "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:973abfd68897472315efb17392416548fde9340b66bf6be3f9d1cdaa1fa9916f", "size": 504, "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:c0b9b2c32396000d47d360b4eae1e70c976aa225c87b11f9d411d27777f9c75d", "size": 504, "platform": { "architecture": "arm64", "os": "linux" } } ] } 2022/01/28 16:18:38 --> GET https://public.ecr.aws/v2/eks-distro/kubernetes/pause/manifests/sha256:973abfd68897472315efb17392416548fde9340b66bf6be3f9d1cdaa1fa9916f 2022/01/28 16:18:38 GET /v2/eks-distro/kubernetes/pause/manifests/sha256:973abfd68897472315efb17392416548fde9340b66bf6be3f9d1cdaa1fa9916f HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Accept: application/vnd.oci.image.manifest.v1+json Authorization: <redacted> Accept-Encoding: gzip 2022/01/28 16:18:38 <-- 200 https://public.ecr.aws/v2/eks-distro/kubernetes/pause/manifests/sha256:973abfd68897472315efb17392416548fde9340b66bf6be3f9d1cdaa1fa9916f (113.386485ms) 2022/01/28 16:18:38 HTTP/2.0 200 OK Content-Length: 504 Content-Type: application/vnd.oci.image.manifest.v1+json Date: Fri, 28 Jan 2022 03:18:38 GMT Docker-Distribution-Api-Version: registry/2.0 { "mediaType": "application/vnd.oci.image.manifest.v1+json", "schemaVersion": 2, "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "digest": "sha256:511e5006c68619289ded4b246ee199cbd7a5be1009a47b4c60f2aefa5419a53a", "size": 612 }, "layers": [ { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "digest": "sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf", "size": 304537 } ] } 2022/01/28 16:18:38 --> GET https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:511e5006c68619289ded4b246ee199cbd7a5be1009a47b4c60f2aefa5419a53a 2022/01/28 16:18:38 GET /v2/eks-distro/kubernetes/pause/blobs/sha256:511e5006c68619289ded4b246ee199cbd7a5be1009a47b4c60f2aefa5419a53a HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Authorization: <redacted> Accept-Encoding: gzip 2022/01/28 16:18:38 <-- 307 https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:511e5006c68619289ded4b246ee199cbd7a5be1009a47b4c60f2aefa5419a53a (99.759486ms) 2022/01/28 16:18:38 HTTP/2.0 307 Temporary Redirect Date: Fri, 28 Jan 2022 03:18:38 GMT Docker-Distribution-Api-Version: registry/2.0 Location: https://d2glxqk2uabbnd.cloudfront.net/eb7a5a-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/c359eb2e-1560-480d-995c-dea9c4ebde26?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 Content-Length: 0 2022/01/28 16:18:38 --> GET https://d2glxqk2uabbnd.cloudfront.net/eb7a5a-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/c359eb2e-1560-480d-995c-dea9c4ebde26?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 2022/01/28 16:18:38 GET /eb7a5a-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/c359eb2e-1560-480d-995c-dea9c4ebde26?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 HTTP/1.1 Host: d2glxqk2uabbnd.cloudfront.net User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Referer: https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:511e5006c68619289ded4b246ee199cbd7a5be1009a47b4c60f2aefa5419a53a Accept-Encoding: gzip 2022/01/28 16:18:38 <-- 200 https://d2glxqk2uabbnd.cloudfront.net/eb7a5a-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/c359eb2e-1560-480d-995c-dea9c4ebde26?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 (116.731223ms) 2022/01/28 16:18:38 HTTP/2.0 200 OK Content-Length: 612 Accept-Ranges: bytes Age: 19285 Content-Type: application/octet-stream Date: Thu, 27 Jan 2022 21:57:14 GMT Etag: "af8108f3d470b6f64f5cc022e31b4a27-1" Last-Modified: Wed, 19 Jan 2022 07:23:51 GMT Server: AmazonS3 Via: 1.1 cc58556a6e846289f4d3105969536e4c.cloudfront.net (CloudFront) X-Amz-Cf-Id: cB30gx3kwBzfaWHdr8GGGIu3Vyp3ZvqDBFo33XIYwMeESf4r-597Jw== X-Amz-Cf-Pop: SFO53-C1 X-Amz-Server-Side-Encryption: AES256 X-Amz-Version-Id: STll3gBXJo9RdWJG6CbX1A8X1ai02xYc X-Cache: Hit from cloudfront {"architecture":"amd64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Entrypoint":["/pause"],"WorkingDir":"/","OnBuild":null},"created":"2022-01-19T07:23:09.246889612Z","history":[{"created":"2022-01-19T07:23:09.246889612Z","created_by":"COPY /pause /pause # buildkit","comment":"buildkit.dockerfile.v0"},{"created":"2022-01-19T07:23:09.246889612Z","created_by":"ENTRYPOINT [\"/pause\"]","comment":"buildkit.dockerfile.v0","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:3d2d6db4b867c4fd1bd6f8f3f9ec9bf19128c8371e80c3132693657a95d1da1e"]}} 2022/01/28 16:18:38 --> GET https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf [body redacted: omitting binary blobs from logs] 2022/01/28 16:18:38 GET /v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Authorization: <redacted> Accept-Encoding: gzip 2022/01/28 16:18:38 <-- 307 https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf (91.254451ms) [body redacted: omitting binary blobs from logs] 2022/01/28 16:18:38 HTTP/2.0 307 Temporary Redirect Date: Fri, 28 Jan 2022 03:18:38 GMT Docker-Distribution-Api-Version: registry/2.0 Location: https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 Content-Length: 0 2022/01/28 16:18:38 --> GET https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 [body redacted: omitting binary blobs from logs] 2022/01/28 16:18:38 GET /58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 HTTP/1.1 Host: d2glxqk2uabbnd.cloudfront.net User-Agent: crane/v0.8.0 go-containerregistry/v0.8.0 Referer: https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf Accept-Encoding: gzip 2022/01/28 16:18:38 <-- 200 https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?CallerAccountId=927157667477&Expires=1643343518&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 (51.153136ms) [body redacted: omitting binary blobs from logs] 2022/01/28 16:18:38 HTTP/2.0 200 OK Content-Length: 304537 Accept-Ranges: bytes Age: 19285 Content-Type: application/octet-stream Date: Thu, 27 Jan 2022 21:57:14 GMT Etag: "f36747e0a872cef07a0bae9767031103-1" Last-Modified: Wed, 19 Jan 2022 07:23:51 GMT Server: AmazonS3 Via: 1.1 cc58556a6e846289f4d3105969536e4c.cloudfront.net (CloudFront) X-Amz-Cf-Id: KzR4CaElficCskyLv_-U59UZOSkD7Dt8LTenxN5rUwxh6Mrm5tu14Q== X-Amz-Cf-Pop: SFO53-C1 X-Amz-Server-Side-Encryption: AES256 X-Amz-Version-Id: l7hbEJHbXyu.FSn6WmRWa8fxMBjxl6bS X-Cache: Hit from cloudfront ``` We see towards the end here, it resolves to a CloudFront URI https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?CallerAccountId=927157667477&Expires=1643343518&[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 Behind the serving in the URI, is s3 but it is not exposed. CloudFront is even a detail. There's nothing visible in the URI about the blob. Hitting https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf requires authorization. # Fetching an individual blob There's only one layer in this image ``` crane blob --verbose public.ecr.aws/eks-distro/kubernetes/pause:v1.21.5-eks-1-21-8@sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf > /dev/null ``` ``` 2022/01/28 16:24:57 --> GET https://public.ecr.aws/v2/ 2022/01/28 16:24:57 GET /v2/ HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.7.0 go-containerregistry/v0.7.0 Accept-Encoding: gzip 2022/01/28 16:24:58 <-- 401 https://public.ecr.aws/v2/ (1.048181503s) 2022/01/28 16:24:58 HTTP/2.0 401 Unauthorized Content-Length: 58 Content-Type: application/json; charset=utf-8 Date: Fri, 28 Jan 2022 03:24:58 GMT Docker-Distribution-Api-Version: registry/2.0 Www-Authenticate: Bearer realm="https://public.ecr.aws/token/",service="public.ecr.aws",scope="aws" {"errors":[{"code":"DENIED","message":"Not Authorized"}]} 2022/01/28 16:24:58 --> GET https://public.ecr.aws/token/?scope=repository%3Aeks-distro%2Fkubernetes%2Fpause%3Apull&service=public.ecr.aws [body redacted: basic token response contains credentials] 2022/01/28 16:24:58 GET /token/?scope=repository%3Aeks-distro%2Fkubernetes%2Fpause%3Apull&service=public.ecr.aws HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.7.0 go-containerregistry/v0.7.0 Accept-Encoding: gzip 2022/01/28 16:24:59 <-- 200 https://public.ecr.aws/token/?scope=repository%3Aeks-distro%2Fkubernetes%2Fpause%3Apull&service=public.ecr.aws (233.068676ms) [body redacted: basic token response contains credentials] 2022/01/28 16:24:59 HTTP/2.0 200 OK Content-Length: 653 Content-Type: application/json; charset=utf-8 Date: Fri, 28 Jan 2022 03:24:58 GMT Docker-Distribution-Api-Version: registry/2.0 2022/01/28 16:24:59 --> GET https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf [body redacted: omitting binary blobs from logs] 2022/01/28 16:24:59 GET /v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf HTTP/1.1 Host: public.ecr.aws User-Agent: crane/v0.7.0 go-containerregistry/v0.7.0 Authorization: <redacted> Accept-Encoding: gzip 2022/01/28 16:24:59 <-- 307 https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf (253.951402ms) [body redacted: omitting binary blobs from logs] 2022/01/28 16:24:59 HTTP/2.0 307 Temporary Redirect Date: Fri, 28 Jan 2022 03:24:59 GMT Docker-Distribution-Api-Version: registry/2.0 Location: https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?Expires=1643343899&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 Content-Length: 0 2022/01/28 16:24:59 --> GET https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?Expires=1643343899&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 [body redacted: omitting binary blobs from logs] 2022/01/28 16:24:59 GET /58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?Expires=1643343899&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 HTTP/1.1 Host: d2glxqk2uabbnd.cloudfront.net User-Agent: crane/v0.7.0 go-containerregistry/v0.7.0 Referer: https://public.ecr.aws/v2/eks-distro/kubernetes/pause/blobs/sha256:7c6d4d5ddd335e6acd0b2d5eb91dfaa2a988cec62ffc5eed5304ce2ffd64a5cf Accept-Encoding: gzip 2022/01/28 16:25:00 <-- 200 https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?Expires=1643343899&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 (735.581404ms) [body redacted: omitting binary blobs from logs] 2022/01/28 16:25:00 HTTP/2.0 200 OK Content-Length: 304537 Accept-Ranges: bytes Age: 19666 Content-Type: application/octet-stream Date: Thu, 27 Jan 2022 21:57:14 GMT Etag: "f36747e0a872cef07a0bae9767031103-1" Last-Modified: Wed, 19 Jan 2022 07:23:51 GMT Server: AmazonS3 Via: 1.1 a881cb8cde2d5f28c5d1e3662b510ada.cloudfront.net (CloudFront) X-Amz-Cf-Id: pBnWgd2zXodUuTYIUv57i6J_NKKY_-8a1YGizRWXj-guwNJhTL7t8Q== X-Amz-Cf-Pop: LAX3-C3 X-Amz-Server-Side-Encryption: AES256 X-Amz-Version-Id: l7hbEJHbXyu.FSn6WmRWa8fxMBjxl6bS X-Cache: Hit from cloudfront ``` The URI in which the blob resolves to is different again. This time it is https://d2glxqk2uabbnd.cloudfront.net/58fb3b-379412251201-74bb087c-5bd2-4918-8058-d5eaf7ee8631/fbf6ceae-b28a-4f65-b877-1fc4e69f8d2e?Expires=1643343899&Signature=[OMMITED]&Key-Pair-Id=KSPLJWGOARK62 meaning if somehow they were to be generated, they wouldn't be able to be effectively reused.