Skip to content
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

oras pull error: empty response Docker-Content-Digest #225

Closed
johankees opened this issue Jul 4, 2022 · 8 comments · Fixed by #237
Closed

oras pull error: empty response Docker-Content-Digest #225

johankees opened this issue Jul 4, 2022 · 8 comments · Fixed by #237
Assignees
Labels
bug Something isn't working
Milestone

Comments

@johankees
Copy link

Pulling a container from AWS ECR fails with error empty response Docker-Content-Digest.

Steps to reproduce:

Expected result:

  • Image pulled successfully, and response:
    Pulled ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/IMAGE:TAG
    Digest: sha256:<SOME_SHA>
    

Actual result:

  • Image failed to be pulled:
    Error: GET "https://ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/v2/IMAGE/manifests/TAG": empty response Docker-Content-Digest
    

Verbose error message:

-> oras pull ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/IMAGE:TAG -d
DEBU[0000]  Request URL: "https://ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/v2/IMAGE/manifests/TAG"
DEBU[0000]  Request method: "GET"
DEBU[0000]  Request headers:
DEBU[0000]    "Accept": "application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.cncf.oras.artifact.manifest.v1+json"
DEBU[0000]    "User-Agent": "oras/0.13.0"
DEBU[0000]  Response Status: "401 Unauthorized"
DEBU[0000]  Response headers:
DEBU[0000]    "Docker-Distribution-Api-Version": "registry/2.0"
DEBU[0000]    "Sizes": ""
DEBU[0000]    "Www-Authenticate": "Basic realm=\"https://ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/\",service=\"ecr.amazonaws.com\""
DEBU[0000]    "Date": "Mon, 04 Jul 2022 13:06:58 GMT"
DEBU[0000]    "Content-Length": "15"
DEBU[0000]    "Content-Type": "text/plain; charset=utf-8"
DEBU[0000]  Request URL: "https://ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/v2/IMAGE/manifests/TAG"
DEBU[0000]  Request method: "GET"
DEBU[0000]  Request headers:
DEBU[0000]    "User-Agent": "oras/0.13.0"
DEBU[0000]    "Accept": "application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.cncf.oras.artifact.manifest.v1+json"
DEBU[0000]    "Authorization": "*****"
DEBU[0001]  Response Status: "200 OK"
DEBU[0001]  Response headers:
DEBU[0001]    "Content-Type": "application/vnd.oci.image.manifest.v1+json"
DEBU[0001]    "Docker-Distribution-Api-Version": "registry/2.0"
DEBU[0001]    "Sizes": ""
DEBU[0001]    "Date": "Mon, 04 Jul 2022 13:06:59 GMT"
DEBU[0001]    "Content-Length": "396"
Error: GET "https://ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/v2/IMAGE/manifests/TAG": empty response Docker-Content-Digest

Version Information:
Oras: 0.13.0

Note: I have tested the same command with v0.12.0 and it works fine in this version. So it looks like this issue was introduced in v0.13.0.

@shizhMSFT shizhMSFT added the question Further information is requested label Jul 5, 2022
@shizhMSFT
Copy link
Contributor

AWS ECR is not compliant with Docker Registry HTTP API V2 where Docker-Content-Digest is required in the response.

In OCI spec,

A successful response SHOULD contain the digest of the uploaded blob in the header Docker-Content-Digest.

/cc @michaelb990

@shizhMSFT shizhMSFT transferred this issue from oras-project/oras Jul 5, 2022
@shizhMSFT shizhMSFT added this to the v2.0.0-rc.1 milestone Jul 5, 2022
@michaelb990
Copy link

Hmm... A client failure based on a registry not returning a header that SHOULD be present seems like a client issue, not a registry issue.

We can still look into fixing this on the registry side, but I'm curious why this is a required header for the ORAS client. Do you know why this changed in v0.13.0?

@shizhMSFT
Copy link
Contributor

