From caf8db5b279382335fbb1f6d7402ed9b73618d37 Mon Sep 17 00:00:00 2001 From: Matteo Mortari Date: Wed, 26 Jun 2024 01:01:22 +0200 Subject: [PATCH] fix(core): provider do_request to maintain verify in all request, basic headers (#145) * fix(core): provider do_request to maintain verify in all request * basic headers maintenance * add test case * amending test for GHA setup * add CHANGELOG entry * use tls_verify also for login for consistency Signed-off-by: tarilabs --- .github/workflows/auth-tests.yaml | 4 ++++ CHANGELOG.md | 1 + oras/auth/basic.py | 6 +++++- oras/provider.py | 20 ++++++++++-------- oras/tests/test_oras.py | 34 ++++++++++++++++++++++++++++++- 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/.github/workflows/auth-tests.yaml b/.github/workflows/auth-tests.yaml index ca06d310..ff67209b 100644 --- a/.github/workflows/auth-tests.yaml +++ b/.github/workflows/auth-tests.yaml @@ -23,9 +23,13 @@ jobs: registry_port: 5000 with_auth: true REGISTRY_AUTH: "{htpasswd: {realm: localhost, path: /etc/docker/registry/auth.htpasswd}}" + REGISTRY_HTTP_TLS_CERTIFICATE: "/etc/docker/registry/server.cert" + REGISTRY_HTTP_TLS_KEY: "/etc/docker/registry/server.key" REGISTRY_STORAGE_DELETE_ENABLED: "true" run: | htpasswd -cB -b auth.htpasswd myuser mypass cp auth.htpasswd /etc/docker/registry/auth.htpasswd + apk add openssl + openssl req -newkey rsa:4096 -nodes -sha256 -keyout /etc/docker/registry/server.key -x509 -days 365 -subj "/C=IT/ST=Lombardy/L=Milan/O=Acme Org/OU=IT Department/CN=example.com" -out /etc/docker/registry/server.cert registry serve /etc/docker/registry/config.yml & sleep 5 echo $PWD && ls $PWD && make test diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a570875..affe9f82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The versions coincide with releases on pip. Only major versions will be released ## [0.0.x](https://github.com/oras-project/oras-py/tree/main) (0.0.x) - refactor of auth to be provided by backend modules (0.2.0) + - bugfix maintain requests's verify valorization for all invocations, augment basic auth header to existing headers - Allow generating a Subject from a pre-existing Manifest (0.1.30) - add option to not refresh headers during the pushing flow, useful for push with basic auth (0.1.29) - enable additionalProperties in schema validation (0.1.28) diff --git a/oras/auth/basic.py b/oras/auth/basic.py index 686eeea9..bd9e72ac 100644 --- a/oras/auth/basic.py +++ b/oras/auth/basic.py @@ -39,4 +39,8 @@ def authenticate_request( :param originalResponse: original response to get the Www-Authenticate header :type originalResponse: requests.Response """ - return self.get_auth_header(), True + result = {} + if headers is not None: + result.update(headers) + result.update(self.get_auth_header()) + return result, True diff --git a/oras/provider.py b/oras/provider.py index 3f312158..5049adaf 100644 --- a/oras/provider.py +++ b/oras/provider.py @@ -953,6 +953,7 @@ def do_request( json=json, headers=headers, stream=stream, + verify=self._tls_verify, ) # One retry if 403 denied (need new token?) @@ -960,11 +961,14 @@ def do_request( headers, changed = self.auth.authenticate_request( response, headers, refresh=True ) - return self.session.request( - method, - url, - data=data, - json=json, - headers=headers, - stream=stream, - ) + response = self.session.request( + method, + url, + data=data, + json=json, + headers=headers, + stream=stream, + verify=self._tls_verify, + ) + + return response diff --git a/oras/tests/test_oras.py b/oras/tests/test_oras.py index d5248c29..0f16f718 100644 --- a/oras/tests/test_oras.py +++ b/oras/tests/test_oras.py @@ -25,9 +25,10 @@ def test_login_logout(registry, credentials): """ Login and logout are all we can test with basic auth! """ - client = oras.client.OrasClient(hostname=registry, insecure=True) + client = oras.client.OrasClient(hostname=registry, tls_verify=False) res = client.login( hostname=registry, + tls_verify=False, username=credentials.user, password=credentials.password, ) @@ -158,3 +159,34 @@ def test_directory_push_pull(tmp_path, registry, credentials, target_dir): assert str(tmp_path) in files[0] assert os.path.exists(files[0]) assert "artifact.txt" in os.listdir(files[0]) + + +@pytest.mark.with_auth(True) +def test_directory_push_pull_selfsigned_auth( + tmp_path, registry, credentials, target_dir +): + """ + Test push and pull for directory using a self-signed cert registry (`tls_verify=False`) and basic auth (`auth_backend="basic"`) + """ + client = oras.client.OrasClient( + hostname=registry, tls_verify=False, auth_backend="basic" + ) + res = client.login( + hostname=registry, + tls_verify=False, + username=credentials.user, + password=credentials.password, + ) + assert res["Status"] == "Login Succeeded" + + # Test upload of a directory + upload_dir = os.path.join(here, "upload_data") + res = client.push(files=[upload_dir], target=target_dir) + assert res.status_code == 201 + files = client.pull(target=target_dir, outdir=tmp_path) + + assert len(files) == 1 + assert os.path.basename(files[0]) == "upload_data" + assert str(tmp_path) in files[0] + assert os.path.exists(files[0]) + assert "artifact.txt" in os.listdir(files[0])