Skip to content

Commit bcdf5e8

Browse files
committed
Add support for multi-token management in SmartCardUtils
1 parent 8a9e9d9 commit bcdf5e8

1 file changed

Lines changed: 91 additions & 2 deletions

File tree

sssd_test_framework/utils/smartcard.py

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,43 @@ def initialize_card(self, label: str = "sc_test", so_pin: str = "12345678", user
7676
self.cli.command("softhsm2-util --init-token", args), env={"SOFTHSM2_CONF": self.SOFTHSM2_CONF_PATH}
7777
)
7878

79+
def initialize_additional_token(self, label: str, so_pin: str = "12345678", user_pin: str = "123456") -> None:
80+
"""
81+
Initializes an additional SoftHSM token without wiping existing tokens.
82+
83+
Unlike :meth:`initialize_card`, this method does **not** remove the
84+
existing token storage directory. It simply calls
85+
``softhsm2-util --init-token --free`` with the given *label* so that a
86+
new slot is allocated alongside any tokens that are already present.
87+
88+
Use this after an initial :meth:`initialize_card` call to create a
89+
multi-token environment (simulating multiple physical smart cards).
90+
91+
:param label: Token label (must be unique among existing tokens).
92+
:type label: str
93+
:param so_pin: Security Officer PIN, defaults to "12345678"
94+
:type so_pin: str, optional
95+
:param user_pin: User PIN, defaults to "123456"
96+
:type user_pin: str, optional
97+
"""
98+
args: CLIBuilderArgs = {
99+
"label": (self.cli.option.VALUE, label),
100+
"free": (self.cli.option.SWITCH, True),
101+
"so-pin": (self.cli.option.VALUE, so_pin),
102+
"pin": (self.cli.option.VALUE, user_pin),
103+
}
104+
self.host.conn.run(
105+
self.cli.command("softhsm2-util --init-token", args), env={"SOFTHSM2_CONF": self.SOFTHSM2_CONF_PATH}
106+
)
107+
79108
def add_cert(
80109
self,
81110
cert_path: str,
82111
cert_id: str = "01",
83112
pin: str = "123456",
84113
private: bool | None = False,
114+
token_label: str | None = None,
115+
label: str | None = None,
85116
) -> None:
86117
"""
87118
Adds a certificate or private key to the smart card.
@@ -94,6 +125,15 @@ def add_cert(
94125
:type pin: str, optional
95126
:param private: Whether the object is a private key. Defaults to False.
96127
:type private: bool, optional
128+
:param token_label: Label of the target token. When ``None`` (the
129+
default) ``pkcs11-tool`` writes to the first available token.
130+
Set this when multiple tokens exist to target a specific one.
131+
:type token_label: str | None, optional
132+
:param label: Label for the PKCS#11 object being written. Required
133+
when ``p11_child`` accesses the token directly (i.e. without
134+
``virt_cacard``), because the response parser expects a
135+
non-empty label.
136+
:type label: str | None, optional
97137
"""
98138
obj_type = "privkey" if private else "cert"
99139
args: CLIBuilderArgs = {
@@ -104,9 +144,20 @@ def add_cert(
104144
"type": (self.cli.option.VALUE, obj_type),
105145
"id": (self.cli.option.VALUE, cert_id),
106146
}
147+
if token_label is not None:
148+
args["token-label"] = (self.cli.option.VALUE, token_label)
149+
if label is not None:
150+
args["label"] = (self.cli.option.VALUE, label)
107151
self.host.conn.run(self.cli.command("pkcs11-tool", args), env={"SOFTHSM2_CONF": self.SOFTHSM2_CONF_PATH})
108152

109-
def add_key(self, key_path: str, key_id: str = "01", pin: str = "123456") -> None:
153+
def add_key(
154+
self,
155+
key_path: str,
156+
key_id: str = "01",
157+
pin: str = "123456",
158+
token_label: str | None = None,
159+
label: str | None = None,
160+
) -> None:
110161
"""
111162
Adds a private key to the smart card.
112163
@@ -116,8 +167,12 @@ def add_key(self, key_path: str, key_id: str = "01", pin: str = "123456") -> Non
116167
:type key_id: str, optional
117168
:param pin: User PIN, defaults to "123456"
118169
:type pin: str, optional
170+
:param token_label: Label of the target token (see :meth:`add_cert`).
171+
:type token_label: str | None, optional
172+
:param label: Label for the PKCS#11 object (see :meth:`add_cert`).
173+
:type label: str | None, optional
119174
"""
120-
self.add_cert(cert_path=key_path, cert_id=key_id, pin=pin, private=True)
175+
self.add_cert(cert_path=key_path, cert_id=key_id, pin=pin, private=True, token_label=token_label, label=label)
121176

122177
def generate_cert(
123178
self,
@@ -150,6 +205,40 @@ def generate_cert(
150205
self.host.conn.run(self.cli.command("openssl req", args))
151206
return key_path, cert_path
152207

208+
def register_for_p11_child(self) -> None:
209+
"""
210+
Register SoftHSM as a system-wide p11-kit module visible to ``p11_child``.
211+
212+
This is required for multi-token scenarios where ``p11_child`` must
213+
iterate all PKCS#11 slots. The method:
214+
215+
1. Ensures ``slots.removable = true`` is set in the SoftHSM config.
216+
2. Copies the SoftHSM config to ``/etc/softhsm2.conf`` so that
217+
``p11_child`` (running as the *sssd* user) can find it without
218+
``SOFTHSM2_CONF`` in its environment.
219+
3. Registers the SoftHSM module with p11-kit.
220+
4. Creates a systemd drop-in for ``sssd.service`` that exports
221+
``SOFTHSM2_CONF``.
222+
5. Adjusts file permissions so the *sssd* user can access the token
223+
storage directory.
224+
"""
225+
conf = self.SOFTHSM2_CONF_PATH
226+
module = "/usr/lib64/pkcs11/libsofthsm2.so"
227+
228+
self.host.conn.run(f"grep -q 'slots.removable' {conf} || echo 'slots.removable = true' >> {conf}")
229+
self.host.conn.run(f"cp {conf} /etc/softhsm2.conf")
230+
self.host.conn.run(f'echo "module: {module}" > /etc/pkcs11/modules/softhsm2.module')
231+
self.fs.mkdir_p("/etc/systemd/system/sssd.service.d")
232+
self.host.conn.run(
233+
f'printf "[Service]\\nEnvironment=SOFTHSM2_CONF={conf}\\n" '
234+
f"> /etc/systemd/system/sssd.service.d/softhsm.conf"
235+
)
236+
self.host.conn.run("systemctl daemon-reload")
237+
self.host.conn.run("chmod -R o+rX /opt/test_ca/")
238+
self.host.conn.run(
239+
f"chown -R sssd:sssd {self.TOKEN_STORAGE_PATH}/ " f"&& chmod -R 770 {self.TOKEN_STORAGE_PATH}/"
240+
)
241+
153242
def insert_card(self) -> None:
154243
"""
155244
Simulates card insertion by starting the smart card service.

0 commit comments

Comments
 (0)