sources/curl: add org.osbuild.mtls secrets support

If `org.osbuild.mtls` is passed as a secret name, look for the mtls data
in the environment.
This commit is contained in:
Sanne Raymaekers 2024-03-06 14:36:02 +01:00 committed by Simon de Vlieger
parent c990c07f79
commit 29159189f1
2 changed files with 104 additions and 6 deletions

View file

@ -2,13 +2,19 @@
"""
Source for downloading files from URLs.
The files are indexed by their content hash. Can download files
that require secrets. The only secret provider currently supported
is `org.osbuild.rhsm` for downloading Red Hat content that requires
a subscriptions.
The files are indexed by their content hash. It can download files
that require secrets. The secret providers currently supported are:
Internally use curl to download the files; the files are cached in
an internal cache. Multiple parallel connections are used to speed
- `org.osbuild.rhsm` for downloading Red Hat content that requires
a subscriptions.
- `org.osbuild.mtls` for downloading content that requires client
certificats. The paths to the key and cert should be set in the
environment in OSBUILD_SOURCES_CURL_SSL_CLIENT_KEY,
OSBUILD_SOURCES_CURL_SSL_CLIENT_CERT, and optionally
OSBUILD_SOURCES_CURL_SSL_CA_CERT.
It uses curl to download the files; the files are cached in an
internal cache. Multiple parallel connections are used to speed
up the download.
"""
@ -107,6 +113,16 @@ class CurlSource(sources.SourceService):
if self.subscriptions is None:
self.subscriptions = Subscriptions.from_host_system()
url["secrets"] = self.subscriptions.get_secrets(url.get("url"))
elif url.get("secrets", {}).get("name") == "org.osbuild.mtls":
key = os.getenv("OSBUILD_SOURCES_CURL_SSL_CLIENT_KEY")
cert = os.getenv("OSBUILD_SOURCES_CURL_SSL_CLIENT_CERT")
if not (key and cert):
raise RuntimeError(f"mtls secrets required but key ({key}) or cert ({cert}) not defined")
url["secrets"] = {
'ssl_ca_cert': os.getenv("OSBUILD_SOURCES_CURL_SSL_CA_CERT"),
'ssl_client_cert': cert,
'ssl_client_key': key,
}
return checksum, url

View file

@ -0,0 +1,82 @@
#!/usr/bin/python3
import contextlib
import os
import pathlib
import socket
import tempfile
import pytest
SOURCES_NAME = "org.osbuild.curl"
def test_curl_source_not_exists(sources_module):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
curl_source = sources_module.CurlSource.from_args(["--service-fd", str(sock.fileno())])
tmpdir = tempfile.TemporaryDirectory()
curl_source.cache = tmpdir.name
desc = {
"url": "http://localhost:80/a",
}
checksum = "sha256:1234567890123456789012345678901234567890909b14ffb032aa20fa23d9ad6"
assert not curl_source.exists(checksum, desc)
def test_curl_source_exists(sources_module):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
curl_source = sources_module.CurlSource.from_args(["--service-fd", str(sock.fileno())])
tmpdir = tempfile.TemporaryDirectory()
curl_source.cache = tmpdir.name
desc = {
"url": "http://localhost:80/a",
}
checksum = "sha256:1234567890123456789012345678901234567890909b14ffb032aa20fa23d9ad6"
pathlib.Path(os.path.join(tmpdir.name, checksum)).touch()
assert curl_source.exists(checksum, desc)
def test_curl_source_transform(sources_module):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
curl_source = sources_module.CurlSource.from_args(["--service-fd", str(sock.fileno())])
tmpdir = tempfile.TemporaryDirectory()
curl_source.cache = tmpdir.name
desc = {
"url": "http://localhost:80/a",
"secrets": {
"name": "org.osbuild.mtls",
},
}
with contextlib.ExitStack() as cm:
os.environ["OSBUILD_SOURCES_CURL_SSL_CLIENT_KEY"] = "key"
os.environ["OSBUILD_SOURCES_CURL_SSL_CLIENT_CERT"] = "cert"
def cb():
del os.environ["OSBUILD_SOURCES_CURL_SSL_CLIENT_KEY"]
del os.environ["OSBUILD_SOURCES_CURL_SSL_CLIENT_CERT"]
cm.callback(cb)
checksum = "sha256:1234567890123456789012345678901234567890909b14ffb032aa20fa23d9ad6"
pathlib.Path(os.path.join(tmpdir.name, checksum)).touch()
new_desc = curl_source.transform(checksum, desc)
assert new_desc[1]["secrets"]["ssl_client_key"] == "key"
assert new_desc[1]["secrets"]["ssl_client_cert"] == "cert"
assert new_desc[1]["secrets"]["ssl_ca_cert"] is None
def test_curl_source_transform_fail(sources_module):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
curl_source = sources_module.CurlSource.from_args(["--service-fd", str(sock.fileno())])
tmpdir = tempfile.TemporaryDirectory()
curl_source.cache = tmpdir.name
desc = {
"url": "http://localhost:80/a",
"secrets": {
"name": "org.osbuild.mtls",
},
}
checksum = "sha256:1234567890123456789012345678901234567890909b14ffb032aa20fa23d9ad6"
pathlib.Path(os.path.join(tmpdir.name, checksum)).touch()
with pytest.raises(RuntimeError) as exc:
curl_source.transform(checksum, desc)
assert "mtls secrets required" in str(exc)