# 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.