Compare commits

...

No commits in common. "c9-beta" and "c10s" have entirely different histories.

26 changed files with 227 additions and 8033 deletions

1
.fmf/version Normal file
View File

@ -0,0 +1 @@
1

38
.gitignore vendored
View File

@ -1,2 +1,36 @@
SOURCES/keylime-selinux-1.2.0.tar.gz
SOURCES/v7.3.0.tar.gz
/5.4.1.tar.gz
/keylime-5.5.0-1.fc32.src.rpm
/5.5.0.tar.gz
/5.6.0.tar.gz
/5.6.1.tar.gz
/5.6.2.tar.gz
/5.7.0.tar.gz
/5.7.1.tar.gz
/5.7.2.tar.gz
/5.8.0.tar.gz
/5.8.1.tar.gz
/6.0.1.tar.gz
/6.1.0.tar.gz
/v6.3.0.tar.gz
/v6.3.1.tar.gz
/v6.3.2.tar.gz
/v6.4.0.tar.gz
/v6.4.1.tar.gz
/v6.4.2.tar.gz
/v6.4.3.tar.gz
/keylime-selinux-1.0.0.tar.gz
/v6.5.3.tar.gz
/v6.6.0.tar.gz
/v6.7.0.tar.gz
/v6.8.0.tar.gz
/v7.0.0.tar.gz
/v7.2.5.tar.gz
/v7.3.0.tar.gz
/v7.4.0.tar.gz
/v7.5.0.tar.gz
/keylime-selinux-38.1.0.tar.gz
/v7.6.0.tar.gz
/v7.7.0.tar.gz
/v7.8.0.tar.gz
/v7.9.0.tar.gz
/v7.12.1.tar.gz

View File

@ -1,2 +0,0 @@
9130beade415b8e3b02aac8d06678f2c45b939fe SOURCES/keylime-selinux-1.2.0.tar.gz
400e2b019060b8a6cc255dbfc14c582121acbee1 SOURCES/v7.3.0.tar.gz

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# keylime
The keylime package

View File

@ -1,104 +0,0 @@
Subject: [PATCH] Remove usage of Required/NotRequired typing_ext
Since we do not yet have typing_extensions packaged, let us not
use its functionality yet.
---
keylime/ima/types.py | 33 ++++++++++++++-------------------
keylime/registrar_client.py | 8 +-------
2 files changed, 15 insertions(+), 26 deletions(-)
diff --git a/keylime/ima/types.py b/keylime/ima/types.py
index 99f0aa7..a0fffdf 100644
--- a/keylime/ima/types.py
+++ b/keylime/ima/types.py
@@ -6,11 +6,6 @@ if sys.version_info >= (3, 8):
else:
from typing_extensions import Literal, TypedDict
-if sys.version_info >= (3, 11):
- from typing import NotRequired, Required
-else:
- from typing_extensions import NotRequired, Required
-
### Types for tpm_dm.py
RuleAttributeType = Optional[Union[int, str, bool]]
@@ -51,7 +46,7 @@ class Rule(TypedDict):
class Policies(TypedDict):
- version: Required[int]
+ version: int
match_on: MatchKeyType
rules: Dict[str, Rule]
@@ -60,27 +55,27 @@ class Policies(TypedDict):
class RPMetaType(TypedDict):
- version: Required[int]
- generator: NotRequired[int]
- timestamp: NotRequired[str]
+ version: int
+ generator: int
+ timestamp: str
class RPImaType(TypedDict):
- ignored_keyrings: Required[List[str]]
- log_hash_alg: Required[Literal["sha1", "sha256", "sha384", "sha512"]]
+ ignored_keyrings: List[str]
+ log_hash_alg: Literal["sha1", "sha256", "sha384", "sha512"]
dm_policy: Optional[Policies]
RuntimePolicyType = TypedDict(
"RuntimePolicyType",
{
- "meta": Required[RPMetaType],
- "release": NotRequired[int],
- "digests": Required[Dict[str, List[str]]],
- "excludes": Required[List[str]],
- "keyrings": Required[Dict[str, List[str]]],
- "ima": Required[RPImaType],
- "ima-buf": Required[Dict[str, List[str]]],
- "verification-keys": Required[str],
+ "meta": RPMetaType,
+ "release": int,
+ "digests": Dict[str, List[str]],
+ "excludes": List[str],
+ "keyrings": Dict[str, List[str]],
+ "ima": RPImaType,
+ "ima-buf": Dict[str, List[str]],
+ "verification-keys": str,
},
)
diff --git a/keylime/registrar_client.py b/keylime/registrar_client.py
index ab28977..ea5341b 100644
--- a/keylime/registrar_client.py
+++ b/keylime/registrar_client.py
@@ -13,12 +13,6 @@ if sys.version_info >= (3, 8):
else:
from typing_extensions import TypedDict
-if sys.version_info >= (3, 11):
- from typing import NotRequired
-else:
- from typing_extensions import NotRequired
-
-
class RegistrarData(TypedDict):
ip: Optional[str]
port: Optional[str]
@@ -27,7 +21,7 @@ class RegistrarData(TypedDict):
aik_tpm: str
ek_tpm: str
ekcert: Optional[str]
- provider_keys: NotRequired[Dict[str, str]]
+ provider_keys: Dict[str, str]
logger = keylime_logging.init_logging("registrar_client")
--
2.41.0

View File

@ -1,27 +0,0 @@
From e8a1fa55ff0892ee2380e832ac94abc629b401d6 Mon Sep 17 00:00:00 2001
From: Patrik Koncity <pkoncity@redhat.com>
Date: Thu, 10 Aug 2023 07:47:04 -0400
Subject: [PATCH 2/2] Allow keylime_server_t tcp connect to several domains
---
keylime-selinux-1.2.0/keylime.te | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/keylime-selinux-1.2.0/keylime.te b/keylime-selinux-1.2.0/keylime.te
index 8d47d26..8e6487b 100644
--- a/keylime-selinux-1.2.0/keylime.te
+++ b/keylime-selinux-1.2.0/keylime.te
@@ -83,6 +83,10 @@ allow keylime_server_t self:udp_socket create_stream_socket_perms;
manage_dirs_pattern(keylime_server_t, keylime_log_t, keylime_log_t)
manage_files_pattern(keylime_server_t, keylime_log_t, keylime_log_t)
+corenet_tcp_connect_http_cache_port(keylime_server_t)
+corenet_tcp_connect_mysqld_port(keylime_server_t)
+corenet_tcp_connect_postgresql_port(keylime_server_t)
+
fs_getattr_all_fs(keylime_server_t)
fs_rw_inherited_tmpfs_files(keylime_server_t)
--
2.39.3

View File