Before v0.13.0, oras CLI is based on oras-go v0.1.0, which is further based on containerd, and it seems containerd does not check the Docker-Content-Digest header. In v0.13.0, oras CLI is based on oras-go v2, which is purely implemented according to the Docker and OCI specs.

Since it is a "MUST" in the docker spec and a "SHOULD" in the OCI spec, oras-go MAY handle empty Docker-Content-Digest in the response.

@shizhMSFT
Copy link
Contributor

As we don't have an ECR to test with, @michaelb990 can you ask @nima to help fixing this?

@shizhMSFT shizhMSFT added bug Something isn't working and removed question Further information is requested labels Jul 5, 2022
@shizhMSFT shizhMSFT modified the milestones: v2.0.0-rc.1, v2.0.0 Jul 5, 2022
@nima
Copy link
Contributor

nima commented Jul 8, 2022

Okay I have a repro, and will look into this today/weekend.

Side-questions: any discussions (or existence) of black-box/smoke-testing that would have caught something like this? Even something very basic; single command to test out various common and valid critical permutations of commands that should never fail.

nima added a commit to nima/oras-go that referenced this issue Jul 11, 2022
nima added a commit to nima/oras-go that referenced this issue Jul 11, 2022
Fixes oras-project#225

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Jul 11, 2022
Fixes oras-project#225

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Jul 12, 2022
Fixes oras-project#225

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Jul 15, 2022
That this issue existed is a side-effect of an earlier chronic pathology.  At
least in the pull workflow, no where does the library (on behalf of the client)
verify on its own the digest returned by the server.  By not doing so, it also
has become dependent on the optional response header `Docker-Content-Digest`,
which has lead to this bug.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).
nima added a commit to nima/oras-go that referenced this issue Jul 15, 2022
That this issue existed is a side-effect of an earlier chronic pathology.  At
least in the pull workflow, no where does the library (on behalf of the client)
verify on its own the digest returned by the server.  By not doing so, it also
has become dependent on the optional response header `Docker-Content-Digest`,
which has lead to this bug.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Jul 15, 2022
That this issue existed is a side-effect of an earlier chronic pathology.  At
least in the pull workflow, no where does the library (on behalf of the client)
verify on its own the digest returned by the server.  By not doing so, it also
has become dependent on the optional response header `Docker-Content-Digest`,
which has lead to this bug.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
@nima
Copy link
Contributor

nima commented Jul 16, 2022

I think I need some help with this; I've started a thread here describing my current approach and its shortcomings.

nima added a commit to nima/oras-go that referenced this issue Jul 16, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

This change--depite possibly being a meager improvement, is still inadequate.
The reason for the inadequacy is that it relies heavily on a response body not
being close, and this is not always the case.  Where it is closed, it again
defaults back to scavenging from any of the two digests available to it, and
neither is guaranteed to even exist:

 1) The header `Docker-Content-Digest`, as already mentioned, is OPTIONAL
 2) The user-supplied `reference` is polymorphic, in that it could just as
    well be a `digest`, as it could a `tag`.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Jul 17, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

This change--depite possibly being a meager improvement, is still inadequate.
The reason for the inadequacy is that it relies heavily on a response body not
being close, and this is not always the case.  Where it is closed, it again
defaults back to scavenging from any of the two digests available to it, and
neither is guaranteed to even exist:

 1) The header `Docker-Content-Digest`, as already mentioned, is OPTIONAL
 2) The user-supplied `reference` is polymorphic, in that it could just as
    well be a `digest`, as it could a `tag`.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Jul 18, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

This change--depite possibly being a meager improvement, is still inadequate.
The reason for the inadequacy is that it relies heavily on a response body not
being close, and this is not always the case.  Where it is closed, it again
defaults back to scavenging from any of the two digests available to it, and
neither is guaranteed to even exist:

 1) The header `Docker-Content-Digest`, as already mentioned, is OPTIONAL
 2) The user-supplied `reference` is polymorphic, in that it could just as
    well be a `digest`, as it could a `tag`.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
