Implement verifier graceful shutdown

The included patches implement graceful shutdown for both pull and push
models, cancelling pending operations, and waiting for critical
in-flight operations to finish before shutting down.

Backport the following upstream PRs:
 - https://github.com/keylime/keylime/pull/1809
   - Document supported configuration options
   - Sync missing and removed options from configuration templates
 - https://github.com/keylime/keylime/pull/1868
   - Remove 'enable_authentication' from agent config templates
 - https://github.com/keylime/keylime/pull/1855
   - Add push-model documentation
 - https://github.com/keylime/keylime/pull/1869
   - Add verifier graceful shutdown
 - https://github.com/keylime/keylime/pull/1883
   - Ignore SIGTERM and SIGINT signals on Manager and parent processes
 - https://github.com/keylime/keylime/pull/1886
   - Move socket from /tmp to /var/run/keylime

Also, update the keylime-selinux to the latest release (43.2.1) to
include the following changes:

 - https://github.com/RedHat-SP-Security/keylime-selinux/pull/33
   - Allow Keylime to perform socket operation on /var/run/keylime
 - https://github.com/RedHat-SP-Security/keylime-selinux/pull/34
   - Allow Keylime to read /proc/net to populate certificates Subject
     Alternative Names (SAN)

Documentation updates and configuration template updates were included
to allow the graceful shutdown patch to apply cleanly.

This also modifies the test runner to use pytest, adding python3-pytest
to the BuildRequires. This was necessary to make the fixtures created in
conftest.py to be used, which is not available when running with
unittest.

Resolves: RHEL-151493
Resolves: RHEL-151408

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
This commit is contained in:
Anderson Toshiyuki Sasaki 2026-04-09 17:42:26 +02:00
parent d7b9d5aca9
commit eca2d398c1
No known key found for this signature in database
9 changed files with 6013 additions and 4 deletions

1
.gitignore vendored
View File