@ -1,51 +0,0 @@
From b8e26ca5e98e1b842db2fc21411962d40f27c557 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Tue, 15 Aug 2023 07:19:28 -0400
Subject: [PATCH 3/4] Use version 2.0 as the minimum for the configuration
---
keylime/cmd/convert_config.py | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/keylime/cmd/convert_config.py b/keylime/cmd/convert_config.py
index ac28151..1d71b99 100755
--- a/keylime/cmd/convert_config.py
+++ b/keylime/cmd/convert_config.py
@@ -191,7 +191,13 @@ def output(components: List[str], config: RawConfigParser, templates: str, outdi
# Check that there are templates for all components
for component in components:
- version = config[component]["version"].strip('" ')
+ # Minimum version.
+ version = '2.0'
+ if "version" in config[component]:
+ version = config[component]["version"].strip('" ')
+ else:
+ config[component]["version"] = version
+
version_dir = os.path.join(templates, version)
if not os.path.isdir(version_dir):
raise Exception(f"Could not find directory {version_dir}")
@@ -292,15 +298,15 @@ def process_mapping(
raise Exception("Invalid version number found in old configuration")
except (configparser.NoOptionError, configparser.NoSectionError):
- print(f"No version found in old configuration for {component}, using '1.0'")
- old_version = (1, 0)
+ print(f"No version found in old configuration for {component}, using '2.0'")
+ old_version = (2, 0)
else:
# If the old_version does not contain the component from the
# mapping, use the minimum version to use defaults
- old_version = (1, 0)
+ old_version = (2, 0)
# Skip versions lower than the current version
- if old_version >= new_version:
+ if old_version >= new_version and component in old_config:
new[component] = old_config[component]
continue
--
2.39.3

View File

@ -1,88 +0,0 @@
From dbd521e8e8f0ffd9ace79c7b9b888f4cb89488f9 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Tue, 15 Aug 2023 06:09:37 -0400
Subject: [PATCH 4/4] Duplicate str_to_version for the upgrade tool
So it does not depend on python-keylime
---
keylime/cmd/convert_config.py | 24 ++++++++++++++++++++++--
templates/2.0/adjust.py | 22 ++++++++++++++++++++--
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/keylime/cmd/convert_config.py b/keylime/cmd/convert_config.py
index c1c6180..cad5e31 100755
--- a/keylime/cmd/convert_config.py
+++ b/keylime/cmd/convert_config.py
@@ -84,13 +84,33 @@ import importlib.util
import itertools
import json
import os
+import re
import shutil
from configparser import RawConfigParser
-from typing import List, Optional, Tuple
+from typing import List, Optional, Tuple, Union
from jinja2 import Template
-from keylime.common.version import str_to_version
+
+def str_to_version(v_str: str) -> Union[Tuple[int, int], None]:
+ """
+ Validates the string format and converts the provided string to a tuple of
+ ints which can be sorted and compared.
+
+ :returns: Tuple with version number parts converted to int. In case of
+ invalid version string, returns None
+ """
+
+ # Strip to remove eventual quotes and spaces
+ v_str = v_str.strip('" ')
+
+ m = re.match(r"^(\d+)\.(\d+)$", v_str)
+
+ if not m:
+ return None
+
+ return (int(m.group(1)), int(m.group(2)))
+
COMPONENTS = ["agent", "verifier", "tenant", "registrar", "ca", "logging"]
diff --git a/templates/2.0/adjust.py b/templates/2.0/adjust.py
index 312b790..c1e582a 100644
--- a/templates/2.0/adjust.py
+++ b/templates/2.0/adjust.py
@@ -2,9 +2,27 @@ import ast
import configparser
import re
from configparser import RawConfigParser
-from typing import Dict, List, Optional, Tuple
+from typing import Dict, List, Optional, Tuple, Union
-from keylime.common.version import str_to_version
+
+def str_to_version(v_str: str) -> Union[Tuple[int, int], None]:
+ """
+ Validates the string format and converts the provided string to a tuple of
+ ints which can be sorted and compared.
+
+ :returns: Tuple with version number parts converted to int. In case of
+ invalid version string, returns None
+ """
+
+ # Strip to remove eventual quotes and spaces
+ v_str = v_str.strip('" ')
+
+ m = re.match(r"^(\d+)\.(\d+)$", v_str)
+
+ if not m:
+ return None
+
+ return (int(m.group(1)), int(m.group(2)))
def adjust(config: RawConfigParser, mapping: Dict) -> None: # pylint: disable=unused-argument
--
2.39.3

View File

@ -1,50 +0,0 @@
From f2432efbeb7b6305067111bb3a77ef5d7da4eb5b Mon Sep 17 00:00:00 2001
From: Thore Sommer <mail@thson.de>
Date: Thu, 10 Aug 2023 16:15:57 +0300
Subject: [PATCH 5/6] elchecking/example: add ignores for
EV_PLATFORM_CONFIG_FLAGS
These are generated by edk2 when used with QEMU, but we do not have a
reference for them.
Signed-off-by: Thore Sommer <mail@thson.de>
---
keylime/mba/elchecking/example.py | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/keylime/mba/elchecking/example.py b/keylime/mba/elchecking/example.py
index 8885227..921db4e 100644
--- a/keylime/mba/elchecking/example.py
+++ b/keylime/mba/elchecking/example.py
@@ -75,7 +75,6 @@ shim_authcode_sha256_no_secureboot = tests.obj_test(
kernel_cmdline=tests.type_test(str),
)
-
allowed_kernel_list_test_no_secureboot = tests.list_test(shim_authcode_sha256_no_secureboot)
@@ -303,6 +302,20 @@ class Example(policies.Policy):
),
),
)
+ # edk2 measures up to 4 of those events, where we do not have a good way to get a reference
+ # See:
+ # - https://github.com/keylime/keylime/issues/1393
+ # - https://github.com/tianocore/edk2/commit/935343cf1639a28530904a1e8d73d6517a07cbff
+ dispatcher.set(
+ (1, "EV_PLATFORM_CONFIG_FLAGS"),
+ tests.Or(
+ tests.OnceTest(tests.AcceptAll()),
+ tests.OnceTest(tests.AcceptAll()),
+ tests.OnceTest(tests.AcceptAll()),
+ tests.OnceTest(tests.AcceptAll()),
+ ),
+ )
+
dispatcher.set((4, "EV_EFI_ACTION"), tests.EvEfiActionTest(4))
for pcr in range(8):
dispatcher.set((pcr, "EV_SEPARATOR"), tests.EvSeperatorTest())
--
2.39.3

View File

