debian-forge/sources/org.osbuild.ostree
Sanne Raymaekers ae563ff896 sources/ostree: fix quotation marks in mTLS remote options
Example of broken repo config:
```
...
"tls-client-key-path=/etc/pki/consumer/key.pem"
"tls-client-cert-path=/etc/pki/consumer/cert.pem"
```
2023-01-13 11:35:43 +01:00

165 lines
4.6 KiB
Python
Executable file

#!/usr/bin/python3
"""Fetch OSTree commits from an repository
Uses ostree to pull specific commits from (remote) repositories
at the provided `url`. Can verify the commit, if one or more
gpg keys are provided via `gpgkeys`.
"""
import os
import subprocess
import sys
import uuid
from osbuild import sources
from osbuild.util.ostree import show
from osbuild.util.rhsm import Subscriptions
SCHEMA = """
"additionalProperties": false,
"definitions": {
"item": {
"description": "The commits to fetch indexed their checksum",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"[0-9a-f]{5,64}": {
"type": "object",
"additionalProperties": false,
"required": ["remote"],
"properties": {
"remote": {
"type": "object",
"additionalProperties": false,
"required": ["url"],
"properties": {
"url": {
"type": "string",
"description": "URL of the repository."
},
"contenturl": {
"type": "string",
"description": "content URL of the repository."
},
"gpgkeys": {
"type": "array",
"items": {
"type": "string",
"description": "GPG keys to verify the commits"
}
},
"secrets": {
"type": "object",
"additionalProperties": false,
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Name of the secrets provider."
}
}
}
}
}
}
}
}
}
},
"properties": {
"items": {"$ref": "#/definitions/item"},
"commits": {"$ref": "#/definitions/item"}
},
"oneOf": [{
"required": ["items"]
}, {
"required": ["commits"]
}]
"""
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf-8",
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
input=_input,
check=True)
class OSTreeSource(sources.SourceService):
content_type = "org.osbuild.ostree"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.repo = None
def fetch_one(self, checksum, desc):
commit = checksum
remote = desc["remote"]
url = remote["url"]
gpg = remote.get("gpgkeys", [])
uid = str(uuid.uuid4())
remote_add_args = []
if not gpg:
remote_add_args = ["--no-gpg-verify"]
if "contenturl" in remote:
remote_add_args.append(f"--contenturl={remote['contenturl']}")
if remote.get("secrets", {}).get("name") == "org.osbuild.rhsm.consumer":
secrets = Subscriptions.get_consumer_secrets()
remote_add_args.append(f"--set=tls-client-key-path={secrets['consumer_key']}")
remote_add_args.append(f"--set=tls-client-cert-path={secrets['consumer_cert']}")
ostree("remote", "add",
uid, url,
*remote_add_args,
repo=self.repo)
for key in gpg:
ostree("remote", "gpg-import", "--stdin", uid,
repo=self.repo, _input=key)
# Transfer the commit: remote → cache
print(f"pulling {commit}", file=sys.stderr)
ostree("pull", uid, commit, repo=self.repo)
# Remove the temporary remotes again
ostree("remote", "delete", uid,
repo=self.repo)
def setup(self, args):
super().setup(args)
# Prepare the cache and the output repo
self.repo = os.path.join(self.cache, "repo")
ostree("init", mode="archive", repo=self.repo)
# Make sure the cache repository uses locks to protect the metadata during
# shared access. This is the default since `2018.5`, but lets document this
# explicitly here.
ostree("config", "set", "repo.locking", "true", repo=self.repo)
# pylint: disable=[no-self-use]
def exists(self, checksum, _desc):
try:
show(self.repo, checksum)
except RuntimeError:
return False
return True
def main():
service = OSTreeSource.from_args(sys.argv[1:])
service.main()
if __name__ == '__main__':
main()