-
Notifications
You must be signed in to change notification settings - Fork 284
Smartcard multi token tests #8519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,8 +8,78 @@ | |
|
|
||
| import pytest | ||
| from sssd_test_framework.roles.client import Client | ||
| from sssd_test_framework.roles.ipa import IPA | ||
| from sssd_test_framework.topology import KnownTopology | ||
|
|
||
| TOKEN1_LABEL = "SC_Token_1" | ||
| TOKEN2_LABEL = "SC_Token_2" | ||
| TOKEN_PIN = "123456" | ||
|
spoore1 marked this conversation as resolved.
|
||
|
|
||
|
|
||
| def enroll_to_token( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering now if this would be better to add this to the smartcard util in the framework with this: SSSD/sssd-test-framework#239 Also, if this is moved to the framework, can the |
||
| client: Client, | ||
| ipa: IPA, | ||
| username: str, | ||
| *, | ||
| token_label: str, | ||
| cert_id: str = "01", | ||
| pin: str = TOKEN_PIN, | ||
| ) -> None: | ||
| """ | ||
| Request an IPA-signed certificate for *username* and store it on *token_label*. | ||
|
|
||
| :param client: Client role object. | ||
| :type client: Client | ||
| :param ipa: IPA role object whose CA issues the certificate. | ||
| :type ipa: IPA | ||
| :param username: IPA principal to issue the certificate for. | ||
| :type username: str | ||
| :param token_label: SoftHSM token label to write the objects to. | ||
| :type token_label: str | ||
| :param cert_id: PKCS#11 object ID, defaults to "01". | ||
| :type cert_id: str, optional | ||
| :param pin: User PIN for the token, defaults to TOKEN_PIN. | ||
| :type pin: str, optional | ||
| """ | ||
| cert, key, _ = ipa.ca.request(username) | ||
| cert_content = ipa.fs.read(cert) | ||
| key_content = ipa.fs.read(key) | ||
|
|
||
| cert_path = f"/opt/test_ca/{username}_{token_label}.crt" | ||
| key_path = f"/opt/test_ca/{username}_{token_label}.key" | ||
|
|
||
| client.fs.write(cert_path, cert_content) | ||
| client.fs.write(key_path, key_content) | ||
|
|
||
| client.smartcard.add_key(key_path, key_id=cert_id, pin=pin, token_label=token_label, label=username) | ||
| client.smartcard.add_cert(cert_path, cert_id=cert_id, pin=pin, token_label=token_label, label=username) | ||
|
|
||
|
|
||
| def setup_two_tokens( | ||
| client: Client, | ||
| ipa: IPA, | ||
| *, | ||
| token1_username: str, | ||
| token2_username: str, | ||
| ) -> None: | ||
| """ | ||
| Create two SoftHSM tokens, each holding an IPA-signed certificate. | ||
|
|
||
| :param client: Client role object. | ||
| :type client: Client | ||
| :param ipa: IPA role object. | ||
| :type ipa: IPA | ||
| :param token1_username: IPA user whose cert goes onto token 1. | ||
| :type token1_username: str | ||
| :param token2_username: IPA user whose cert goes onto token 2. | ||
| :type token2_username: str | ||
| """ | ||
| client.smartcard.initialize_card(label=TOKEN1_LABEL, user_pin=TOKEN_PIN) | ||
| enroll_to_token(client, ipa, token1_username, token_label=TOKEN1_LABEL) | ||
|
|
||
| client.smartcard.initialize_card(label=TOKEN2_LABEL, user_pin=TOKEN_PIN, reset=False) | ||
| enroll_to_token(client, ipa, token2_username, token_label=TOKEN2_LABEL) | ||
|
|
||
|
|
||
| @pytest.mark.importance("critical") | ||
| @pytest.mark.topology(KnownTopology.Client) | ||
|
|
@@ -30,3 +100,93 @@ def test_smartcard__su_as_local_user(client: Client): | |
| result = client.host.conn.run("su - localuser1 -c 'su - localuser1 -c whoami'", input="123456") | ||
| assert "PIN" in result.stderr, "String 'PIN' was not found in stderr!" | ||
| assert "localuser1" in result.stdout, "'localuser1' not found in 'whoami' output!" | ||
|
|
||
|
|
||
| @pytest.mark.importance("critical") | ||
| @pytest.mark.topology(KnownTopology.IPA) | ||
| @pytest.mark.builtwith(client="virtualsmartcard") | ||
| def test_smartcard__two_tokens_match_on_first(client: Client, ipa: IPA): | ||
| """ | ||
| :title: Two smart cards – valid certificate on the first token | ||
| :setup: | ||
| 1. Create IPA user and a decoy IPA user | ||
| 2. Initialize two SoftHSM tokens (simulating two smart cards) | ||
| 3. Place the target user's IPA certificate on token 1 | ||
| 4. Place the decoy user's IPA certificate on token 2 | ||
| 5. Configure SSSD for smart card authentication and start services | ||
| :steps: | ||
| 1. Authenticate as the target IPA user via nested ``su`` with the | ||
| smart card PIN | ||
| :expectedresults: | ||
| 1. SSSD's ``p11_child`` finds valid certificates on both tokens, | ||
| SSSD maps the token-1 certificate to the target user, prompts | ||
| for PIN, and authentication succeeds | ||
| :customerscenario: True | ||
| """ | ||
| username = "scuser_t1" | ||
| decoy = "scdecoy_t1" | ||
| ipa.user(username).add() | ||
| ipa.user(decoy).add() | ||
|
|
||
| setup_two_tokens(client, ipa, token1_username=username, token2_username=decoy) | ||
| client.sssd.common.smartcard_with_softhsm(client.smartcard) | ||
| assert client.auth.su.smartcard_with_su(username, TOKEN_PIN) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a note to change this if you rename in SSSD/sssd-test-framework#239 |
||
|
|
||
|
|
||
| @pytest.mark.importance("critical") | ||
| @pytest.mark.topology(KnownTopology.IPA) | ||
| @pytest.mark.builtwith(client="virtualsmartcard") | ||
| def test_smartcard__two_tokens_match_on_second(client: Client, ipa: IPA): | ||
| """ | ||
| :title: Two smart cards – valid certificate only on the second token | ||
| :setup: | ||
| 1. Create IPA user and a decoy IPA user | ||
| 2. Initialize two SoftHSM tokens (simulating two smart cards) | ||
| 3. Place the decoy user's IPA certificate on token 1 | ||
| 4. Place the target user's IPA certificate on token 2 | ||
| 5. Configure SSSD for smart card authentication and start services | ||
| :steps: | ||
| 1. Authenticate as the target IPA user via nested ``su`` with the | ||
| smart card PIN | ||
| :expectedresults: | ||
| 1. SSSD's ``p11_child`` does **not** stop at token 1 (whose cert | ||
| maps to the decoy user); it continues to token 2, finds the | ||
| certificate that maps to the target user, prompts for PIN, and | ||
| authentication succeeds | ||
| :customerscenario: True | ||
| """ | ||
| username = "scuser_t2" | ||
| decoy = "scdecoy_t2" | ||
| ipa.user(username).add() | ||
| ipa.user(decoy).add() | ||
|
|
||
| setup_two_tokens(client, ipa, token1_username=decoy, token2_username=username) | ||
| client.sssd.common.smartcard_with_softhsm(client.smartcard) | ||
| assert client.auth.su.smartcard_with_su(username, TOKEN_PIN) | ||
|
|
||
|
|
||
| @pytest.mark.importance("critical") | ||
| @pytest.mark.topology(KnownTopology.IPA) | ||
| @pytest.mark.builtwith(client="virtualsmartcard") | ||
| def test_smartcard__two_tokens_match_on_both(client: Client, ipa: IPA): | ||
| """ | ||
| :title: Two smart cards – valid certificate on both tokens | ||
| :setup: | ||
| 1. Create IPA user | ||
| 2. Initialize two SoftHSM tokens (simulating two smart cards) | ||
| 3. Place a valid IPA certificate for the same user on both tokens | ||
| 4. Configure SSSD for smart card authentication and start services | ||
| :steps: | ||
| 1. Authenticate as the IPA user via nested ``su`` with the PIN of | ||
| the first token | ||
| :expectedresults: | ||
| 1. SSSD's ``p11_child`` finds valid certificates on both tokens and | ||
| authentication succeeds regardless of which token is tried first | ||
| :customerscenario: True | ||
| """ | ||
| username = "scuser_both" | ||
| ipa.user(username).add() | ||
|
|
||
| setup_two_tokens(client, ipa, token1_username=username, token2_username=username) | ||
| client.sssd.common.smartcard_with_softhsm(client.smartcard) | ||
| assert client.auth.su.smartcard_with_su(username, TOKEN_PIN, num_certs=2) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change introduces a dependency on a personal fork (
krishnavema/sssd-test-framework). While this might be acceptable for development, it poses a security and maintenance risk for the main branch. The changes from this fork should be merged into the upstreamSSSD/sssd-test-frameworkrepository, and the dependency should point to an official release or commit from the upstream repository before this pull request is merged.