Skip to content

Commit

Permalink
scripts: add criu-keygen script
Browse files Browse the repository at this point in the history
This script, similar to ssh-keygen and certtool, makes it easier
to generate and install certificate and key to enable encryption
support with CRIU.

Signed-off-by: Radostin Stoyanov <[email protected]>
  • Loading branch information
rst0git committed Jul 8, 2024
1 parent 8ab8d47 commit 3936cbf
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 0 deletions.
1 change: 1 addition & 0 deletions Documentation/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ endif
FOOTER := footer.txt
SRC1 += crit.txt
SRC1 += criu-ns.txt
SRC1 += criu-keygen.txt
SRC1 += compel.txt
SRC1 += criu-amdgpu-plugin.txt
SRC8 += criu.txt
Expand Down
29 changes: 29 additions & 0 deletions Documentation/criu-keygen.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
CRIU-KEYGEN(1)
==============
include::footer.txt[]

NAME
----
criu-keygen - criu encryption key utility

SYNOPSIS
--------
*criu-keygen* [<options>]

DESCRIPTION
-----------
The *criu-keygen* command generates and manages encryption keys for CRIU.
*criu-keygen* can create keys for use by CRIU. The type of key to be
generated is specified with the *-t* option. If invoked without any arguments,
*criu-keygen* will generate an RSA keys.

A system administrator wishing to use CRIU with encryption, would run *criu-keygen*
once to create a certficicate and private key in '/etc/pki/criu/'.

SEE ALSO
--------
criu(8)

AUTHOR
------
The CRIU team
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ ruff:
lib/pycriu/images/images.py \
scripts/criu-ns \
test/others/criu-ns/run.py \
scripts/criu-keygen \
crit/*.py \
crit/crit/*.py \
scripts/uninstall_module.py \
Expand Down
3 changes: 3 additions & 0 deletions criu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,15 @@ install: $(obj)/criu
$(Q) install -m 755 scripts/systemd-autofs-restart.sh $(DESTDIR)$(LIBEXECDIR)/criu/scripts
$(E) " INSTALL " scripts/criu-ns
$(Q) install -m 755 scripts/criu-ns $(DESTDIR)$(SBINDIR)
$(E) " INSTALL " scripts/criu-keygen
$(Q) install -m 755 scripts/criu-keygen $(DESTDIR)$(SBINDIR)
.PHONY: install

uninstall:
$(E) " UNINSTALL" criu
$(Q) $(RM) $(addprefix $(DESTDIR)$(SBINDIR)/,criu)
$(Q) $(RM) $(addprefix $(DESTDIR)$(SBINDIR)/,criu-ns)
$(Q) $(RM) $(addprefix $(DESTDIR)$(SBINDIR)/,criu-keygen)
$(Q) $(RM) $(addprefix $(DESTDIR)$(INCLUDEDIR)/criu/,$(notdir $(UAPI_HEADERS)))
$(Q) $(RM) $(addprefix $(DESTDIR)$(LIBEXECDIR)/criu/scripts/,systemd-autofs-restart.sh)
.PHONY: uninstall
Expand Down
96 changes: 96 additions & 0 deletions scripts/criu-keygen
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
import os
import argparse
import datetime
import pathlib

from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric import ec

CRIU_PKI_PATH = "/etc/pki/criu"
CRIU_KEY_PATH = "/etc/pki/criu/private"


def generate_certificate(private_key):
"""
Generate x509 certificate from private key and save
them in the default PKI path.
"""
key_path = input("Enter file in which to save the key ({}): ".format(
os.path.join(CRIU_KEY_PATH, "key.pem")
))
if not key_path:
key_path = os.path.join(CRIU_KEY_PATH, "key.pem")

cert_path = input("Enter file in which to save the certificate ({}): ".format(
os.path.join(CRIU_PKI_PATH, "cert.pem")
))
if not cert_path:
cert_path = os.path.join(CRIU_PKI_PATH, "cert.pem")

subject = issuer = x509.Name([])
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.now(datetime.timezone.utc))
.not_valid_after(datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=10))
.sign(private_key, hashes.SHA256())
)

pathlib.Path(CRIU_KEY_PATH).mkdir(parents=True, exist_ok=True)

os.umask(0o277)
with open(key_path, "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
))

os.umask(0o222)
with open(cert_path, "wb") as f:
f.write(cert.public_bytes(serialization.Encoding.PEM))


def generate_ec_key(key_size):
"""
Create a self-signed certificate with an EC key.
"""
if not key_size:
key_size = 256
print("Generating public/private ec key pair.")
private_key = ec.generate_private_key(ec.SECP256R1(key_size=key_size))
generate_certificate(private_key)


def generate_rsa_key(key_size):
"""
Create a self-signed certificate with an RSA key.
"""
if not key_size:
key_size = 2048
print("Generating public/private rsa key pair.")
private_key = rsa.generate_private_key(public_exponent=65537, key_size=key_size)
generate_certificate(private_key)


def main():
parser = argparse.ArgumentParser(description='Generate X.509 certificates and private keys for CRIU.')
parser.add_argument('--type', choices=['rsa', 'ec'], default='rsa', help='Type of key to create (default: rsa)')
parser.add_argument('--bits', type=int, help='Number of bits in the key')
args = parser.parse_args()

if args.type == 'rsa':
generate_rsa_key(args.bits)
elif args.type == 'ec':
generate_ec_key()

Check failure

Code scanning / CodeQL

Wrong number of arguments in a call Error

Call to
function generate_ec_key
with too few arguments; should be no fewer than 1.


if __name__ == "__main__":
main()

0 comments on commit 3936cbf

Please sign in to comment.