Skip to content

Conversation

@jedevc
Copy link
Member

@jedevc jedevc commented Jul 17, 2023

- What I did

Fixes docker/buildx#1642 (this one was an utter pain to track down 🎉)

The logic in RegistryHosts appears to be shared between BuildKit and the containerd snapshotter, so this may also be a containerd related fix?

Note

This patch fixes the above issue, but the underlying bug in the issue is actually the use of url.Parse, which can incorrectly parse "foo-registry:5000" with opaque data: https://play.golang.com/p/469UqjaiVhg.

Instead of just fixing this directly, it makes more sense to actually just use the same logic that we already have for parsing the insecure registries config.

- How I did it

The logic previously used in RegistryHosts was duplicated logic from the config we've already parsed - however, there were significant differences in exactly the outputs it produced.

To resolve the above buildx issue, it's sufficient to just update RegistryHosts to use the already parsed configs, which have been validated and cleaned appropriately. We can also add support for the CIDR notation allowed in insecure-registries while we're in the area.

- How to verify it

See the reproduction instructions in docker/buildx#1642 (comment). Before the patches in this PR you should see:

#3 [internal] load metadata for foo-registry:5000/library/hello-world:linux
#3 ERROR: failed to do request: Head "https://foo-registry:5000/v2/library/hello-world/manifests/linux": http: server gave HTTP response to HTTPS client
------
 > [internal] load metadata for foo-registry:5000/library/hello-world:linux:
------
Dockerfile:1
--------------------
   1 | >>> FROM foo-registry:5000/library/hello-world:linux
   2 |     RUN ["/hello"]
--------------------
ERROR: failed to solve: foo-registry:5000/library/hello-world:linux: failed to do request: Head "https://foo-registry:5000/v2/library/hello-world/manifests/linux": http: server gave HTTP response to HTTPS client

And after the patches, the build should complete successfully, with no error displayed.

- Description for the changelog

Resolve insecure-registries consistently for BuildKit builds

- A picture of a cute animal (not mandatory but encouraged)

image

cc @tianon @tonistiigi @crazy-max

jedevc added 2 commits July 17, 2023 12:30
The RegistryHosts lookup function is used by both BuildKit and by the
containerd snapshotter. However, this function differs in behaviour from
the config parser for the RegistryConfig:

- The protocol for insecure registries is treated as significant by
  RegistryHosts, while the RegistryConfig strips this information.
- RegistryConfig validates and deduplicates mirrors.
- RegistryConfig does not parse the insecure-registries as URLs, which
  can lead to parsing opaque URLs as was possible by the RegistryHosts
  function.

This patch updates the lookup function to ensure consistency.

Signed-off-by: Justin Chadwell <me@jedevc.com>
insecure-registries supports using CIDR notation, however, buildkit in
moby was not respecting these. We can update the RegistryHosts function
to support this by inserting the correct host into the lookup map if
it's explicitly marked as insecure.

Signed-off-by: Justin Chadwell <me@jedevc.com>
Comment on lines 192 to 193
// RegistryHosts returns the registry hosts configuration for the host component
// of a distribution image reference.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the "for the host component" part still accurate after this?

(I need to look into the logic; I know there's a lot of ugliness in this area, some for historic reasons 😞)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, yup. We still take a host as the argument, and store the resulting hosts.

We already discarded paths/fragments/etc in this function, so no behaviour changes on that front.

@thaJeztah thaJeztah added area/distribution Image Distribution status/2-code-review kind/bugfix PR's that fix bugs labels Jul 17, 2023
@thaJeztah thaJeztah requested a review from tianon July 17, 2023 13:01
@thaJeztah
Copy link
Member

@tianon @neersighted PTAL :)

@neersighted neersighted self-requested a review July 19, 2023 14:20
Comment on lines +205 to +206
c.PlainHTTP = &t
c.Insecure = &t
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean we assume all insecure registries are plain HTTP, or is this used to trigger the "try HTTPS ignoring the cert, then fall back to HTTP" logic? Sorry, I'm not very familiar with the underlying code here 😭

(IMO this detection behavior of "insecure-registries" is still a misfeature and it'd be a benefit to us to go the other direction and encourage users to make it explicit, but I think I might've already lost that fight with some of the previous related PRs 🙈)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or is this used to trigger the "try HTTPS ignoring the cert, then fall back to HTTP" logic

Exactly this 🎉 This is how we get here in BuildKit: https://github.com/moby/buildkit/blob/master/util/resolver/resolver.go#L25.

This function gets called in resolver.NewRegistryConfig which is called by moby, which returns the two hosts, which get tried in order (return on first success).

and it'd be a benefit to us to go the other direction and encourage users to make it explicit, but I think I might've already lost that fight with some of the previous related PRs

I don't think this battle is necessarily lost -- given our lack of knowledge about how this worked, I think it's fair to assume most users don't really know. So we could make a point of deprecating the current behavior at some point, and try and require protocols.

@jedevc
Copy link
Member Author

jedevc commented Jul 24, 2023

Looking further, this looks like this may also resolve:

Local registry mirror configuration isn’t implemented yet with the containerd image store. The registry-mirrors and insecure-registries aren’t taken into account by the Docker daemon.

from https://docs.docker.com/desktop/containerd/#docker-desktop-4120-release.

I can't find a tracking issue for this in GitHub though, not sure if this way already fixed by something else?

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@thaJeztah
Copy link
Member

We briefly discussed this in the maintainers call. This is indeed one of the "historic" areas where a lot of context has been lost, and behavior is very under-defined. Let's get this one in for the 25.0 release at least, and if the world doesn't explode, we can consider backporting to 24.0 and 23.0 branches if needed.

@cpuguy83
Copy link
Member

cpuguy83 commented Aug 4, 2023

Did this need a backport?

@thaJeztah thaJeztah added this to the 25.0.0 milestone Aug 7, 2023
@thaJeztah
Copy link
Member

@cpuguy83 see my comment above, but if you think it's safe, we can still consider to already backport it

@MetSystem
Copy link

When used internally, you need to use http, and you want to configure the item to turn it on or off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/distribution Image Distribution kind/bugfix PR's that fix bugs status/2-code-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUILDKIT ignores "insecure-registries". server gave HTTP response to HTTPS client. x509: certificate error

5 participants