@ -1,43 +0,0 @@
From ed213b9533535ceae5026b2fab274f80bcc58cb8 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Tue, 15 Aug 2023 09:18:32 -0400
Subject: [PATCH 6/6] Revert mapping changes
---
templates/2.0/mapping.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/templates/2.0/mapping.json b/templates/2.0/mapping.json
index 66addbc..0036b63 100644
--- a/templates/2.0/mapping.json
+++ b/templates/2.0/mapping.json
@@ -207,7 +207,7 @@
"registrar_port": {
"section": "cloud_verifier",
"option": "registrar_port",
- "default": "8881"
+ "default": "8891"
},
"tls_dir": {
"section": "cloud_verifier",
@@ -232,7 +232,7 @@
"server_key_password": {
"section": "cloud_verifier",
"option": "private_key_pw",
- "default": ""
+ "default": "default"
},
"enable_agent_mtls": {
"section": "cloud_verifier",
@@ -558,7 +558,7 @@
"server_key_password": {
"section": "registrar",
"option": "private_key_pw",
- "default": ""
+ "default": "default"
},
"server_cert": {
"section": "registrar",
--
2.39.3

View File

@ -1,90 +0,0 @@
From 3dc40e8b1878d84045ee80cb6d216348713c048a Mon Sep 17 00:00:00 2001
From: Karel Srot <ksrot@redhat.com>
Date: Tue, 15 Aug 2023 10:00:50 +0200
Subject: [PATCH 7/7] Handle session close using a session manager
Resolves https://github.com/keylime/keylime/issues/1455
Signed-off-by: Karel Srot <ksrot@redhat.com>
---
keylime/revocation_notifier.py | 50 +++++++++++++++++-----------------
packit-ci.fmf | 1 +
2 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/keylime/revocation_notifier.py b/keylime/revocation_notifier.py
index 31a3095..5cc8b1a 100644
--- a/keylime/revocation_notifier.py
+++ b/keylime/revocation_notifier.py
@@ -132,32 +132,32 @@ def notify_webhook(tosend: Dict[str, Any]) -> None:
def worker_webhook(tosend: Dict[str, Any], url: str) -> None:
interval = config.getfloat("verifier", "retry_interval")
exponential_backoff = config.getboolean("verifier", "exponential_backoff")
- session = requests.session()
- logger.info("Sending revocation event via webhook...")
- for i in range(config.getint("verifier", "max_retries")):
- next_retry = retry.retry_time(exponential_backoff, interval, i, logger)
- try:
- response = session.post(url, json=tosend, timeout=5)
- if response.status_code in [200, 202]:
- break
-
- logger.debug(
- "Unable to publish revocation message %d times via webhook, "
- "trying again in %d seconds. "
- "Server returned status code: %s",
- i,
- next_retry,
- response.status_code,
- )
- except requests.exceptions.RequestException as e:
- logger.debug(
- "Unable to publish revocation message %d times via webhook, trying again in %d seconds: %s",
- i,
- next_retry,
- e,
- )
+ with requests.Session() as session:
+ logger.info("Sending revocation event via webhook...")
+ for i in range(config.getint("verifier", "max_retries")):
+ next_retry = retry.retry_time(exponential_backoff, interval, i, logger)
+ try:
+ response = session.post(url, json=tosend, timeout=5)
+ if response.status_code in [200, 202]:
+ break
+
+ logger.debug(
+ "Unable to publish revocation message %d times via webhook, "
+ "trying again in %d seconds. "
+ "Server returned status code: %s",
+ i,
+ next_retry,
+ response.status_code,
+ )
+ except requests.exceptions.RequestException as e:
+ logger.debug(
+ "Unable to publish revocation message %d times via webhook, trying again in %d seconds: %s",
+ i,
+ next_retry,
+ e,
+ )
- time.sleep(next_retry)
+ time.sleep(next_retry)
w = functools.partial(worker_webhook, tosend, url)
t = threading.Thread(target=w, daemon=True)
diff --git a/packit-ci.fmf b/packit-ci.fmf
index f4d2dae..7abe313 100644
--- a/packit-ci.fmf
+++ b/packit-ci.fmf
@@ -108,6 +108,7 @@ adjust:
- /setup/configure_tpm_emulator
- /setup/install_upstream_keylime
- /setup/install_rust_keylime_from_copr
+ - /setup/configure_kernel_ima_module/ima_policy_simple
- /functional/basic-attestation-on-localhost
- /functional/basic-attestation-with-custom-certificates
- /functional/basic-attestation-without-mtls
--
2.41.0

View File

@ -1,31 +0,0 @@
From aa891f456d5cf0fc23e16d87fb28efc79a0d8073 Mon Sep 17 00:00:00 2001
From: Marcio Silva <marcio.a.silva@ibm.com>
Date: Wed, 23 Aug 2023 11:24:59 -0300
Subject: [PATCH 8/8] verifier: should read parameters from verifier.conf only
Single-line fix for #1446
The verifier should read "durable attestation" backend imports from
verifier.conf (and NOT from registrar.conf)
Signed-off-by: Marcio Silva <marcio.a.silva@ibm.com>
---
keylime/cloud_verifier_tornado.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/keylime/cloud_verifier_tornado.py b/keylime/cloud_verifier_tornado.py
index d65cb63..261022a 100644
--- a/keylime/cloud_verifier_tornado.py
+++ b/keylime/cloud_verifier_tornado.py
@@ -51,7 +51,7 @@ except SQLAlchemyError as err:
sys.exit(1)
try:
- rmc = record.get_record_mgt_class(config.get("registrar", "durable_attestation_import", fallback=""))
+ rmc = record.get_record_mgt_class(config.get("verifier", "durable_attestation_import", fallback=""))
if rmc:
rmc = rmc("verifier")
except record.RecordManagementException as rme:
--
2.41.0

View File

@ -1,48 +0,0 @@
From 9e5ac9f25cd400b16d5969f531cee28290543f2a Mon Sep 17 00:00:00 2001
From: Marcio Silva <marcio.a.silva@ibm.com>
Date: Wed, 12 Jul 2023 12:05:47 -0300
Subject: [PATCH] Fix for CVE-2023-38201 (Security Advisory
GHSA-f4r5-q63f-gcww)
In addition to remove the offending message, this patch also ensures
deletion of an agent's record from the database in case of failure after
a single attempt.
Signed-off-by: Marcio Silva <marcio.a.silva@ibm.com>
---
keylime/registrar_common.py | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/keylime/registrar_common.py b/keylime/registrar_common.py
index 1fd97cd0c..7f15ae430 100644
--- a/keylime/registrar_common.py
+++ b/keylime/registrar_common.py
@@ -250,7 +250,9 @@ def get_network_params(
try:
port = int(port)
if port < 1 or port > 65535:
- logger.warning("Contact port for agent %s is not a number between 1 and got: %s.", agent_id, port)
+ logger.warning(
+ "Contact port for agent %s is not a number between 1 and 65535 got: %s.", agent_id, port
+ )
port = None
except ValueError:
logger.warning("Contact port for agent %s is not a valid number got: %s.", agent_id, port)
@@ -447,7 +449,16 @@ def do_PUT(self) -> None:
logger.error("SQLAlchemy Error: %s", e)
raise
else:
- raise Exception(f"Auth tag {auth_tag} does not match expected value {ex_mac}")
+ if agent_id and session.query(RegistrarMain).filter_by(agent_id=agent_id).delete():
+ try:
+ session.commit()
+ except SQLAlchemyError as e:
+ logger.error("SQLAlchemy Error: %s", e)
+ raise
+
+ raise Exception(
+ f"Auth tag {auth_tag} for agent {agent_id} does not match expected value. The agent has been deleted from database, and a restart of it will be required"
+ )
web_util.echo_json_response(self, 200, "Success")
logger.info("PUT activated: %s", agent_id)

View File

@ -1,69 +0,0 @@
From e17d5a6a47c1405a799a06754d3e905856e3035d Mon Sep 17 00:00:00 2001
From: florian <264356+flozilla@users.noreply.github.com>
Date: Tue, 11 Jul 2023 21:31:27 +0200
Subject: [PATCH 10/10] CVE-2023-38200
Extend Registrar SSL socket to be non-blocking
Fixes: CVE-2023-38200
Upstream:
- https://github.com/keylime/keylime/commit/c68d8f0b7
- https://github.com/keylime/keylime/commit/27d515f4b
---
keylime/registrar_common.py | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/keylime/registrar_common.py b/keylime/registrar_common.py
index d1d20dd..6441e3b 100644
--- a/keylime/registrar_common.py
+++ b/keylime/registrar_common.py
@@ -2,8 +2,10 @@ import base64
import http.server
import ipaddress
import os
+import select
import signal
import socket
+import ssl
import sys
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
@@ -77,6 +79,25 @@ class BaseHandler(BaseHTTPRequestHandler, SessionManager):
class ProtectedHandler(BaseHandler):
+ def handle(self) -> None:
+ """Need to perform SSL handshake here, as
+ do_handshake_on_connect=False for non-blocking SSL socket"""
+ while True:
+ try:
+ self.request.do_handshake()
+ break
+ except ssl.SSLWantReadError:
+ select.select([self.request], [], [])
+ except ssl.SSLWantWriteError:
+ select.select([], [self.request], [])
+ except ssl.SSLError as e:
+ logger.error("SSL connection error: %s", e)
+ return
+ except Exception as e:
+ logger.error("General communication failure: %s", e)
+ return
+ BaseHTTPRequestHandler.handle(self)
+
def do_HEAD(self) -> None:
"""HEAD not supported"""
web_util.echo_json_response(self, 405, "HEAD not supported")
@@ -494,7 +515,7 @@ def start(host: str, tlsport: int, port: int) -> None:
protected_server = RegistrarServer((host, tlsport), ProtectedHandler)
context = web_util.init_mtls("registrar", logger=logger)
if context is not None:
- protected_server.socket = context.wrap_socket(protected_server.socket, server_side=True)
+ protected_server.socket = context.wrap_socket(protected_server.socket, server_side=True, do_handshake_on_connect=False)
thread_protected_server = threading.Thread(target=protected_server.serve_forever)
# Set up the unprotected registrar server
--
2.41.0

View File

@ -1,244 +0,0 @@
From b0cf69c9db20eb319ea2e90c22f500e09b704224 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Wed, 23 Aug 2023 16:24:15 +0200
Subject: [PATCH] Implement automatic agent API version bump
Automatically update the agent supported API version in the database if
the agent is updated and its API version is bumped.
Previously, if an agent was added to a verifier while it used an old API
version, and then it is updated with an API version bump, the
attestation would fail as the verifier would try to reach the agent
using the old API version.
Fixes #1457
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
---
keylime/cloud_verifier_tornado.py | 185 +++++++++++++++++++++++++++---
1 file changed, 167 insertions(+), 18 deletions(-)
diff --git a/keylime/cloud_verifier_tornado.py b/keylime/cloud_verifier_tornado.py
index 261022ac6..31e6f7159 100644
--- a/keylime/cloud_verifier_tornado.py
+++ b/keylime/cloud_verifier_tornado.py
@@ -32,6 +32,7 @@
)
from keylime.agentstates import AgentAttestState, AgentAttestStates
from keylime.common import retry, states, validators
+from keylime.common.version import str_to_version
from keylime.da import record
from keylime.db.keylime_db import DBEngineManager, SessionManager
from keylime.db.verifier_db import VerfierMain, VerifierAllowlist
@@ -998,6 +999,80 @@ def data_received(self, chunk: Any) -> None:
raise NotImplementedError()
+async def update_agent_api_version(agent: Dict[str, Any], timeout: float = 60.0) -> Union[Dict[str, Any], None]:
+ agent_id = agent["agent_id"]
+
+ logger.info("Agent %s API version bump detected, trying to update stored API version", agent_id)
+ kwargs = {}
+ if agent["ssl_context"]:
+ kwargs["context"] = agent["ssl_context"]
+
+ res = tornado_requests.request(
+ "GET",
+ f"http://{agent['ip']}:{agent['port']}/version",
+ **kwargs,
+ timeout=timeout,
+ )
+ response = await res
+
+ if response.status_code != 200:
+ logger.warning(
+ "Could not get agent %s supported API version, Error: %s",
+ agent["agent_id"],
+ response.status_code,
+ )
+ return None
+
+ try:
+ json_response = json.loads(response.body)
+ new_version = json_response["results"]["supported_version"]
+ old_version = agent["supported_version"]
+
+ # Only update the API version to use if it is supported by the verifier
+ if new_version in keylime_api_version.all_versions():
+ new_version_tuple = str_to_version(new_version)
+ old_version_tuple = str_to_version(old_version)
+
+ assert new_version_tuple, f"Agent {agent_id} version {new_version} is invalid"
+ assert old_version_tuple, f"Agent {agent_id} version {old_version} is invalid"
+
+ # Check that the new version is greater than current version
+ if new_version_tuple <= old_version_tuple:
+ logger.warning(
+ "Agent %s API version %s is lower or equal to previous version %s",
+ agent_id,
+ new_version,
+ old_version,
+ )
+ return None
+
+ logger.info("Agent %s new API version %s is supported", agent_id, new_version)
+ session = get_session()
+ agent["supported_version"] = new_version
+
+ # Remove keys that should not go to the DB
+ agent_db = dict(agent)
+ for key in exclude_db:
+ if key in agent_db:
+ del agent_db[key]
+
+ session.query(VerfierMain).filter_by(agent_id=agent_id).update(agent_db) # pyright: ignore
+ session.commit()
+ else:
+ logger.warning("Agent %s new API version %s is not supported", agent_id, new_version)
+ return None
+
+ except SQLAlchemyError as e:
+ logger.error("SQLAlchemy Error updating API version for agent %s: %s", agent_id, e)
+ return None
+ except Exception as e:
+ logger.exception(e)
+ return None
+
+ logger.info("Agent %s API version updated to %s", agent["agent_id"], agent["supported_version"])
+ return agent
+
+
async def invoke_get_quote(
agent: Dict[str, Any], runtime_policy: str, need_pubkey: bool, timeout: float = 60.0
) -> None:
@@ -1028,15 +1103,43 @@ async def invoke_get_quote(
# this is a connection error, retry get quote
if response.status_code in [408, 500, 599]:
asyncio.ensure_future(process_agent(agent, states.GET_QUOTE_RETRY))
- else:
- # catastrophic error, do not continue
- logger.critical(
- "Unexpected Get Quote response error for cloud agent %s, Error: %s",
- agent["agent_id"],
- response.status_code,
- )
- failure.add_event("no_quote", "Unexpected Get Quote reponse from agent", False)
- asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
+ return
+
+ if response.status_code == 400:
+ try:
+ json_response = json.loads(response.body)
+ if "API version not supported" in json_response["status"]:
+ update = update_agent_api_version(agent)
+ updated = await update
+
+ if updated:
+ asyncio.ensure_future(process_agent(updated, states.GET_QUOTE_RETRY))
+ else:
+ logger.warning("Could not update stored agent %s API version", agent["agent_id"])
+ failure.add_event(
+ "version_not_supported",
+ {"context": "Agent API version not supported", "data": json_response},
+ False,
+ )
+ asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
+ return
+
+ except Exception as e:
+ logger.exception(e)
+ failure.add_event(
+ "exception", {"context": "Agent caused the verifier to throw an exception", "data": str(e)}, False
+ )
+ asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
+ return
+
+ # catastrophic error, do not continue
+ logger.critical(
+ "Unexpected Get Quote response error for cloud agent %s, Error: %s",
+ agent["agent_id"],
+ response.status_code,
+ )
+ failure.add_event("no_quote", "Unexpected Get Quote reponse from agent", False)
+ asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
else:
try:
json_response = json.loads(response.body)
@@ -1100,15 +1203,43 @@ async def invoke_provide_v(agent: Dict[str, Any], timeout: float = 60.0) -> None
if response.status_code != 200:
if response.status_code in [408, 500, 599]:
asyncio.ensure_future(process_agent(agent, states.PROVIDE_V_RETRY))
- else:
- # catastrophic error, do not continue
- logger.critical(
- "Unexpected Provide V response error for cloud agent %s, Error: %s",
- agent["agent_id"],
- response.status_code,
- )
- failure.add_event("no_v", {"message": "Unexpected provide V response", "data": response.status_code}, False)
- asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
+ return
+
+ if response.status_code == 400:
+ try:
+ json_response = json.loads(response.body)
+ if "API version not supported" in json_response["status"]:
+ update = update_agent_api_version(agent)
+ updated = await update
+
+ if updated:
+ asyncio.ensure_future(process_agent(updated, states.PROVIDE_V_RETRY))
+ else:
+ logger.warning("Could not update stored agent %s API version", agent["agent_id"])
+ failure.add_event(
+ "version_not_supported",
+ {"context": "Agent API version not supported", "data": json_response},
+ False,
+ )
+ asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
+ return
+
+ except Exception as e:
+ logger.exception(e)
+ failure.add_event(
+ "exception", {"context": "Agent caused the verifier to throw an exception", "data": str(e)}, False
+ )
+ asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
+ return
+
+ # catastrophic error, do not continue
+ logger.critical(
+ "Unexpected Provide V response error for cloud agent %s, Error: %s",
+ agent["agent_id"],
+ response.status_code,
+ )
+ failure.add_event("no_v", {"message": "Unexpected provide V response", "data": response.status_code}, False)
+ asyncio.ensure_future(process_agent(agent, states.FAILED, failure))
else:
asyncio.ensure_future(process_agent(agent, states.GET_QUOTE))
@@ -1134,6 +1265,24 @@ async def invoke_notify_error(agent: Dict[str, Any], tosend: Dict[str, Any], tim
agent["agent_id"],
)
elif response.status_code != 200:
+ if response.status_code == 400:
+ try:
+ json_response = json.loads(response.body)
+ if "API version not supported" in json_response["status"]:
+ update = update_agent_api_version(agent)
+ updated = await update
+
+ if updated:
+ asyncio.ensure_future(invoke_notify_error(updated, tosend))
+ else:
+ logger.warning("Could not update stored agent %s API version", agent["agent_id"])
+
+ return
+
+ except Exception as e:
+ logger.exception(e)
+ return
+
logger.warning(
"Unexpected Notify Revocation response error for cloud agent %s, Error: %s",
agent["agent_id"],

View File

@ -1,59 +0,0 @@
--- a/scripts/create_runtime_policy.sh 2023-10-09 17:04:26.121194607 +0200
+++ b/scripts/create_runtime_policy.sh 2023-10-09 17:06:02.089855614 +0200
@@ -42,7 +42,7 @@
exit $NOARGS;
fi
-ALGO=sha1sum
+ALGO=sha256sum
ALGO_LIST=("sha1sum" "sha256sum" "sha512sum")
@@ -78,7 +78,7 @@
# Where to look for initramfs image
-INITRAMFS_LOC="/boot/"
+INITRAMFS_LOC="/boot"
if [ -d "/ostree" ]; then
# If we are on an ostree system change where we look for initramfs image
loc=$(grep -E "/ostree/[^/]([^/]*)" -o /proc/cmdline | head -n 1 | cut -d / -f 3)
@@ -121,7 +121,7 @@
cp -r /tmp/ima/$i-extracted-unmk/. /tmp/ima/$i-extracted
fi
elif [[ -x "/usr/lib/dracut/skipcpio" ]] ; then
- /usr/lib/dracut/skipcpio $i | gunzip -c | cpio -i -d 2> /dev/null
+ /usr/lib/dracut/skipcpio $i | gunzip -c 2> /dev/null | cpio -i -d 2> /dev/null
else
echo "ERROR: No tools for initramfs image processing found!"
break
@@ -130,9 +130,26 @@
find -type f -exec $ALGO "./{}" \; | sed "s| \./\./| /|" >> $OUTPUT
done
-# Convert to runtime policy
-echo "Converting created allowlist to Keylime runtime policy"
-python3 $WORKING_DIR/../keylime/cmd/convert_runtime_policy.py -a $OUTPUT -o $OUTPUT
+# when ROOTFS_LOC = '/', the path starts on allowlist ends up with double '//'
+#
+# Example:
+#
+# b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c //bar
+#
+# Replace the unwanted '//' with a single '/'
+sed -i 's| /\+| /|g' $ALLOWLIST_DIR/${OUTPUT}
+
+# When the file name contains newlines or backslashes, the output of sha256sum
+# adds a backslash at the beginning of the line.
+#
+# Example:
+#
+# $ echo foo > ba\\r
+# $ sha256sum ba\\r
+# \b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c ba\\r
+#
+# Remove the unwanted backslash prefix
+sed -i 's/^\\//g' $ALLOWLIST_DIR/${OUTPUT}
# Clean up
rm -rf /tmp/ima

View File

@ -1,44 +0,0 @@
diff --git a/keylime/cloud_verifier_common.py b/keylime/cloud_verifier_common.py
index a7399d2..c0f416d 100644
--- a/keylime/cloud_verifier_common.py
+++ b/keylime/cloud_verifier_common.py
@@ -8,7 +8,7 @@ from keylime.agentstates import AgentAttestState, AgentAttestStates, TPMClockInf
from keylime.common import algorithms
from keylime.db.verifier_db import VerfierMain
from keylime.failure import Component, Event, Failure
-from keylime.ima import file_signatures
+from keylime.ima import file_signatures, ima
from keylime.ima.types import RuntimePolicyType
from keylime.tpm import tpm_util
from keylime.tpm.tpm_main import Tpm
@@ -271,7 +271,7 @@ def process_get_status(agent: VerfierMain) -> Dict[str, Any]:
logger.debug('The contents of the agent %s attribute "mb_refstate" are %s', agent.agent_id, agent.mb_refstate)
has_runtime_policy = 0
- if agent.ima_policy.generator and agent.ima_policy.generator > 1:
+ if agent.ima_policy.generator and agent.ima_policy.generator > ima.RUNTIME_POLICY_GENERATOR.EmptyAllowList:
has_runtime_policy = 1
response = {
diff --git a/keylime/cmd/create_policy.py b/keylime/cmd/create_policy.py
index 0841d64..086b92a 100755
--- a/keylime/cmd/create_policy.py
+++ b/keylime/cmd/create_policy.py
@@ -6,6 +6,7 @@ import argparse
import binascii
import collections
import copy
+import datetime
import gzip
import json
import multiprocessing
@@ -580,6 +581,9 @@ def main() -> None:
policy["excludes"] = sorted(list(set(policy["excludes"])))
policy["ima"]["ignored_keyrings"] = sorted(list(set(policy["ima"]["ignored_keyrings"])))
+ policy["meta"]["generator"] = ima.RUNTIME_POLICY_GENERATOR.LegacyAllowList
+ policy["meta"]["timestamp"] = str(datetime.datetime.now())
+
try:
ima.validate_runtime_policy(policy)
except ima.ImaValidationError as ex:

View File

@ -1,80 +0,0 @@
From add9847988e963fd124863736592fc16cc8c716b Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 11 Jul 2023 18:03:28 -0400
Subject: [PATCH 14/14] tpm_util: Replace a logger.error with an Exception in
case of invalid signature
This fixes a possibly severe issue in 7.2.5 & 7.3.0.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
keylime/tpm/tpm_util.py | 6 +-----
keylime/tpm/tpm_util_test.py | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/keylime/tpm/tpm_util.py b/keylime/tpm/tpm_util.py
index ce2ce0f..58a1a04 100644
--- a/keylime/tpm/tpm_util.py
+++ b/keylime/tpm/tpm_util.py
@@ -3,7 +3,6 @@ import string
import struct
from typing import Any, Dict, List, Optional, Tuple, Union
-from cryptography.exceptions import InvalidSignature
from cryptography.hazmat import backends
from cryptography.hazmat.primitives import hashes, hmac, serialization
from cryptography.hazmat.primitives.asymmetric import ec, padding
@@ -155,10 +154,7 @@ def checkquote(
digest.update(quoteblob)
quote_digest = digest.finalize()
- try:
- verify(pubkey, signature, quote_digest, hashfunc)
- except InvalidSignature:
- logger.error("Invalid quote signature!")
+ verify(pubkey, signature, quote_digest, hashfunc)
# Check that reported nonce is expected one
retDict = tpm2_objects.unmarshal_tpms_attest(quoteblob)
diff --git a/keylime/tpm/tpm_util_test.py b/keylime/tpm/tpm_util_test.py
index aaf16cd..2c73997 100644
--- a/keylime/tpm/tpm_util_test.py
+++ b/keylime/tpm/tpm_util_test.py
@@ -2,6 +2,7 @@ import base64
import unittest
from unittest import mock
+from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.asymmetric.ec import (
SECP256R1,
EllipticCurve,
@@ -60,6 +61,26 @@ class TestTpmUtil(unittest.TestCase):
except Exception as e:
self.fail(f"checkquote failed with {e}")
+ # test bad input
+ bad_quoteblob = bytearray(quoteblob)
+ bad_quoteblob[5] ^= 0x1
+ with self.assertRaises(InvalidSignature):
+ checkquote(aikblob, nonce, sigblob, bad_quoteblob, pcrblob, "sha256")
+
+ l = list(nonce)
+ l[0] = "a"
+ bad_nonce = "".join(l)
+ with self.assertRaises(Exception):
+ checkquote(aikblob, bad_nonce, sigblob, quoteblob, pcrblob, "sha256")
+
+ bad_pcrblob = bytearray(pcrblob)
+ bad_pcrblob[5] ^= 0x1
+ with self.assertRaises(Exception):
+ checkquote(aikblob, nonce, sigblob, quoteblob, bad_pcrblob, "sha256")
+
+ with self.assertRaises(ValueError):
+ checkquote(aikblob, nonce, sigblob, quoteblob, pcrblob, "sha1")
+
@staticmethod
def not_random(numbytes: int) -> bytes:
return b"\x12" * numbytes
--
2.41.0

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +0,0 @@
From 4bd644b74719fdbb6c521d3d5eb2430d8dc18b36 Mon Sep 17 00:00:00 2001
From: Sergio Correia <scorreia@redhat.com>
Date: Wed, 5 Feb 2025 16:16:25 +0000
Subject: [PATCH 16/16] Use TLS on revocation notification webhook
---
keylime/requests_client.py | 5 ++
keylime/revocation_notifier.py | 91 +++++++++++++++++++++++-----------
2 files changed, 68 insertions(+), 28 deletions(-)
diff --git a/keylime/requests_client.py b/keylime/requests_client.py
index 85a175c..e993fbc 100644
--- a/keylime/requests_client.py
+++ b/keylime/requests_client.py
@@ -1,3 +1,4 @@
+import re
import ssl
from typing import Any, Dict, Optional
@@ -15,6 +16,10 @@ class RequestsClient:
ignore_hostname: bool = True,
**kwargs: Any,
) -> None:
+ # Remove eventual "http?://" from the base url
+ if base_url.startswith("http"):
+ base_url = re.sub(r"https?://", "", base_url)
+
if tls_enabled:
self.base_url = f"https://{base_url}"
else:
diff --git a/keylime/revocation_notifier.py b/keylime/revocation_notifier.py
index 5cc8b1a..434bf64 100644
--- a/keylime/revocation_notifier.py
+++ b/keylime/revocation_notifier.py
@@ -9,8 +9,9 @@ from typing import Any, Callable, Dict, Optional, Set
import requests
-from keylime import config, crypto, json, keylime_logging
+from keylime import config, crypto, json, keylime_logging, web_util
from keylime.common import retry
+from keylime.requests_client import RequestsClient
logger = keylime_logging.init_logging("revocation_notifier")
broker_proc: Optional[Process] = None
@@ -109,7 +110,10 @@ def notify(tosend: Dict[str, Any]) -> None:
exponential_backoff = config.getboolean("verifier", "exponential_backoff")
next_retry = retry.retry_time(exponential_backoff, interval, i, logger)
logger.debug(
- "Unable to publish revocation message %d times, trying again in %f seconds: %s", i, next_retry, e
+ "Unable to publish revocation message %d times, trying again in %f seconds: %s",
+ i,
+ next_retry,
+ e,
)
time.sleep(next_retry)
mysock.close()
@@ -132,30 +136,50 @@ def notify_webhook(tosend: Dict[str, Any]) -> None:
def worker_webhook(tosend: Dict[str, Any], url: str) -> None:
interval = config.getfloat("verifier", "retry_interval")
exponential_backoff = config.getboolean("verifier", "exponential_backoff")
- with requests.Session() as session:
- logger.info("Sending revocation event via webhook...")
- for i in range(config.getint("verifier", "max_retries")):
- next_retry = retry.retry_time(exponential_backoff, interval, i, logger)
+
+ max_retries = config.getint("verifier", "max_retries")
+ if max_retries <= 0:
+ logger.info("Invalid value found in 'max_retries' option for verifier, using default value")
+ max_retries = 5
+
+ # Get TLS options from the configuration
+ (cert, key, trusted_ca, key_password), verify_server_cert = web_util.get_tls_options(
+ "verifier", is_client=True, logger=logger
+ )
+
+ # Generate the TLS context using the obtained options
+ tls_context = web_util.generate_tls_context(cert, key, trusted_ca, key_password, is_client=True, logger=logger)
+
+ logger.info("Sending revocation event via webhook to %s ...", url)
+ for i in range(max_retries):
+ next_retry = retry.retry_time(exponential_backoff, interval, i, logger)
+
+ with RequestsClient(
+ url,
+ verify_server_cert,
+ tls_context,
+ ) as client:
try:
- response = session.post(url, json=tosend, timeout=5)
- if response.status_code in [200, 202]:
- break
-
- logger.debug(
- "Unable to publish revocation message %d times via webhook, "
- "trying again in %d seconds. "
- "Server returned status code: %s",
- i,
- next_retry,
- response.status_code,
- )
- except requests.exceptions.RequestException as e:
- logger.debug(
- "Unable to publish revocation message %d times via webhook, trying again in %d seconds: %s",
- i,
- next_retry,
- e,
- )
+ res = client.post("", json=tosend, timeout=5)
+ except requests.exceptions.SSLError as ssl_error:
+ if "TLSV1_ALERT_UNKNOWN_CA" in str(ssl_error):
+ logger.warning(
+ "Keylime does not recognize certificate from peer. Check if verifier 'trusted_server_ca' is configured correctly"
+ )
+
+ raise ssl_error from ssl_error
+
+ if res and res.status_code in [200, 202]:
+ break
+
+ logger.debug(
+ "Unable to publish revocation message %d times via webhook, "
+ "trying again in %d seconds. "
+ "Server returned status code: %s",
+ i + 1,
+ next_retry,
+ res.status_code,
+ )
time.sleep(next_retry)
@@ -167,7 +191,11 @@ def notify_webhook(tosend: Dict[str, Any]) -> None:
cert_key = None
-def process_revocation(revocation: Dict[str, Any], callback: Callable[[Dict[str, Any]], None], cert_path: str) -> None:
+def process_revocation(
+ revocation: Dict[str, Any],
+ callback: Callable[[Dict[str, Any]], None],
+ cert_path: str,
+) -> None:
global cert_key
if cert_key is None:
@@ -179,10 +207,17 @@ def process_revocation(revocation: Dict[str, Any], callback: Callable[[Dict[str,
cert_key = crypto.x509_import_pubkey(certpem)
if cert_key is None:
- logger.warning("Unable to check signature of revocation message: %s not available", cert_path)
+ logger.warning(
+ "Unable to check signature of revocation message: %s not available",
+ cert_path,
+ )
elif "signature" not in revocation or revocation["signature"] == "none":
logger.warning("No signature on revocation message from server")
- elif not crypto.rsa_verify(cert_key, revocation["msg"].encode("utf-8"), revocation["signature"].encode("utf-8")):
+ elif not crypto.rsa_verify(
+ cert_key,
+ revocation["msg"].encode("utf-8"),
+ revocation["signature"].encode("utf-8"),
+ ):
logger.error("Invalid revocation message siganture %s", revocation)
else:
message = json.loads(revocation["msg"])
--
2.47.1

79
changelog Normal file
View File

@ -0,0 +1,79 @@
* Thu Jul 07 2022 Sergio Correia <scorreia@redhat.com> - 6.4.1-3
- Opt in to rpmautospec
* Mon Jun 13 2022 Python Maint <python-maint@redhat.com> - 6.4.1-2
- Rebuilt for Python 3.11
* Mon Jun 06 2022 Sergio Correia <scorreia@redhat.com> - 6.4.1-1
- Updating for Keylime release v6.4.1
* Wed May 04 2022 Sergio Correia <scorreia@redhat.com> - 6.4.0-1
- Updating for Keylime release v6.4.0
* Wed Apr 06 2022 Sergio Correia <scorreia@redhat.com> - 6.3.2-1
- Updating for Keylime release v6.3.2
* Mon Feb 14 2022 Sergio Correia <scorreia@redhat.com> - 6.3.1-1
- Updating for Keylime release v6.3.1
* Tue Feb 08 2022 Sergio Correia <scorreia@redhat.com> - 6.0.3-4
- Add Conflicts clauses for the subpackages
* Mon Feb 07 2022 Sergio Correia <scorreia@redhat.com> - 6.3.0-3
- Split keylime into subpackages
Related: rhbz#2045874 - Keylime subpackaging and agent alternatives
* Thu Jan 27 2022 Sergio Correia <scorreia@redhat.com> - 6.3.0-2
- Fix permissions of config file
* Thu Jan 27 2022 Sergio Correia <scorreia@redhat.com> - 6.3.0-1
- Updating for Keylime release v6.3.0
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 6.1.0-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 6.1.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Fri Jun 04 2021 Python Maint <python-maint@redhat.com> - 6.1.0-3
- Rebuilt for Python 3.10
* Thu Mar 25 2021 Luke Hinds <lhinds@redhat.com> 6.0.1-1
- Updating for Keylime release v6.1.0
* Wed Mar 03 2021 Luke Hinds <lhinds@redhat.com> 6.0.1-1
- Updating for Keylime release v6.0.1
* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 6.0.0-2
- Rebuilt for updated systemd-rpm-macros
See https://pagure.io/fesco/issue/2583.
* Wed Feb 24 2021 Luke Hinds <lhinds@redhat.com> 6.0.0-1
- Updating for Keylime release v6.0.0
* Tue Feb 02 2021 Luke Hinds <lhinds@redhat.com> 5.8.1-1
- Updating for Keylime release v5.8.1
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 5.8.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Sat Jan 23 2021 Luke Hinds <lhinds@redhat.com> 5.8.0-1
- Updating for Keylime release v5.8.0
* Fri Jul 17 2020 Luke Hinds <lhinds@redhat.com> 5.7.2-1
- Updating for Keylime release v5.7.2
* Tue May 26 2020 Miro Hrončok <mhroncok@redhat.com> - 5.6.2-2
- Rebuilt for Python 3.9
* Fri May 01 2020 Luke Hinds <lhinds@redhat.com> 5.6.2-1
- Updating for Keylime release v5.6.2
* Thu Feb 06 2020 Luke Hinds <lhinds@redhat.com> 5.5.0-1
- Updating for Keylime release v5.5.0
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 5.4.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Thu Dec 12 2019 Luke Hinds <lhinds@redhat.com> 5.4.1-1
Initial Packaging

17
ci_tests.fmf Normal file
View File

@ -0,0 +1,17 @@
/e2e:
plan:
import:
url: https://github.com/RedHat-SP-Security/keylime-plans.git
name: /generic/e2e
/package-update:
plan:
import:
url: https://github.com/RedHat-SP-Security/keylime-plans.git
name: /generic/package-update
/rpmverify:
plan:
import:
url: https://github.com/RedHat-SP-Security/keylime-plans.git
name: /generic/rpmverify

6
gating.yaml Normal file
View File

@ -0,0 +1,6 @@
--- !Policy
product_versions:
- rhel-10
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

View File

@ -1,40 +1,26 @@
%global srcname keylime
%global policy_version 1.2.0
%global with_selinux 1
%global selinuxtype targeted
%global policy_version 38.1.0
# Package is actually noarch, but it has an optional dependency that is
# arch-specific.
%global debug_package %{nil}
%global with_selinux 1
%global selinuxtype targeted
Name: keylime
Version: 7.3.0
Release: 15%{?dist}
Version: 7.12.1
Release: %autorelease
Summary: Open source TPM software for Bootstrapping and Maintaining Trust
URL: https://github.com/keylime/keylime
Source0: https://github.com/keylime/keylime/archive/refs/tags/v%{version}.tar.gz
Source1: %{srcname}.sysusers
# The selinux policy for keylime is distributed via this repo: https://github.com/RedHat-SP-Security/keylime-selinux
Source2: https://github.com/RedHat-SP-Security/%{name}-selinux/archive/v%{policy_version}/keylime-selinux-%{policy_version}.tar.gz
Patch: 0001-Remove-usage-of-Required-NotRequired-typing_ext.patch
Patch: 0002-Allow-keylime_server_t-tcp-connect-to-several-domain.patch
Patch: 0003-Use-version-2.0-as-the-minimum-for-the-configuration.patch
Patch: 0004-Duplicate-str_to_version-for-the-upgrade-tool.patch
Patch: 0005-elchecking-example-add-ignores-for-EV_PLATFORM_CONFI.patch
Patch: 0006-Revert-mapping-changes.patch
Patch: 0007-Handle-session-close-using-a-session-manager.patch
Patch: 0008-verifier-should-read-parameters-from-verifier.conf-o.patch
Patch: 0009-CVE-2023-38201.patch
Patch: 0010-CVE-2023-38200.patch
Patch: 0011-Automatically-update-agent-API-version.patch
Patch: 0012-Restore-create-allowlist.patch
Patch: 0013-Set-generator-and-timestamp-in-create-policy.patch
Patch: 0014-tpm_util-Replace-a-logger.error-with-an-Exception-in.patch
Patch: 0015-Backport-keylime-policy-tool.patch
Patch: 0016-Use-TLS-on-revocation-notification-webhook.patch
License: ASL 2.0 and MIT
# Main program: Apache-2.0
# Icons: MIT
License: Apache-2.0 AND MIT
BuildRequires: git-core
BuildRequires: swig
@ -44,17 +30,26 @@ BuildRequires: python3-dbus
BuildRequires: python3-jinja2
BuildRequires: python3-setuptools
BuildRequires: systemd-rpm-macros
BuildRequires: tpm2-abrmd-selinux
Requires: python3-%{srcname} = %{version}-%{release}
Requires: %{srcname}-base = %{version}-%{release}
Requires: %{srcname}-verifier = %{version}-%{release}
Requires: %{srcname}-registrar = %{version}-%{release}
Requires: %{srcname}-tenant = %{version}-%{release}
Requires: %{srcname}-tools = %{version}-%{release}
# webapp was removed upstream in release 6.4.2.
Obsoletes: %{srcname}-webapp < 6.4.2
# python agent was removed upstream in release 7.0.0.
Obsoletes: python3-%{srcname}-agent < 7.0.0
# Agent.
Requires: keylime-agent
Suggests: keylime-agent-rust
Suggests: %{srcname}-agent-rust
# Conflicts with the monolithic versions of the package, before the split.
Conflicts: keylime < 6.3.0-3
%{?python_enable_dependency_generator}
%description
@ -65,12 +60,14 @@ and runtime integrity measurement solution.
Summary: The base package contains the default configuration
License: MIT
# Conflicts with the monolithic versions of the package, before the split.
Conflicts: keylime < 6.3.0-3
Requires(pre): python3-jinja2
Requires(pre): shadow-utils
Requires(pre): util-linux
Requires: procps-ng
Requires: tpm2-tss
Requires: openssl
%if 0%{?with_selinux}
# This ensures that the *-selinux package and all its dependencies are not pulled
@ -90,6 +87,9 @@ The base package contains the Keylime default configuration
Summary: The Python Keylime module
License: MIT
# Conflicts with the monolithic versions of the package, before the split.
Conflicts: keylime < 6.3.0-3
Requires: %{srcname}-base = %{version}-%{release}
%{?python_provide:%python_provide python3-%{srcname}}
@ -104,10 +104,10 @@ Requires: python3-gpg
Requires: python3-lark-parser
Requires: python3-pyasn1
Requires: python3-pyasn1-modules
requires: python3-psutil
Requires: python3-jsonschema
Requires: python3-psutil
Requires: python3-typing-extensions
Requires: tpm2-tools
Requires: openssl
%description -n python3-%{srcname}
The python3-keylime module implements the functionality used
@ -117,6 +117,9 @@ by Keylime components.
Summary: The Python Keylime Verifier component
License: MIT
# Conflicts with the monolithic versions of the package, before the split.
Conflicts: keylime < 6.3.0-3
Requires: %{srcname}-base = %{version}-%{release}
Requires: python3-%{srcname} = %{version}-%{release}
@ -128,6 +131,9 @@ of the machine that the agent is running on.
Summary: The Keylime Registrar component
License: MIT
# Conflicts with the monolithic versions of the package, before the split.
Conflicts: keylime < 6.3.0-3
Requires: %{srcname}-base = %{version}-%{release}
Requires: python3-%{srcname} = %{version}-%{release}
@ -153,6 +159,9 @@ Custom SELinux policy module
Summary: The Python Keylime Tenant
License: MIT
# Conflicts with the monolithic versions of the package, before the split.
Conflicts: keylime < 6.3.0-3
Requires: %{srcname}-base = %{version}-%{release}
Requires: python3-%{srcname} = %{version}-%{release}
@ -160,13 +169,26 @@ Requires: python3-%{srcname} = %{version}-%{release}
%description tenant
The Keylime Tenant can be used to provision a Keylime Agent.
%package tools
Summary: Keylime tools
License: MIT
# Conflicts with the monolithic versions of the package, before the split.
Conflicts: keylime < 6.3.0-3
Requires: %{srcname}-base = %{version}-%{release}
Requires: python3-%{srcname} = %{version}-%{release}
%description tools
The keylime tools package includes miscelaneous tools.
%prep
%autosetup -S git -n %{srcname}-%{version} -a2
%if 0%{?with_selinux}
# SELinux policy (originally from selinux-policy-contrib)
# this policy module will override the production module
mkdir selinux
make -f %{_datadir}/selinux/devel/Makefile %{srcname}.pp
bzip2 -9 %{srcname}.pp
@ -179,7 +201,6 @@ bzip2 -9 %{srcname}.pp
%py3_install
mkdir -p %{buildroot}/%{_sharedstatedir}/%{srcname}
mkdir -p --mode=0700 %{buildroot}/%{_rundir}/%{srcname}
mkdir -p --mode=0700 %{buildroot}/%{_localstatedir}/log/%{srcname}
mkdir -p --mode=0700 %{buildroot}/%{_sysconfdir}/%{srcname}/
for comp in "verifier" "tenant" "registrar" "ca" "logging"; do
@ -187,20 +208,18 @@ for comp in "verifier" "tenant" "registrar" "ca" "logging"; do
install -Dpm 400 config/${comp}.conf %{buildroot}/%{_sysconfdir}/%{srcname}
done
# Ship some scripts.
mkdir -p %{buildroot}/%{_datadir}/%{srcname}/scripts
for s in create_mb_refstate \
ek-openssl-verify; do
install -Dpm 755 scripts/${s} \
%{buildroot}/%{_datadir}/%{srcname}/scripts/${s}
# Do not ship a few scripts that are to be obsoleted soon.
# The functionality they provide is now provided by keylime-policy.
for s in keylime_convert_runtime_policy \
keylime_create_policy \
keylime_sign_runtime_policy; do
rm -f %{buildroot}/%{_bindir}/"${s}"
done
# On RHEL 9.3, install create_runtime_policy.sh as create_allowlist.sh
# The convert_runtime_policy.py script to convert allowlist and excludelist into
# runtime policy is not called anymore.
# See: https://issues.redhat.com/browse/RHEL-11866
install -Dpm 755 scripts/create_runtime_policy.sh \
%{buildroot}/%{_datadir}/%{srcname}/scripts/create_allowlist.sh
# Ship the ek-openssl-verify script.
mkdir -p %{buildroot}/%{_datadir}/%{srcname}/scripts
install -Dpm 755 scripts/ek-openssl-verify \
%{buildroot}/%{_datadir}/%{srcname}/scripts/ek-openssl-verify
# Ship configuration templates.
cp -r ./templates %{buildroot}%{_datadir}/%{srcname}/templates/
@ -220,7 +239,6 @@ install -Dpm 644 ./services/%{srcname}_registrar.service \
%{buildroot}%{_unitdir}/%{srcname}_registrar.service
cp -r ./tpm_cert_store %{buildroot}%{_sharedstatedir}/%{srcname}/
chmod 400 %{buildroot}%{_sharedstatedir}/%{srcname}/tpm_cert_store/*.pem
install -p -d %{buildroot}/%{_tmpfilesdir}
cat > %{buildroot}/%{_tmpfilesdir}/%{srcname}.conf << EOF
@ -262,29 +280,15 @@ exit 0
%post verifier
/usr/bin/keylime_upgrade_config --component verifier >/dev/null
%systemd_post %{srcname}_verifier.service
exit 0
%post registrar
/usr/bin/keylime_upgrade_config --component registrar >/dev/null
%systemd_post %{srcname}_registrar.service
exit 0
%post tenant
/usr/bin/keylime_upgrade_config --component tenant >/dev/null
exit 0
%preun verifier
%systemd_preun %{srcname}_verifier.service
%preun registrar
%systemd_preun %{srcname}_registrar.service
%postun verifier
%systemd_postun_with_restart %{srcname}_verifier.service
%postun registrar
%systemd_postun_with_restart %{srcname}_registrar.service
%if 0%{?with_selinux}
# SELinux contexts are saved so that only affected files can be
# relabeled after the policy module installation
@ -299,7 +303,7 @@ if [ "$1" -le "1" ]; then # First install
# The services need to be restarted for the custom label to be
# applied in case they where already present in the system,
# restart fails silently in case they where not.
for svc in agent registrar verifier; do
for svc in registrar verifier; do
[ -f "%{_unitdir}/%{srcname}_${svc}".service ] && \
%systemd_postun_with_restart "%{srcname}_${svc}".service
done
@ -313,6 +317,21 @@ if [ $1 -eq 0 ]; then
fi
%endif
%preun verifier
%systemd_preun %{srcname}_verifier.service
%preun registrar
%systemd_preun %{srcname}_registrar.service
%preun tenant
%systemd_preun %{srcname}_registrar.service
%postun verifier
%systemd_postun_with_restart %{srcname}_verifier.service
%postun registrar
%systemd_postun_with_restart %{srcname}_registrar.service
%files verifier
%license LICENSE
%attr(500,%{srcname},%{srcname}) %dir %{_sysconfdir}/%{srcname}/verifier.conf.d
@ -345,14 +364,14 @@ fi
%license LICENSE
%{python3_sitelib}/%{srcname}-*.egg-info/
%{python3_sitelib}/%{srcname}
%{_datadir}/%{srcname}/scripts/create_mb_refstate
%{_bindir}/keylime_attest
%{_bindir}/keylime_convert_runtime_policy
%{_bindir}/keylime_create_policy
%{_bindir}/keylime_sign_runtime_policy
%{_bindir}/keylime_userdata_encrypt
%{_bindir}/keylime-policy
%files tools
%license LICENSE
%{_bindir}/%{srcname}_userdata_encrypt
%files base
%license LICENSE
%doc README.md
@ -360,13 +379,11 @@ fi
%config(noreplace) %verify(not md5 size mode mtime) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/ca.conf
%config(noreplace) %verify(not md5 size mode mtime) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/logging.conf
%attr(700,%{srcname},%{srcname}) %dir %{_rundir}/%{srcname}
%attr(700,%{srcname},%{srcname}) %dir %{_localstatedir}/log/%{srcname}
%attr(700,%{srcname},%{srcname}) %dir %{_sharedstatedir}/%{srcname}
%attr(500,%{srcname},%{srcname}) %dir %{_sharedstatedir}/%{srcname}/tpm_cert_store
%attr(400,%{srcname},%{srcname}) %{_sharedstatedir}/%{srcname}/tpm_cert_store/*.pem
%{_tmpfilesdir}/%{srcname}.conf
%{_sysusersdir}/%{srcname}.conf
%{_datadir}/%{srcname}/scripts/create_allowlist.sh
%{_datadir}/%{srcname}/scripts/ek-openssl-verify
%{_datadir}/%{srcname}/templates
%{_bindir}/keylime_upgrade_config
@ -375,134 +392,4 @@ fi
%license LICENSE
%changelog
* Wed Feb 05 2025 Sergio Correia <scorreia@redhat.com> - 7.3.0-15
- Use TLS on revocation notification webhook
- Include system installed CA certificates when verifying webhook
server certificate
- Include the CA certificates added via configuration file option
'trusted_server_ca'
Resolves: RHEL-78057
Resolves: RHEL-78313
Resolves: RHEL-78316
* Fri Jan 10 2025 Sergio Correia <scorreia@redhat.com> - 7.3.0-14
- Backport keylime-policy tool
Resolves: RHEL-75797
* Fri Jan 05 2024 Sergio Correia <scorreia@redhat.com> - 7.3.0-13
- Backport fix for CVE-2023-3674
Resolves: RHEL-21013
* Tue Oct 17 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 7.3.0-12
- Set the generator and timestamp in create_policy.py
Related: RHEL-11866
* Mon Oct 09 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 7.3.0-11
- Suppress unnecessary error message
Related: RHEL-11866
* Fri Oct 06 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 7.3.0-10
- Restore allowlist generation script
Resolves: RHEL-11866
Resolves: RHEL-11867
* Wed Sep 06 2023 Sergio Correia <scorreia@redhat.com> - 7.3.0-9
- Rebuild for properly tagging the resulting build
Resolves: RHEL-1898
* Fri Sep 01 2023 Sergio Correia <scorreia@redhat.com> - 7.3.0-8
- Add missing dependencies python3-jinja2 and util-linux
Resolves: RHEL-1898
* Mon Aug 28 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 7.3.0-7
- Automatically update agent API version
Resolves: RHEL-1518
* Mon Aug 28 2023 Sergio Correia <scorreia@redhat.com> - 7.3.0-6
- Fix registrar is subject to a DoS against SSL (CVE-2023-38200)
Resolves: rhbz#2222694
* Fri Aug 25 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 7.3.0-5
- Fix challenge-protocol bypass during agent registration (CVE-2023-38201)
Resolves: rhbz#2222695
* Tue Aug 22 2023 Sergio Correia <scorreia@redhat.com> - 7.3.0-4
- Update spec file to use %verify(not md5 size mode mtime) for files updated in %post scriptlets
Resolves: RHEL-475
* Tue Aug 15 2023 Sergio Correia <scorreia@redhat.com> - 7.3.0-3
- Fix Keylime configuration upgrades issues introduced in last rebase
Resolves: RHEL-475
- Handle session close using a session manager
Resolves: RHEL-1252
- Add ignores for EV_PLATFORM_CONFIG_FLAGS
Resolves: RHEL-947
* Tue Aug 8 2023 Patrik Koncity <pkoncity@redhat.com> - 7.3.0-2
- Keylime SELinux policy provides more restricted ports.
- New SELinux label for ports used by keylime.
- Adding tabrmd interfaces allow unix stream socket communication and dbus communication.
- Allow the keylime_server_t domain to get the attributes of all filesystems.
Resolves: RHEL-595
Resolves: RHEL-390
Resolves: RHEL-948
* Wed Jul 19 2023 Sergio Correia <scorreia@redhat.com> - 7.3.0-1
- Update to 7.3.0
Resolves: RHEL-475
* Fri Jan 13 2023 Sergio Correia <scorreia@redhat.com> - 6.5.2-4
- Backport upstream PR#1240 - logging: remove option to log into separate file
Resolves: rhbz#2154584 - keylime verifier is not logging to /var/log/keylime
* Thu Dec 1 2022 Sergio Correia <scorreia@redhat.com> - 6.5.2-3
- Remove leftover policy file
Related: rhbz#2152135
* Thu Dec 1 2022 Patrik Koncity <pkoncity@redhat.com> - 6.5.2-2
- Use keylime selinux policy from upstream.
Resolves: rhbz#2152135
* Mon Nov 14 2022 Sergio Correia <scorreia@redhat.com> - 6.5.2-1
- Update to 6.5.2
Resolves: CVE-2022-3500
Resolves: rhbz#2138167 - agent fails IMA attestation when one scripts is executed quickly after the other
Resolves: rhbz#2140670 - Segmentation fault in /usr/share/keylime/create_mb_refstate script
Resolves: rhbz#142009 - Registrar may crash during EK validation when require_ek_cert is enabled
* Tue Sep 13 2022 Sergio Correia <scorreia@redhat.com> - 6.5.0-1
- Update to 6.5.0
Resolves: rhbz#2120686 - Keylime configuration is too complex
* Fri Aug 26 2022 Sergio Correia <scorreia@redhat.com> - 6.4.3-1
- Update to 6.4.3
Resolves: rhbz#2121044 - Error parsing EK ASN.1 certificate of Nuvoton HW TPM
* Fri Aug 26 2022 Patrik Koncity <pkoncity@redhat.com> - 6.4.2-6
- Update keylime SELinux policy
- Resolves: rhbz#2121058
* Fri Aug 26 2022 Patrik Koncity <pkoncity@redhat.com> - 6.4.2-5
- Update keylime SELinux policy and removed duplicate rules
- Resolves: rhbz#2121058
* Fri Aug 26 2022 Patrik Koncity <pkoncity@redhat.com> - 6.4.2-4
- Update keylime SELinux policy
- Resolves: rhbz#2121058
* Wed Aug 17 2022 Patrik Koncity <pkoncity@redhat.com> - 6.4.2-3
- Add keylime-selinux policy as subpackage
- See https://fedoraproject.org/wiki/SELinux/IndependentPolicy
- Resolves: rhbz#2121058
* Mon Jul 11 2022 Sergio Correia <scorreia@redhat.com> - 6.4.2-2
- Fix efivar-libs dependency
Related: rhbz#2082989
* Thu Jul 07 2022 Sergio Correia <scorreia@redhat.com> - 6.4.2-1
- Update to 6.4.2
Related: rhbz#2082989
* Tue Jun 21 2022 Sergio Correia <scorreia@redhat.com> - 6.4.1-1
- Add keylime to RHEL-9
Resolves: rhbz#2082989
%autochangelog

2
sources Normal file
View File

@ -0,0 +1,2 @@
SHA512 (v7.12.1.tar.gz) = c1297ebfc659102d73283255cfda4a977dfbff9bdd3748e05de405dadb70f752ad39aa5848edda9143d8ec620d07c21f1551fa4a914c99397620ab1682e58458
SHA512 (keylime-selinux-38.1.0.tar.gz) = cbb54511b14a0352e1c2679909b0dcbc00924bacf8f783b230a782d0fae6e3b0168704ea4896c273199163e04a26bcb6217cf30dc480fc300e1fdcb7e39d00a8