@shizhMSFT shizhMSFT modified the milestones: v2.0.0-rc.2, v2.0.0-rc.3 Aug 9, 2022
@FeynmanZhou
Copy link
Member

FeynmanZhou commented Aug 10, 2022

Please note that this issue also caused the Notation pull works to fail with ECR since there is a dependency for Notary v2. Can we prioritize it? @nima

@nima
Copy link
Contributor

nima commented Aug 17, 2022

I've been away for a couple of weeks; taking a look at this now; will update here.

nima added a commit to nima/oras-go that referenced this issue Aug 17, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

This change--depite possibly being a meager improvement, is still inadequate.
The reason for the inadequacy is that it relies heavily on a response body not
being close, and this is not always the case.  Where it is closed, it again
defaults back to scavenging from any of the two digests available to it, and
neither is guaranteed to even exist:

 1) The header `Docker-Content-Digest`, as already mentioned, is OPTIONAL
 2) The user-supplied `reference` is polymorphic, in that it could just as
    well be a `digest`, as it could a `tag`.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Aug 18, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

This change--depite possibly being a meager improvement, is still inadequate.
The reason for the inadequacy is that it relies heavily on a response body not
being close, and this is not always the case.  Where it is closed, it again
defaults back to scavenging from any of the two digests available to it, and
neither is guaranteed to even exist:

 1) The header `Docker-Content-Digest`, as already mentioned, is OPTIONAL
 2) The user-supplied `reference` is polymorphic, in that it could just as
    well be a `digest`, as it could a `tag`.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
@shizhMSFT shizhMSFT linked a pull request Aug 18, 2022 that will close this issue
nima added a commit to nima/oras-go that referenced this issue Aug 19, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

In this change, two new functions have been added:

    1) calculateDigestFromResponse
    2) verifyContentDigestForPull

The former calculates the actual digest of the response body.  The latter
performs a 3-way validation between the two potentially-empty digests--namely,
the reference digest (if indeed the reference supplied by the user was a digest
and not a tag), and the response header optionally set by the server (that is,
`Docker-Content-Digest`).

This change--depite possibly being a meager improvement, is still inadequate.
The reason for the inadequacy is that it relies heavily on a response body not
being close, and this is not always the case.  Where it is closed, it again
defaults back to scavenging from any of the two digests available to it, and
neither is guaranteed to even exist:

 1) The header `Docker-Content-Digest`, as already mentioned, is OPTIONAL
 2) The user-supplied `reference` is polymorphic, in that it could just as
    well be a `digest`, as it could a `tag`.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Aug 22, 2022
Part of this change was to revert unrelated changes in
`registry/reference*.go'; those to be posted as a separate PR.

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Aug 22, 2022
Fixes the `oras pull error: empty response Docker-Content-Digest` bug (oras-project#225).

In this PR, the PR comments were addressed, and unrelated changes in
`registry/reference*.go' were reverted for a separate PR (not yet out).

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Aug 22, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <nima@users.noreply.github.com>
nima added a commit to nima/oras-go that referenced this issue Aug 25, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue oras-project#225.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <github@nima.id.au>
Wwwsylvia pushed a commit that referenced this issue Aug 25, 2022
That this issue existed is a side-effect of an earlier chronic issue.  At least
in the pull workflow, no where does the library (on behalf of the client)
attempt to verify the digest returned by the register/server.  By not doing so,
it also has taken an unhealthy dependency on a precariously OPTIONAL response
header, namely, `Docker-Content-Digest`.  All this has lead to issue #225.

Discussion thread on this has been opened up in Slack:

    https://cloud-native.slack.com/archives/CJ1KHJM5Z/p1657935407555609

Signed-off-by: Nima Talebi <github@nima.id.au>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
No open projects
Status: Done
Development

Successfully merging a pull request may close this issue.

5 participants