Skip to content

Commit 13cffb3

Browse files
committed
SSL auth and user GPG key support for user templates repos
This commit adds the support of user defined GPG keys and SSL authentication for user templates repositories. GPG keys and SSL cert/key must be configured in DNF repositories files using the well-known options (gpgkey, sslclientcert, sslclientkey). If the keys are stored in /etc/qubes/repo-templates/keys/, they will be added to the payload sent to proxy in base64 and will be written to the Proxy VM before DNF command execution
1 parent 02a9b4f commit 13cffb3

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

qubesadmin/tools/qvm_template.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"""Tool for managing VM templates."""
2121

2222
import argparse
23+
import base64
2324
import collections
2425
import configparser
2526
import datetime
@@ -59,6 +60,8 @@
5960
LOCK_FILE = '/var/tmp/qvm-template.lck'
6061
DATE_FMT = '%Y-%m-%d %H:%M:%S'
6162
TAR_HEADER_BYTES = 512
63+
WRAPPER_PAYLOAD_BEGIN = "###!Q!BEGIN-QUBES-WRAPPER!Q!###"
64+
WRAPPER_PAYLOAD_END = "###!Q!END-QUBES-WRAPPER!Q!###"
6265

6366
UPDATEVM = str('global UpdateVM')
6467

@@ -502,9 +505,48 @@ def check_newline(string, name):
502505
check_newline(spec, 'template name')
503506
payload += spec + '\n'
504507
payload += '---\n'
508+
509+
repo_config = ""
505510
for path in args.repo_files:
506511
with open(path, 'r', encoding='utf-8') as fd:
507-
payload += fd.read() + '\n'
512+
repo_config += fd.read() + '\n'
513+
payload += repo_config
514+
515+
# Add base64 encoded files to payload if needed
516+
def encode_key(path):
517+
if path.startswith("file://"):
518+
path = path[7:]
519+
520+
if not path.startswith(
521+
"/etc/qubes/repo-templates/keys/") or not os.path.isfile(path):
522+
return ""
523+
524+
encoded_key = "#" + path + "\n"
525+
with open(path, "rb") as key:
526+
encoded_key += f"#{base64.b64encode(key.read()).decode('ascii')}\n"
527+
return encoded_key
528+
529+
def append_keys(payload):
530+
config = configparser.ConfigParser()
531+
try:
532+
config.read_string(payload)
533+
except RuntimeError:
534+
return ""
535+
536+
file_list = set()
537+
for section in config.sections():
538+
for option in ["gpgkey", "sslclientcert", "sslclientkey"]:
539+
if config.has_option(section, option):
540+
file_list.add(config.get(section, option))
541+
542+
encoded_keys = "".join(encode_key(file_path) for file_path in file_list)
543+
if not encoded_keys:
544+
return ""
545+
546+
return f"\n{WRAPPER_PAYLOAD_BEGIN}\n{encoded_keys}{WRAPPER_PAYLOAD_END}"
547+
548+
payload += append_keys(repo_config)
549+
508550
return payload
509551

510552

0 commit comments

Comments
 (0)