openshift / oc-mirror

Lifecycle manager for internet-disconnected OpenShift environments
Apache License 2.0
82 stars 80 forks source link

CLID-101: Fix TlsVerify always set to false #838

Closed sherine-k closed 2 months ago

sherine-k commented 2 months ago

Description

This PR removes the field TlsVerify from the CopyOptions.Global which was bypassing TLS handshake completely for all registries involved. This field was added there when some code was copied from the skopeo code base, where it was already marked deprecated.

Fixes # CLID-101

Type of change

Please delete options that are not relevant.

Implementation details

Instead of a global TlsVerify, one should set tls verification under either CopyOptions.SrcImage or CopyOptions.DestImage. The exact field can be found under type dockerImageOptions, and its type is commonFlag.OptionalBool.

This makes it impossible to set the field directly. Instead, we use the flags associated with the options to set the value. Example:

srcFlags, srcOpts := mirror.ImageSrcFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "src-", "screds")
destFlags, destOpts := mirror.ImageDestFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "dest-", "dcreds")

srcFlags.Set("src-tls-verify", "false")
destFlags.Set("dest-tls-verify", "false")

Fixing unit tests

Most unit tests don't really call a registry. The fix here is easy: simply remove field TlsVerify when initializing the Global structure. For some unit tests, where a HTTPMock is used as the registry (image-blob-gatherer_test.go for instance), the flags need to be set. This is because the containers/image code is by default now going to make a TLS handshake, unless we set --src-tls-verify and --dest-tls-verify to false.

Fixing executor.go + delete.go

Here we use the same technique (using the flagSet.Set) to force the value of the flags as follows:

