[PATCH v2 1/2] schema: enforce signer config constraints via schema

1 view
Skip to first unread message

Felix Moessbauer

unread,
Apr 30, 2026, 8:56:22 AM (10 days ago) Apr 30
to kas-...@googlegroups.com, jan.k...@siemens.com, Felix Moessbauer
The signer configuration has various constraints (like if a gpg server
is configured, the key fingerprint must be provided as well). To harden
the configuration against split-brain cases, we now enforce these
constraints via the schema.

By that, we also document, that this part cannot be split across
multiple configuration files.

Signed-off-by: Felix Moessbauer <felix.mo...@siemens.com>
---
Changes since v1:

- enforce more signer related conditions in schema
- drop now redundant checks in keyhandler
- fix typo in commit message
- extended tests

Best regards,
Felix

docs/userguide/project-configuration.rst | 3 ++-
kas/keyhandler.py | 20 ++++++--------------
kas/schema-kas.json | 18 ++++++++++++++++++
3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/docs/userguide/project-configuration.rst b/docs/userguide/project-configuration.rst
index 37fecdbac..04c887b54 100644
--- a/docs/userguide/project-configuration.rst
+++ b/docs/userguide/project-configuration.rst
@@ -464,7 +464,8 @@ Configuration reference
This dict contains the public keys or certificates that are used to verify
the authenticity of the repositories. In case of GPG keys, these are made
available to the build environment as well by pointing the ``GNUPGHOME``
- environment variable to the local keystore.
+ environment variable to the local keystore. A single signer configuration
+ must not be split across multiple config files.

``<signer_id>``: dict [optional]
:kasschemadesc:`signers.additionalProperties`
diff --git a/kas/keyhandler.py b/kas/keyhandler.py
index 092ce2b46..a0ad5de11 100644
--- a/kas/keyhandler.py
+++ b/kas/keyhandler.py
@@ -97,25 +97,21 @@ class GPGKeyHandler(KeyHandler):
self.gpg.trust_keys(fingerprint, 'TRUST_NEVER')

def _import_keys(self, signers, confinst):
+ """
+ Import the keys based on the config entries.
+ The schema ensures, that only valid combinations can
+ be passed to this function.
+ """
for name, loc in signers.items():
fingerprint = loc.get('fingerprint')
keyserver = loc.get('gpg_keyserver')
if 'path' in loc:
- if 'repo' not in loc:
- raise KasUserError('path must be used together with repo')
repo = confinst.get_repo(loc['repo'])
keyfile = Path(repo.path) / Path(loc['path'])
import_result = self.gpg.import_keys_file(keyfile)
- elif keyserver:
- if not fingerprint:
- raise KasUserError('"gpg_keyserver" must be used together '
- 'with "fingerprint"')
+ else:
import_result = self.gpg.recv_keys(keyserver,
fingerprint)
- else:
- raise KasUserError(
- 'neither "path" nor "gpg_keyserver" specified for signer '
- f'"{name}"')
if import_result.count == 0:
raise KeyImportError(name, 'No keys imported')
if import_result.count > 1:
@@ -181,10 +177,6 @@ class SSHKeyHandler(KeyHandler):
self.signers = {}

for name, loc in signers.items():
- if 'repo' not in loc:
- raise KasUserError('For SSH keys, a repo must be specified')
- if 'path' not in loc:
- raise KasUserError('For SSH keys, a path must be specified')
repo = confinst.get_repo(loc['repo'])
pubfile = Path(repo.path) / Path(loc['path'])
keydata = subprocess.check_output(['ssh-keygen', '-lf',
diff --git a/kas/schema-kas.json b/kas/schema-kas.json
index ba9a583c6..f3594a247 100644
--- a/kas/schema-kas.json
+++ b/kas/schema-kas.json
@@ -385,6 +385,24 @@
"type": "object",
"description": "Pairs of name and location of a public key or certificate. The name is used to reference the entry in the repository configuration.",
"additionalProperties": false,
+ "oneOf": [
+ {"required": ["path"]},
+ {"required": ["gpg_keyserver"]}
+ ],
+ "allOf": [
+ {
+ "if": {"required": ["path"]},
+ "then": {"required": ["repo"]}
+ },
+ {
+ "if": {"required": ["gpg_keyserver"]},
+ "then": {"required": ["fingerprint"]}
+ },
+ {
+ "if": {"properties": {"type": {"const": "ssh"}}, "required": ["type"]},
+ "then": {"required": ["path", "repo"]}
+ }
+ ],
"properties": {
"type": {
"description": "Type of the cryptographic material.",
--
2.53.0

Reply all
Reply to author
Forward
0 new messages