@ -37,3 +37,4 @@
/keylime-selinux-42.1.2.tar.gz
/v7.14.1.tar.gz
/keylime-selinux-43.1.1.tar.gz
/keylime-selinux-43.2.1.tar.gz

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
From 416d3906fe4071132d5cdc494f828ce3a909f336 Mon Sep 17 00:00:00 2001
From: Sergio Arroutbi <sarroutb@redhat.com>
Date: Fri, 20 Mar 2026 10:57:23 +0100
Subject: [PATCH] Remove enable_authentication agent config option
The Rust agent does not parse the enable_authentication
configuration option and always performs authentication.
Remove the option from both the agent.j2 template and the
2.5 mapping.json to avoid exposing a non-functional setting
to users.
Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com>
---
templates/2.5/agent.j2 | 7 -------
templates/2.5/mapping.json | 3 +--
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/templates/2.5/agent.j2 b/templates/2.5/agent.j2
index d5eec733d..5e9a1a706 100644
--- a/templates/2.5/agent.j2
+++ b/templates/2.5/agent.j2
@@ -274,10 +274,3 @@ ima_ml_path = "{{ agent.ima_ml_path }}"
# If set as a relative path, it will be considered from the root path "/".
# If set as an absolute path, it will use it without changes
measuredboot_ml_path = "{{ agent.measuredboot_ml_path }}"
-
-# Enable challenge-response authentication for push model attestation.
-# When enabled, the agent will authenticate with the verifier using TPM-based
-# proof of possession before sending attestation evidence.
-# This option is specific to the push attestation model.
-# The default is False (disabled).
-enable_authentication = {{ agent.enable_authentication }}
diff --git a/templates/2.5/mapping.json b/templates/2.5/mapping.json
index 522aa4ce9..4b198e768 100644
--- a/templates/2.5/mapping.json
+++ b/templates/2.5/mapping.json
@@ -13,8 +13,7 @@
"ima_ml_count_file": "/tmp/ima_ml_count",
"uefi_logs_evidence_version": "1.0",
"tls_accept_invalid_certs": "false",
- "tls_accept_invalid_hostnames": "false",
- "enable_authentication": "true"
+ "tls_accept_invalid_hostnames": "false"
}
},
"verifier": {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,151 @@
From 15f20d2dd2e63cc621295befef46bc4161a1f636 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Fri, 10 Apr 2026 13:22:44 +0200
Subject: [PATCH] shared_data: Ignore SIGTERM and SIGINT on Manager and parent
processes
When systemd stops the verifier (or registrar), SIGTERM is delivered to
the entire process group, including the multiprocessing Manager's server
process that hosts the shared policy cache. The Manager dies
immediately, but worker processes still have in-flight process_agent()
coroutines that need the cache, causing ConnectionResetError.
The same race occurs with SIGINT (Ctrl+C) when running the daemon in
the foreground.
Fix this in two parts:
1. Use SyncManager.start(initializer=...) to install SIG_IGN for both
SIGTERM and SIGINT in the Manager's server process, so it survives
process-group signals and stays available while workers drain.
2. Ignore SIGTERM and SIGINT in the new architecture's parent process
(start_multi) so it stays in tornado's monitor loop until all
children have drained and exited. Once all children exit, tornado
calls sys.exit(0), triggering atexit handlers which shut down the
Manager via IPC. Without this, the default signal disposition kills
the parent immediately (no atexit), leaving the Manager orphaned.
Resolves: #1882
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
---
keylime/shared_data.py | 28 +++++++++++++++++++++++++++-
keylime/web/base/server.py | 18 ++++++++++++++++++
test/test_verifier_server.py | 11 ++++++++---
3 files changed, 53 insertions(+), 4 deletions(-)
diff --git a/keylime/shared_data.py b/keylime/shared_data.py
index 09cbb97bb..494f2f53b 100644
--- a/keylime/shared_data.py
+++ b/keylime/shared_data.py
@@ -8,8 +8,10 @@
import multiprocessing as mp
import multiprocessing.process
import os
+import signal
import threading
import time
+from multiprocessing.managers import SyncManager
from typing import Any, Dict, List, Optional
from keylime import keylime_logging
@@ -17,6 +19,17 @@
logger = keylime_logging.init_logging("shared_data")
+def _manager_ignore_signals() -> None:
+ """Ignore SIGTERM and SIGINT in the Manager's server process.
+
+ Called as the ``initializer`` for ``SyncManager.start()`` so that
+ the Manager survives process-group signals (systemd SIGTERM, Ctrl+C)
+ and stays available while workers drain in-flight work.
+ """
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+
class FlatDictView:
"""A dictionary-like view over a flat key-value store.
@@ -127,7 +140,20 @@ def __init__(self) -> None:
# Use explicit context to ensure fork compatibility
# The Manager must be started BEFORE any fork() calls
ctx = mp.get_context("fork")
- self._manager = ctx.Manager()
+ # Use SyncManager directly (instead of the ctx.Manager() shortcut)
+ # so we can pass an initializer that makes the Manager's server
+ # process ignore SIGTERM and SIGINT. Without this, systemd's
+ # cgroup-wide SIGTERM (or Ctrl+C SIGINT in foreground) kills the
+ # Manager before workers finish draining, causing
+ # ConnectionResetError in proxy objects. The Manager is still
+ # cleanable via IPC shutdown message, process.kill(), or systemd
+ # SIGKILL escalation.
+ # Cannot use 'with' context manager here: the Manager must outlive
+ # __init__ and persist for the lifetime of SharedDataManager.
+ self._manager = SyncManager(ctx=ctx)
+ self._manager.start( # pylint: disable=consider-using-with
+ initializer=_manager_ignore_signals,
+ )
# CRITICAL FIX: Use a SINGLE flat dict instead of nested dicts
# Nested DictProxy objects have synchronization issues
diff --git a/keylime/web/base/server.py b/keylime/web/base/server.py
index 4dd02b79e..8e9cce69d 100644
--- a/keylime/web/base/server.py
+++ b/keylime/web/base/server.py
@@ -376,12 +376,30 @@ def start_multi(self) -> None:
self._pre_fork()
+ # Ignore SIGTERM/SIGINT in the parent so it stays in tornado's
+ # monitor loop (os.wait) until all children have drained and
+ # exited cleanly. Once all children exit, tornado calls
+ # sys.exit(0) which triggers atexit → SharedDataManager.cleanup()
+ # → Manager shutdown via IPC. Without this, the default signal
+ # disposition kills the parent immediately (no atexit), leaving
+ # the Manager process orphaned.
+ # Children inherit SIG_IGN but override it in
+ # _install_signal_handlers() before entering the event loop.
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+
# with StatsCollector():
# num = manager.Value('i', 0)
task_id = tornado.process.fork_processes(self.worker_count)
# num.value = num.value + 1
# print(num.value)
+ # Restore default signal disposition in children so they don't
+ # silently ignore SIGTERM/SIGINT before _install_signal_handlers()
+ # replaces these with asyncio-based handlers in start_single().
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+
# Remove the Manager's server process from multiprocessing's child
# tracking so Python's atexit handler does not try to join() it in
# child workers (the Manager was spawned by the parent).
diff --git a/test/test_verifier_server.py b/test/test_verifier_server.py
index e9a47ef70..7601b9cb0 100644
--- a/test/test_verifier_server.py
+++ b/test/test_verifier_server.py
@@ -300,10 +300,15 @@ def test_base_server_calls_post_fork_before_start_single(self):
assert match is not None
method_body = match.group(0)
+ # Strip comment lines to avoid false matches from mentions
+ # in comments (e.g. "# ... before start_single()").
+ code_lines = [line for line in method_body.splitlines() if not line.lstrip().startswith("#")]
+ code_body = "\n".join(code_lines)
+
# Extract the order of operations
- fork_index = method_body.find("fork_processes")
- post_fork_index = method_body.find("_post_fork")
- start_single_index = method_body.find("start_single()")
+ fork_index = code_body.find("fork_processes")
+ post_fork_index = code_body.find("_post_fork")
+ start_single_index = code_body.find("start_single()")
# All should be present
self.assertNotEqual(fork_index, -1, "fork_processes call not found")

View File

@ -0,0 +1,348 @@
From a50c7e50171d8f5999bdd927b6306f6d14974c57 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Thu, 16 Apr 2026 14:14:06 +0200
Subject: [PATCH 1/2] shared_data: Move SyncManager socket to /var/run/keylime/
The SyncManager's server process creates a Unix domain socket for IPC
with worker processes. By default, this socket was placed in /tmp with
a random name (listener-*).
Move the socket to /var/run/keylime/, following standard daemon
practice. Keylime already uses this directory for its ZeroMQ revocation
notification socket.
Changes:
- Pass explicit address to SyncManager so the socket is created at
/var/run/keylime/shared_data.<pid>.sock instead of /tmp/listener-*
- Add _ensure_runtime_dir() to create or validate the directory
- Add test conftest.py to redirect sockets to a temp directory
- Add pytest to test-requirements.txt for pylint to resolve imports
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
---
keylime/shared_data.py | 54 +++++++++++++++++++++++++++++++++++++-----
test-requirements.txt | 1 +
test/conftest.py | 30 +++++++++++++++++++++++
3 files changed, 79 insertions(+), 6 deletions(-)
create mode 100644 test/conftest.py
diff --git a/keylime/shared_data.py b/keylime/shared_data.py
index 494f2f53b..aef39bcc4 100644
--- a/keylime/shared_data.py
+++ b/keylime/shared_data.py
@@ -18,6 +18,23 @@
logger = keylime_logging.init_logging("shared_data")
+_RUNTIME_DIR = "/var/run/keylime"
+
+
+def _ensure_runtime_dir() -> None:
+ """Ensure the runtime directory exists with correct permissions.
+
+ Under systemd, ``tmpfiles.d`` creates ``/var/run/keylime/`` at boot.
+ This function provides a fallback for non-systemd execution and
+ validates permissions in either case.
+ """
+ os.makedirs(_RUNTIME_DIR, mode=0o700, exist_ok=True)
+ perms = os.stat(_RUNTIME_DIR).st_mode & 0o777
+ if perms != 0o700 or not os.access(_RUNTIME_DIR, os.W_OK | os.X_OK):
+ msg = f"{_RUNTIME_DIR} is not usable by the current process"
+ logger.error(msg)
+ raise PermissionError(msg)
+
def _manager_ignore_signals() -> None:
"""Ignore SIGTERM and SIGINT in the Manager's server process.
@@ -137,8 +154,20 @@ def __init__(self) -> None:
"""
logger.debug("Initializing SharedDataManager")
- # Use explicit context to ensure fork compatibility
- # The Manager must be started BEFORE any fork() calls
+ # Ensure /var/run/keylime/ exists with correct permissions
+ # before forking the Manager server process.
+ _ensure_runtime_dir()
+ self._socket_path = os.path.join(_RUNTIME_DIR, f"shared_data.{os.getpid()}.sock")
+
+ # Remove stale socket from a previous run (e.g. after a crash).
+ # CPython's SocketListener does not pre-unlink before bind().
+ try:
+ os.unlink(self._socket_path)
+ except (FileNotFoundError, PermissionError):
+ pass
+
+ # Use explicit context to ensure fork compatibility.
+ # The Manager must be started BEFORE any fork() calls.
ctx = mp.get_context("fork")
# Use SyncManager directly (instead of the ctx.Manager() shortcut)
# so we can pass an initializer that makes the Manager's server
@@ -150,7 +179,7 @@ def __init__(self) -> None:
# SIGKILL escalation.
# Cannot use 'with' context manager here: the Manager must outlive
# __init__ and persist for the lifetime of SharedDataManager.
- self._manager = SyncManager(ctx=ctx)
+ self._manager = SyncManager(address=self._socket_path, ctx=ctx)
self._manager.start( # pylint: disable=consider-using-with
initializer=_manager_ignore_signals,
)
@@ -162,8 +191,6 @@ def __init__(self) -> None:
self._lock = self._manager.Lock()
self._initialized_at = time.time()
- # Register handler to reinitialize manager connection after fork
- # This is needed because Manager uses network connections that don't survive fork
try:
self._parent_pid = os.getpid()
logger.debug("SharedDataManager initialized in process %d", self._parent_pid)
@@ -173,7 +200,10 @@ def __init__(self) -> None:
# Ensure cleanup on exit
atexit.register(self.cleanup)
- logger.info("SharedDataManager initialized successfully")
+ logger.info(
+ "SharedDataManager initialized successfully (socket: %s)",
+ self._socket_path,
+ )
def set_data(self, key: str, value: Any) -> None:
"""Store arbitrary pickleable data by key.
@@ -333,6 +363,18 @@ def cleanup(self) -> None:
except Exception:
logger.exception("Error during SharedDataManager shutdown")
+ # Remove socket file if it still exists. The Manager server
+ # process normally unlinks it on exit, but if it was killed
+ # (SIGKILL) the file may be left behind.
+ socket_path = getattr(self, "_socket_path", None)
+ if socket_path:
+ try:
+ os.unlink(socket_path)
+ except FileNotFoundError:
+ pass
+ except OSError as e:
+ logger.debug("Could not remove socket file %s: %s", socket_path, e)
+
def deregister_child(self) -> None:
"""Remove the Manager's server process from multiprocessing's child tracking.
diff --git a/test-requirements.txt b/test-requirements.txt
index bdd44e3e9..bf74580a9 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,6 +1,7 @@
dbus-python
# modules required for pylint
setuptools
+pytest
# packages required for mypy
sqlalchemy-stubs
types-python-dateutil
diff --git a/test/conftest.py b/test/conftest.py
new file mode 100644
index 000000000..da2843922
--- /dev/null
+++ b/test/conftest.py
@@ -0,0 +1,30 @@
+"""Shared pytest fixtures for keylime tests."""
+
+import shutil
+import tempfile
+from unittest.mock import patch
+
+import pytest
+
+from keylime.shared_data import cleanup_global_shared_memory
+
+
+@pytest.fixture(autouse=True)
+def _shared_data_runtime_dir():
+ """Redirect SharedDataManager sockets to a temporary directory.
+
+ The SyncManager creates Unix domain sockets in /var/run/keylime/,
+ which may not be writable by the test user. This fixture patches
+ the runtime directory to a per-test temp directory so that tests
+ work in any environment.
+
+ After each test, any global SharedDataManager is shut down to
+ prevent stale managers from referencing deleted temp directories.
+ """
+ tmpdir = tempfile.mkdtemp()
+ with patch("keylime.shared_data._RUNTIME_DIR", tmpdir):
+ yield
+ # Shut down any global SharedDataManager left alive by the test
+ # so the next test starts fresh with a new temp directory.
+ cleanup_global_shared_memory()
+ shutil.rmtree(tmpdir, ignore_errors=True)
From 712ab6c841e258e463f858904bfc0991f704a3b9 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Thu, 16 Apr 2026 14:14:45 +0200
Subject: [PATCH 2/2] installer: Add tmpfiles.d config for all keylime
directories
Add keylime-tmpfiles.conf to manage all keylime directories.
This includes:
- /var/run/keylime (runtime IPC sockets)
- /var/lib/keylime (persistent state)
- /etc/keylime and config snippet directories (configuration)
- TPM certificate store copy from /usr/share to /var/lib
Simplify installer.sh to avoid redundant directory creation and
ownership setting. The installer only needs to install the tmpfiles.d
config to /usr/lib/tmpfiles.d/keylime.conf and apply it immediately with
systemd-tmpfiles --create so the directories exist before the services
start.
The installer validates the TPM cert store source exists before copying
and includes a non-systemd fallback for manual directory creation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
---
services/installer.sh | 61 ++++++++++++++++++++++++++--------
services/keylime-tmpfiles.conf | 40 ++++++++++++++++++++++
2 files changed, 87 insertions(+), 14 deletions(-)
create mode 100644 services/keylime-tmpfiles.conf
diff --git a/services/installer.sh b/services/installer.sh
index f34027c61..f462f136b 100755
--- a/services/installer.sh
+++ b/services/installer.sh
@@ -11,7 +11,7 @@ fi
BASEDIR=$(dirname "$0")
# check keylime scripts directory (same for verifier, agent, registrar)
-KEYLIMEDIR=$(dirname $(whereis keylime_verifier | cut -d " " -f 2))
+KEYLIMEDIR=$(dirname "$(whereis keylime_verifier | cut -d " " -f 2)")
if [[ $KEYLIMEDIR == "." ]]; then
echo "Unable to find keylime scripts" 1>&2
exit 1
@@ -20,8 +20,8 @@ fi
echo "Using keylime scripts directory: ${KEYLIMEDIR}"
# prepare keylime service files and store them in systemd path
-sed "s|KEYLIMEDIR|$KEYLIMEDIR|g" $BASEDIR/keylime_registrar.service.template > /etc/systemd/system/keylime_registrar.service
-sed "s|KEYLIMEDIR|$KEYLIMEDIR|g" $BASEDIR/keylime_verifier.service.template > /etc/systemd/system/keylime_verifier.service
+sed "s|KEYLIMEDIR|$KEYLIMEDIR|g" "$BASEDIR/keylime_registrar.service.template" > /etc/systemd/system/keylime_registrar.service
+sed "s|KEYLIMEDIR|$KEYLIMEDIR|g" "$BASEDIR/keylime_verifier.service.template" > /etc/systemd/system/keylime_verifier.service
echo "Creating keylime user if it not exists"
if ! getent passwd keylime >/dev/null; then
@@ -30,23 +30,56 @@ if ! getent passwd keylime >/dev/null; then
keylime
fi
-echo "Changing files to be owned by the keylime user"
-# Create all directories required if not there
-mkdir -p /var/lib/keylime
-mkdir -p /var/log/keylime
-mkdir -p /var/run/keylime
+# install TPM certificate store to /usr/share/keylime/
+# tmpfiles.d will copy this to /var/lib/keylime/tpm_cert_store
+TPM_CERT_STORE_SRC="$BASEDIR/../tpm_cert_store"
+if [[ ! -d "$TPM_CERT_STORE_SRC" ]]; then
+ echo "Missing TPM certificate store: $TPM_CERT_STORE_SRC" 1>&2
+ exit 1
+fi
+
+mkdir -p /usr/share/keylime
+cp -a "$TPM_CERT_STORE_SRC" /usr/share/keylime/ || exit 1
-chown keylime:keylime -R /etc/keylime
-chown keylime:keylime -R /var/lib/keylime
-chown keylime:keylime -R /var/log/keylime
-chown keylime:keylime -R /var/run/keylime
+# install tmpfiles.d config for keylime directories
+mkdir -p /usr/lib/tmpfiles.d
+cp "$BASEDIR/keylime-tmpfiles.conf" /usr/lib/tmpfiles.d/keylime.conf
+
+# apply the tmpfiles.d config immediately to create directories with correct ownership
+if command -v systemd-tmpfiles >/dev/null 2>&1; then
+ systemd-tmpfiles --create keylime.conf
+else
+ echo "Warning: systemd-tmpfiles not found, creating directories manually"
+ # Create essential directories as fallback for non-systemd systems
+ mkdir -p /var/run/keylime /var/lib/keylime \
+ /etc/keylime/ca.conf.d \
+ /etc/keylime/logging.conf.d \
+ /etc/keylime/verifier.conf.d \
+ /etc/keylime/registrar.conf.d \
+ /etc/keylime/tenant.conf.d \
+ /etc/keylime/agent.conf.d
+ chown keylime:keylime /var/run/keylime /var/lib/keylime
+ chmod 700 /var/run/keylime /var/lib/keylime
+ # Mirror tmpfiles.d Z/z semantics: recursively set ownership and
+ # file permissions under /etc/keylime, then fix directories to 0500.
+ chown -R keylime:keylime /etc/keylime
+ find /etc/keylime -type f -exec chmod 400 {} \;
+ find /etc/keylime -type d -exec chmod 500 {} \;
+ # Copy TPM cert store from /usr/share to /var/lib only if the
+ # target does not exist yet (mirrors the tmpfiles.d C directive).
+ # This preserves operator-added EK certificates.
+ if [ -d /usr/share/keylime/tpm_cert_store ] && [ ! -d /var/lib/keylime/tpm_cert_store ]; then
+ cp -r /usr/share/keylime/tpm_cert_store /var/lib/keylime/
+ chown -R keylime:keylime /var/lib/keylime/tpm_cert_store
+ find /var/lib/keylime/tpm_cert_store -type f -exec chmod 400 {} \;
+ chmod 500 /var/lib/keylime/tpm_cert_store
+ fi
+fi
# set permissions
chmod 664 /etc/systemd/system/keylime_registrar.service
chmod 664 /etc/systemd/system/keylime_verifier.service
-chmod 700 /var/run/keylime
-
# enable at startup
systemctl enable keylime_registrar.service
systemctl enable keylime_verifier.service
diff --git a/services/keylime-tmpfiles.conf b/services/keylime-tmpfiles.conf
new file mode 100644
index 000000000..f3c0b43d6
--- /dev/null
+++ b/services/keylime-tmpfiles.conf
@@ -0,0 +1,40 @@
+d /run/keylime 0700 keylime keylime -
+
+d /var/lib/keylime 0700 keylime keylime -
+
+d /etc/keylime 0500 keylime keylime -
+d /etc/keylime/ca.conf.d 0500 keylime keylime -
+d /etc/keylime/logging.conf.d 0500 keylime keylime -
+d /etc/keylime/verifier.conf.d 0500 keylime keylime -
+d /etc/keylime/registrar.conf.d 0500 keylime keylime -
+d /etc/keylime/tenant.conf.d 0500 keylime keylime -
+d /etc/keylime/agent.conf.d 0500 keylime keylime -
+
+# TPM certificate store.
+# Copy the cert store from /usr/share/keylime/tpm_cert_store
+# to /var/lib/keylime/tpm_cert_store.
+# Files inside /var/lib/keylime/tpm_cert_store/ have
+# 0400 permission and are owned by keylime/keylime,
+# while /var/lib/keylime/tpm_cert_store/ itself has
+# permission 0500, also owned by keylime/keylime.
+C /var/lib/keylime/tpm_cert_store 0500 keylime keylime - /usr/share/keylime/tpm_cert_store
+Z /var/lib/keylime/tpm_cert_store 0400 keylime keylime -
+z /var/lib/keylime/tpm_cert_store 0500 keylime keylime -
+# Finally, /var/lib/keylime itself has 0700 permission,
+# and is owned by keylime/keylime.
+z /var/lib/keylime 0700 keylime keylime -
+
+# Keylime configuration in /etc/keylime has permission 0400
+# owned by keylime/keylime, while snippet directories and
+# the actual /etc/keylime directory have permission 0500,
+# also owned by keylime/keylime.
+Z /etc/keylime 0400 keylime keylime -
+# Now fix the directories:
+z /etc/keylime/ca.conf.d 0500 keylime keylime -
+z /etc/keylime/logging.conf.d 0500 keylime keylime -
+z /etc/keylime/verifier.conf.d 0500 keylime keylime -
+z /etc/keylime/registrar.conf.d 0500 keylime keylime -
+z /etc/keylime/tenant.conf.d 0500 keylime keylime -
+z /etc/keylime/agent.conf.d 0500 keylime keylime -
+# And finally, /etc/keylime itself.
+z /etc/keylime 0500 keylime keylime -

View File

@ -1,5 +1,5 @@
%global srcname keylime
%global policy_version 43.1.1
%global policy_version 43.2.1
# Package is actually noarch, but it has an optional dependency that is
# arch-specific.
@ -9,7 +9,7 @@
Name: keylime
Version: 7.14.1
Release: 4%{?dist}
Release: 5%{?dist}
Summary: Open source TPM software for Bootstrapping and Maintaining Trust
URL: https://github.com/keylime/keylime
@ -39,6 +39,21 @@ Patch: 0012-fix-mem-leak-remove-unbounded-functools.cache-from-l.patch
# Backport https://github.com/keylime/keylime/pulls/1874
Patch: 0013-fix-verifier-race-condition-on-agent-delete.patch
# RHEL-151493 - verifier graceful shutdown.
# Backport:
# - https://github.com/keylime/keylime/pull/1809
# - https://github.com/keylime/keylime/pull/1868
# - https://github.com/keylime/keylime/pull/1855
# - https://github.com/keylime/keylime/pull/1869
# - https://github.com/keylime/keylime/pull/1883
# - https://github.com/keylime/keylime/pull/1886
Patch: 0014-push-attestation-documentation.patch
Patch: 0015-remove-enable-authentication-config-option.patch
Patch: 0016-docs-push-attestation-config-tables.patch
Patch: 0017-verifier-graceful-shutdown.patch
Patch: 0018-ignore-sigterm-sigint-manager-parent-processes.patch
Patch: 0019-move-socket-var-run.patch
# Main program: Apache-2.0
# Icons: MIT
License: Apache-2.0 AND MIT
@ -59,6 +74,7 @@ BuildRequires: python3-tornado
BuildRequires: python3-sqlalchemy
BuildRequires: python3-lark
BuildRequires: python3-psutil
BuildRequires: python3-pytest
BuildRequires: python3-pyyaml
BuildRequires: python3-jsonschema
BuildRequires: python3-setuptools
@ -316,7 +332,7 @@ export KEYLIME_CA_CONFIG="${CONF_TEMP_DIR}/ca.conf"
export KEYLIME_LOGGING_CONFIG="${CONF_TEMP_DIR}/logging.conf"
# Run the tests.
%{python3} -m unittest
%pytest
# Cleanup.
[ "${CONF_TEMP_DIR}" ] && rm -rf "${CONF_TEMP_DIR}"

View File

@ -1,2 +1,2 @@
SHA512 (v7.14.1.tar.gz) = d94cd1e25ec31e43fea05d0c404dd25c05b6b28435db2f8ca34546f6ff8bfd5da12d2dcd3b5cf4772c44688ae8968468dc2470da23596714e7615dbf6dfbe841
SHA512 (keylime-selinux-43.1.1.tar.gz) = 1b0a850f68321e4872bb01eb99f5b000f1b5cbe3f1882e781bff519868ba5f4ca50f25b328b3662895969833add5c30d00e2a2361d2d626e7cffd95c0243ec39
SHA512 (keylime-selinux-43.2.1.tar.gz) = 8cb8b032819d3b87e1dceaa7094385b4468c0d6be1e5dfc6d8b6758e6281def5255120ff34d71b5d4bc7fe9b9e960f1a98011e5bf7149df5704d0bbf6afbfad3