The problem here is that the Mode (m2d, d2m or m2m) is determined at the Complete method. At this point, the flagsets are unreachable (flags and options were initialized in func NewMirrorCmd. That is why I had to declare, in the ExecutorSchema type, a private srcFlagSet and destFlagSet, in order to be able to later use them.

Fixing image-blob-gatherer.go

ImageBlobGatherer is used during delete and MirrorToDisk, where:

From the ImageBlobGatherer's perspective though, the local cache is considered a source registry. In order not to disturb TLS handshake for the mirroring, but still be able to gather blobs from cache during archive generation, I added this extra method imageOptions.NewSystemContextWithTLSVerificationOverride : calling it with tlsVerify=false as an input, creates a source system context specific for this use case that bypasses TLS.

How Has This Been Tested?

All Unit and E2E tests pass. With an imageSetConfig containing just an additional image, I tested workflows:

Expected Outcome

No errors related to HTTP such as

2024/04/23 17:42:53  [ERROR]  : unable to add image blobs to the archive : unable to find blobs corresponding to docker://localhost:55000/ubi8/ubi:latest: pinging container registry localhost:55000: Get "https://localhost:55000/v2/": http: server gave HTTP response to HTTPS client 
openshift-ci-robot commented 2 months ago

@sherine-k: This pull request references CLID-101 which is a valid jira issue.

In response to [this](https://github.com/openshift/oc-mirror/pull/838): ># Description > >This PR removes the field `TlsVerify` from the `CopyOptions.Global` which was bypassing TLS handshake completely for all registries involved. >This field was added there when some code was copied from the skopeo code base, where it was already marked deprecated. > >Fixes # [CLID-101](https://issues.redhat.com//browse/CLID-101) > >## Type of change > >Please delete options that are not relevant. > >- [x] Bug fix (non-breaking change which fixes an issue) >- [ ] New feature (non-breaking change which adds functionality) >- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) >- [ ] This change requires a documentation update > >### Implementation details > >Instead of a global `TlsVerify`, one should set tls verification under either `CopyOptions.SrcImage` or `CopyOptions.DestImage`. The exact field can be found under type `dockerImageOptions`, and its type is `commonFlag.OptionalBool`. > >This makes it impossible to set the field directly. Instead, we use the flags associated with the options to set the value. >Example: >``` >srcFlags, srcOpts := mirror.ImageSrcFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "src-", "screds") >destFlags, destOpts := mirror.ImageDestFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "dest-", "dcreds") > >srcFlags.Set("src-tls-verify", "false") >destFlags.Set("dest-tls-verify", "false") >``` > >#### Fixing unit tests >Most unit tests don't really call a registry. The fix here is easy: simply remove field `TlsVerify` when initializing the Global structure. >For some unit tests, where a HTTPMock is used as the registry (image-blob-gatherer_test.go for instance), the flags need to be set. This is because the containers/image code is by default now going to make a TLS handshake, unless we set --src-tls-verify and --dest-tls-verify to false. > >#### Fixing executor.go + delete.go >Here we use the same technique (using the flagSet.Set) to force the value of the flags as follows: >* When DiskToMirror, the source registry is the cache, and therefore ONLY `src-tls-verify` should be set >* When MirrorToDisk, the destination registry is the cache, and therefore ONLY `dest-tls-verify` should be set > >The problem here is that the Mode (m2d, d2m or m2m) is determined at the `Complete` method. At this point, the flagsets are unreachable (flags and options were initialized in func `NewMirrorCmd`. That is why I had to declare, in the `ExecutorSchema` type, a private `srcFlagSet` and `destFlagSet`, in order to be able to later use them. > >#### Fixing image-blob-gatherer.go > >ImageBlobGatherer is used during delete and MirrorToDisk, where: >* dest-tls-verify should be set to false (because we target the cache) >* but src-tls-verify should not be set: it should do TLS handshake with the origin registries > >From the ImageBlobGatherer's perspective though, the local cache is considered a source registry. >In order not to disturb TLS handshake for the mirroring, but still be able to gather blobs from cache during archive generation, I added this extra method `imageOptions.NewSystemContextWithTLSVerificationOverride` : calling it with tlsVerify=false as an input, creates a source system context specific for this use case that bypasses TLS. > ># How Has This Been Tested? > >All Unit and E2E tests pass. >With an imageSetConfig containing just an additional image, I tested workflows: >* mirrorToDisk >* diskToMirror >* mirrorToMirror >* Delete >:warning: graph image generation not tested. This is tricky because the graph image is built using go-containerregistry, and we need to take the tlsVerify from the context and create new setup for go-containerregistry with it. I'm not sure if this is working. >Operator mirroring and release mirroring shouldn't be impacted. > >## Expected Outcome >No errors related to HTTP such as >``` >2024/04/23 17:42:53 [ERROR] : unable to add image blobs to the archive : unable to find blobs corresponding to docker://localhost:55000/ubi8/ubi:latest: pinging container registry localhost:55000: Get "https://localhost:55000/v2/": http: server gave HTTP response to HTTPS client >``` Instructions for interacting with me using PR comments are available [here](https://prow.ci.openshift.org/command-help?repo=openshift%2Foc-mirror). If you have questions or suggestions related to my behavior, please file an issue against the [openshift-eng/jira-lifecycle-plugin](https://github.com/openshift-eng/jira-lifecycle-plugin/issues/new) repository.
openshift-ci[bot] commented 2 months ago

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: sherine-k

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files: - ~~[OWNERS](https://github.com/openshift/oc-mirror/blob/main/OWNERS)~~ [sherine-k] Approvers can indicate their approval by writing `/approve` in a comment Approvers can cancel approval by writing `/approve cancel` in a comment
openshift-ci[bot] commented 2 months ago

@sherine-k: all tests passed!

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
aguidirh commented 2 months ago

/lgtm

openshift-bot commented 2 months ago

[ART PR BUILD NOTIFIER]

This PR has been included in build oc-mirror-plugin-container-v4.17.0-202404241149.p0.g7352815.assembly.stream.el9 for distgit oc-mirror-plugin. All builds following this will include this PR.