Skip to content
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

Finalize UZI PoC Q4 for YubiSign project #59

Open
wants to merge 185 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
185 commits
Select commit Hold shift + click to select a range
b02b92d
work on getting started
basvandriel Oct 29, 2024
5ab7a96
Work with local tool
basvandriel Oct 29, 2024
3b923b8
Work on docs
basvandriel Oct 31, 2024
2d57054
change urls
basvandriel Nov 19, 2024
d0f6ce2
work
basvandriel Nov 20, 2024
8a1fbd9
send jwt
basvandriel Nov 21, 2024
2f4c71a
work on local setup
basvandriel Nov 21, 2024
95aa0c7
work on local setup
basvandriel Nov 21, 2024
24edf86
add images
basvandriel Nov 21, 2024
400cd0f
add screenshots
basvandriel Nov 21, 2024
42c99c6
work
basvandriel Nov 21, 2024
d079f16
move docs
basvandriel Nov 21, 2024
7b34883
rm image
basvandriel Nov 21, 2024
99e0a4f
add intro text
basvandriel Nov 21, 2024
b926f34
Merge branch 'uzipoc_q4_2024' into new-acme-server
basvandriel Nov 22, 2024
ec703aa
Remove initial test cert
basvandriel Nov 22, 2024
6aa00f5
Cleanup test
basvandriel Nov 22, 2024
0f427ff
local setup
basvandriel Nov 22, 2024
f1c5242
Remove comment
basvandriel Nov 22, 2024
6a1a513
add comment
basvandriel Nov 22, 2024
d9f5e42
Clarify documentation
basvandriel Nov 26, 2024
428ebb1
work
basvandriel Nov 26, 2024
2695424
add test
basvandriel Nov 27, 2024
d566329
add init file
basvandriel Nov 27, 2024
e691ee3
work
basvandriel Nov 27, 2024
556a779
Merge branch 'new-acme-server' into feature/dynamic-libykcs11
basvandriel Nov 27, 2024
6d3cd34
Add finder
basvandriel Nov 27, 2024
26228e5
Add license
basvandriel Nov 27, 2024
cbcec30
Add sample env file
basvandriel Nov 27, 2024
62ef173
Revert "Add sample env file"
basvandriel Nov 27, 2024
1ac2b0a
Add requirement
basvandriel Nov 27, 2024
fd54b67
Add sample .env file
basvandriel Nov 27, 2024
b77450c
Configure yubikey pin
basvandriel Nov 28, 2024
5da898a
Remove line
basvandriel Nov 28, 2024
865e9be
Remove debugging line
basvandriel Nov 28, 2024
b7e6906
Remove docker
basvandriel Nov 28, 2024
15b1bf8
Merge pull request #24 from minvws/new-acme-server
basvandriel Nov 28, 2024
492990c
Update app/pkcs.py
basvandriel Nov 28, 2024
3fb56b9
Merge pull request #27 from minvws/feature/license-in-readme
basvandriel Nov 28, 2024
6e043b5
add oidc login url
basvandriel Nov 28, 2024
b93ea6c
Fix
basvandriel Nov 28, 2024
188513e
Merge branch 'uzipoc_q4_2024' into feature/env-file-usage
basvandriel Nov 28, 2024
30d43d4
parse url for oidc provider
basvandriel Nov 28, 2024
366d3f9
check
basvandriel Nov 28, 2024
e02965d
add oidc provider base url
basvandriel Nov 29, 2024
eba7993
normalize urls
basvandriel Nov 29, 2024
57c7573
add ruff
basvandriel Nov 29, 2024
8b5d253
Add github action and configure ruff
basvandriel Nov 29, 2024
1ed420a
reformat
basvandriel Nov 29, 2024
fd2b12a
Fix linting errors
basvandriel Nov 29, 2024
f30b643
Install requirements
basvandriel Nov 29, 2024
633b292
Update app/wizard.py
basvandriel Nov 29, 2024
4330b91
Update .env.example
basvandriel Nov 29, 2024
1611829
Update README.md
basvandriel Nov 29, 2024
55aba06
Only run on PR
basvandriel Nov 29, 2024
2d339e0
WORK
basvandriel Nov 29, 2024
f09b961
Add dev requirements
basvandriel Nov 29, 2024
03ff65a
Merge pull request #28 from minvws/feature/env-file-usage
basvandriel Nov 29, 2024
44148b7
Merge branch 'uzipoc_q4_2024' into feature/dynamic-libykcs11
basvandriel Nov 29, 2024
f332a3b
Merge branch 'uzipoc_q4_2024' into feature/ruff
basvandriel Nov 29, 2024
944125c
fix test
basvandriel Nov 29, 2024
d3d6c9b
cleanup
basvandriel Nov 29, 2024
3e93d09
Change comment
basvandriel Nov 29, 2024
572d1bf
Merge pull request #25 from minvws/feature/dynamic-libykcs11
basvandriel Dec 3, 2024
f89fd75
parse url
basvandriel Dec 3, 2024
0aabad0
work
basvandriel Dec 3, 2024
77b0ba5
work
basvandriel Dec 3, 2024
3eed896
Fix pkcs lib
basvandriel Dec 3, 2024
0b97d62
Clean up docs
basvandriel Dec 3, 2024
e07fa30
apply feedback
basvandriel Dec 3, 2024
775a3bd
remove comment
basvandriel Dec 3, 2024
40156e0
fix readme file
basvandriel Dec 3, 2024
1a5ce2c
Merge pull request #32 from minvws/feature/ali-feedback
basvandriel Dec 3, 2024
a3248b6
fix readme
basvandriel Dec 3, 2024
0c0a56a
Fix docs
basvandriel Dec 3, 2024
db8ad63
Change reference to acme ca
basvandriel Dec 3, 2024
8e018cd
change readme
basvandriel Dec 3, 2024
774d89c
fix docs
basvandriel Dec 3, 2024
5045547
Merge branch 'uzipoc_q4_2024' into feature/directory-usage
basvandriel Dec 3, 2024
62560f3
Remove comment
basvandriel Dec 3, 2024
e98dc23
Cleanup
basvandriel Dec 3, 2024
5cbcdae
remove baseurl
basvandriel Dec 3, 2024
cb6a20d
work
basvandriel Dec 3, 2024
60b9e3c
Merge branch 'uzipoc_q4_2024' into feature/ruff
basvandriel Dec 3, 2024
94b0ca7
reformat
basvandriel Dec 3, 2024
58b6fb7
Close on finish and remove last page
basvandriel Dec 4, 2024
c21c800
reformat
basvandriel Dec 4, 2024
fbf5e39
format
basvandriel Dec 4, 2024
4af7331
Update app/acme_directory_configuration.py
basvandriel Dec 4, 2024
f986e45
apply feedback
basvandriel Dec 4, 2024
e96a864
refactor
basvandriel Dec 4, 2024
cc7746d
Change example .env
basvandriel Dec 4, 2024
15335af
reformat
basvandriel Dec 4, 2024
17a105f
Merge pull request #30 from minvws/feature/ruff
basvandriel Dec 4, 2024
79d363f
Merge branch 'uzipoc_q4_2024' into feature/directory-usage
basvandriel Dec 4, 2024
fad1f66
ruff format
basvandriel Dec 4, 2024
dd0b7be
cleanup
basvandriel Dec 4, 2024
2aeac6a
Ruff lint
basvandriel Dec 4, 2024
755f8b8
Merge branch 'uzipoc_q4_2024' into feature/noendpage
basvandriel Dec 4, 2024
211afbe
Remove profit page
basvandriel Dec 4, 2024
c13303f
Merge pull request #33 from minvws/feature/directory-usage
basvandriel Dec 4, 2024
a235f79
Refer to .in file for requirements
basvandriel Dec 4, 2024
79cb9dd
change text
basvandriel Dec 5, 2024
80c309f
Merge pull request #34 from minvws/feature/noendpage
basvandriel Dec 5, 2024
40e4aa0
Prevent backscrolls
basvandriel Dec 5, 2024
449ff8f
Remove comments
basvandriel Dec 5, 2024
6aca533
First step: refactor + complete emit
basvandriel Dec 5, 2024
a7e2cd7
Use of itemSelectionChanged signal
basvandriel Dec 5, 2024
20500d5
Rename vars
basvandriel Dec 5, 2024
018def0
Deselecting keys workds
basvandriel Dec 5, 2024
820239a
Remove need for selected key
basvandriel Dec 5, 2024
05d99ae
Merge pull request #36 from minvws/feature/no-back-after-keyselect
basvandriel Dec 5, 2024
a96dae5
Merge branch 'uzipoc_q4_2024' into feature/no-next-on-yubiselect
basvandriel Dec 5, 2024
4a4cdc1
Merge pull request #37 from minvws/feature/no-next-on-yubiselect
basvandriel Dec 5, 2024
ec11505
Verify Python version
basvandriel Dec 6, 2024
ee6afb5
Add link to piv tool
basvandriel Dec 6, 2024
c2a0946
add windows specific
basvandriel Dec 6, 2024
5c7646b
add windows requirements
basvandriel Dec 6, 2024
dfe7f6e
Set to rdo beheer for acme
basvandriel Dec 6, 2024
b85108a
Load .env file from correct location
basvandriel Dec 6, 2024
e495b85
Add git clone instruction
basvandriel Dec 6, 2024
08ffc81
apply feedback
basvandriel Dec 6, 2024
9795374
Update docs/LOCALSETUP.md
basvandriel Dec 6, 2024
04a4765
Fix .env.example
ricklambrechts Dec 6, 2024
8761027
Update windows Yubico PIV Tool libykc11 location
ricklambrechts Dec 7, 2024
c474387
env file loading cleanup
basvandriel Dec 9, 2024
f78c2e6
Merge pull request #40 from minvws/feature/jos-windows-feedback
basvandriel Dec 9, 2024
7cb4b4e
Merge pull request #44 from minvws/update-windows-path
basvandriel Dec 9, 2024
5843d8e
Merge pull request #43 from minvws/update-example-config
basvandriel Dec 9, 2024
163dd1c
Add extra windows docs
basvandriel Dec 9, 2024
8de77c9
Merge pull request #46 from minvws/feature/extra-docs-for-windows
basvandriel Dec 9, 2024
dd3f917
try
basvandriel Dec 11, 2024
e2ad04d
Use of direct QWizard
basvandriel Dec 11, 2024
6032292
cleanup
basvandriel Dec 11, 2024
e3c23d6
Merge pull request #53 from minvws/feature/no-window-resize
basvandriel Dec 11, 2024
c5edb4e
Add to docs
basvandriel Dec 12, 2024
6595f4e
add to docs
basvandriel Dec 12, 2024
18081f8
work
basvandriel Dec 12, 2024
4a00399
Cleanup
basvandriel Dec 12, 2024
c4b2b1f
add comment
basvandriel Dec 12, 2024
42bc807
work on resetting
basvandriel Dec 12, 2024
1a509c8
work on test
basvandriel Dec 12, 2024
781b414
Add test for empty result
basvandriel Dec 12, 2024
094c041
log
basvandriel Dec 12, 2024
c003a69
work
basvandriel Dec 12, 2024
b200a7b
refactor
basvandriel Dec 12, 2024
02cdb9f
cleanup
basvandriel Dec 12, 2024
04cd2c5
Enable logs
basvandriel Dec 12, 2024
35b0c9b
work
basvandriel Dec 12, 2024
1841775
cleanu
basvandriel Dec 12, 2024
d5887b0
work
basvandriel Dec 12, 2024
0619455
cleanup
basvandriel Dec 12, 2024
9887c94
Cleanup
basvandriel Dec 12, 2024
2a80a46
Cleanup
basvandriel Dec 12, 2024
8d962ef
work
basvandriel Dec 12, 2024
bc3b4d1
test
basvandriel Dec 16, 2024
035ecb6
rm rsa key import
basvandriel Dec 16, 2024
4bbfd96
Refactor welcome page
basvandriel Dec 16, 2024
8c7c697
remove comment
basvandriel Dec 16, 2024
0834acd
work
basvandriel Dec 16, 2024
15eaf5c
work
basvandriel Dec 16, 2024
512c7e7
test login
basvandriel Dec 17, 2024
338c6ae
test
basvandriel Dec 17, 2024
932ffdd
Cleanup
basvandriel Dec 17, 2024
16d884a
Merge pull request #55 from minvws/feature/refactor-welcome
basvandriel Dec 18, 2024
693431b
Merge pull request #56 from minvws/feature/refactor-login
basvandriel Dec 18, 2024
4847589
Refactor
basvandriel Dec 18, 2024
2ab5df9
Refactor
basvandriel Dec 18, 2024
56d2473
Add RSA step
basvandriel Dec 18, 2024
1a22eaf
Update main.py
basvandriel Dec 18, 2024
e5857e3
Remove unused import
basvandriel Dec 18, 2024
7ce888d
rename
basvandriel Dec 18, 2024
20205e3
cleanup
basvandriel Dec 18, 2024
2e62664
Merge pull request #54 from minvws/feature/yubi-reset
basvandriel Dec 18, 2024
e15d0e7
Merge branch 'uzipoc_q4_2024' into feature/pkcs-check
basvandriel Dec 18, 2024
309db22
Merge pull request #58 from minvws/feature/pkcs-check
basvandriel Dec 18, 2024
29573c7
Update docs/LOCALSETUP.md
basvandriel Dec 19, 2024
e43f519
Update docs/LOCALSETUP.md
basvandriel Dec 19, 2024
6d45d43
Update docs/LOCALSETUP.md
basvandriel Dec 19, 2024
47506eb
Remove defaults
basvandriel Dec 19, 2024
5129d06
work
basvandriel Dec 19, 2024
abd9dff
rename doc files
basvandriel Dec 19, 2024
e4526b6
change docs
basvandriel Dec 19, 2024
604fbb0
Merge pull request #60 from minvws/feature/rick-feedback
basvandriel Dec 19, 2024
0814b72
Variable ACME account email (#61)
basvandriel Dec 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[*.py]
indent_size = 4
max_line_length = 120

[Makefile]
indent_style = tab

[*.md]
trim_trailing_whitespace = false
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
YUBIKEY_PIN="123456"
ACME_SERVER_DIRECTORY_URL="https://acme.proeftuin.uzi-online.irealisatie.nl/directory"
OIDC_PROVIDER_BASE_URL="https://proeftuin.uzi-online.irealisatie.nl"
ACME_ACCOUNT_EMAIL="[email protected]"
35 changes: 35 additions & 0 deletions .github/workflows/formatlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Format and lint

on:
push:
branches:
- "main"
pull_request:
branches:
- "*"
types: [opened, synchronize, closed]

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.13"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install developement requirements
run: pip install -r requirements-dev.txt

- name: Check for linting errors
run: ruff check .

- name: Check for formatting errors
run: ruff format --check

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__pycache__
.pytest_cache
.env
75 changes: 45 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,60 @@
# Disclaimer
This Repository is created as a PoC (Proof of Concept) as part of the project *Toekomstbestendig maken UZI*, and
**should not be used as is in any production environment**.
# PoC with Yubikey

# Wat doet dit?
In order to automate certificate issuance for UZI, a PoC was done with a YubiKey and an ACME server. The keypairs are generated on the YubiKey and the certificate is issued by the ACME server. This program is designed to start with a _new_ YubiKey, meaning it should have the default PIN. This document will give you an high overview.

Dit neemt een yubikey (doe maar versie 5) en maakt daarin de PIV module *leeg*
### Steps

Nadat deze leeg is worden er 4 keys aangemaakt in de yubikey
- The YubiKey is reset: all the certificates on the device will be removed and the PIN code will be reset.
- We will generate 4 public and private key pairs on the YubiKey. These are for PIV Authentication, Digital Signature, Key Management and Card Authentication. Next to that, the YubiKey will generate additional attestation certificates, to prove that the private key is generated on the YubiKey itself. The private keys will always remain in the YubiKey.
- The user logs in via the chosen [authentication flow](./AUTH_FLOW.md). This returns an JWT, containing the user information.
- Per generated key pair, an certificate signing request (CSR) is created and signed by the private key.
- Finally, each certificate signing request with the corresponding attestation certificate is validated at the ACME server. When this is done, the server will issue an certificate for every key pair. Here, the JWT of the user is also used. This is done with the ACME server of iRealisatie. These are then saved back into the YubiKey into the corresponding slot.

Er wordt contact gelegd met de rdo-acme service. En er worden 4 orders aangemaakt
Now it is possible to use the certificate on the YubiKey to sign data.

Van deze 4 orders wordt de unique-anti-replay-token meegestuurd met een uzi-labs digid login verzoek
#### Diagram flow

Er wordt een browser geopend in de applicatie zelf, daarmee log je in als zorg identiteit bij de ziekenboeg-uzi-labs
This diagram expects that the Yubikey is already plugged in the user's computer. Next to that, it's expected that the user should use the **DigiD mock** login method.

De app haalt hierna de JWT-token op bij ziekenboeg-uzi-labs waarin de 4 acmetokens zitten.
```mermaid
sequenceDiagram
actor APP
participant YUBIKEY

Er wordt van de yubikey zelf opgehaald:
* Het intermediate certificaat behorende bij de yubikey zoals geleverd door yubico op de yubikey zelf
APP->>YUBIKEY: 1. Sends request to empty the Yubikeys certificates
YUBIKEY-->YUBIKEY: Empties the certificates

Per sleutel op de yubikey:
* Een door de yubikey ondertekend certificaat per sleutel waarin de garantie (attestation) staat dat de sleutel echt op een yubikey is gemaakt
* een CSR verzoek ondertekend door de aangemaakte sleutel
APP->>YUBIKEY: 2. Sends request to generate 4 new private key pairs
YUBIKEY-->YUBIKEY: 2.1 Create key pair for PIV Authentication
YUBIKEY-->YUBIKEY: 2.2 Create key pair for Digital Signature
YUBIKEY-->YUBIKEY: 2.3 Create key pair for Key Management
YUBIKEY-->YUBIKEY: 2.4 Create key pair for Card Authentication

Per order wordt dan verstuurd:
* De JWT
* Het yubikey intermediate certificaat
* Het attestation certificaat
create participant MAX
APP->>MAX: 3. Opens browser to login the user
MAX-->MAX: 3.1 Validates the user
MAX-->>APP: Returns the JWT containing the user information.

De acme server controleert dan per order:
* of het attestation certificaat van de sleutel klopt
* het token voor order in de JWT zit
* De JWT goed is en van een geldige uzi-cibg-labs-uitgever komt
APP->>APP: 4. Per generated key pair, <br> an certificate signing request (CSR)<br> is created and signed by the private key.

Als dat klopt dan geeft de acme server terug dat het klopt en dan vraagt deze app in de laatste stap een certificaat aan met de eerder genoemde CSR.
create participant ACME_SERVER
loop 5. For every certificate signing request (CSR)
APP->>ACME_SERVER: Validate every certificate signing request with the corresponding attestation certificate
ACME_SERVER-->>APP: OK
end

Als de CSR dezelfde public key heeft als in de vorige stap gecontroleerde gegevens wordt er een Labs-UZI certifcaat uitgegeven op basis van de gegevens in de JWT.
Dit certificaat bevat de huidige UZI-Certificaten structuur.
loop 6. For every key pair
APP->>ACME_SERVER: Request certificate for every key pair, also using the users' JWT
ACME_SERVER-->>APP: OK
ACME_SERVER-->>YUBIKEY: Save certificates
end

Als er een certificaat is opgehaald wordt dit opgeslagen op de juiste plek in de yubikey.
```

Door het laden van de yubikey pkcs11 library in de browser, office, mac os, windows of linux plekken (zoals beschreven door yubico) kan de yubikey daarna
worden gebruikt zoals een UZIpas ook gebruikt kan worden. Voor digitaal ondertekenen van documenten, verzoeken en om in te loggen in de browser bij
partijen die UZI certificaten login mogelijk maken.
### Disclaimer

This Repository is created as a PoC (Proof of Concept) as part of the project _Toekomstbestendig maken UZI_, and **should not be used as is in any production environment**.

### Licentie

This project is licensed under the [EUPL-1.2 license](./LICENSE.txt).
88 changes: 50 additions & 38 deletions app/acme.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@
import requests
from jwcrypto import jwk, jwt

import urllib.parse

from app.acme_directory_configuration import ACMEDirectoryConfiguration


class Acme:
url = None
url: urllib.parse.ParseResult
key = None
nonce = None
kid = None
order = None
certurl = None
finalize = {}

def __init__(self, url):
self.url = url
_directory_configuration: ACMEDirectoryConfiguration

def __init__(
self,
directory_config: ACMEDirectoryConfiguration,
):
self._directory_configuration = directory_config

def debugrequest(self, protected, payload):
print(" protected")
Expand All @@ -36,9 +45,7 @@ def gen_key(self):
This does only generate a P-256 key for use with JWT.
This key is only used during the session to request a certificate from ACME.
"""
self.key = jwk.JWK.generate(
kty="EC", crv="P-256", key_ops=["verify", "sign"], alg="ES256"
)
self.key = jwk.JWK.generate(kty="EC", crv="P-256", key_ops=["verify", "sign"], alg="ES256")

def get_nonce(self):
"""
Expand All @@ -47,7 +54,10 @@ def get_nonce(self):
without having to use the previous nonce. This is stored in self.nonce
as with all updates, as every request answers with a new nonce.
"""
response = requests.get(self.url + "acme/new-nonce", timeout=60)
response = requests.get(
self._directory_configuration.new_nonce_url,
timeout=60,
)
self.nonce = response.headers["Replay-Nonce"]

def account_request(self, request):
Expand All @@ -58,18 +68,20 @@ def account_request(self, request):
add the nonce (see above), url and alg and tada.wav.
"""
print("Account Request")

protected = {
"alg": "ES256",
"nonce": self.nonce,
"url": self.url + "acme/new-acct",
"url": self._directory_configuration.new_account_url,
"jwk": self.key.export_public(True),
}
token = jwt.JWS(payload=json.dumps(request))
token.add_signature(self.key, alg="ES256", protected=protected)
self.debugrequest(protected, request)
headers = {"Content-Type": "application/jose+json"}

response = requests.post(
self.url + "acme/new-acct",
self._directory_configuration.new_account_url,
data=token.serialize(),
headers=headers,
timeout=60,
Expand All @@ -88,18 +100,21 @@ def create_order(self, keynum, order):
afterwards.
"""
print("Order")

new_order_url = self._directory_configuration.new_order_url

protected = {
"alg": "ES256",
"nonce": self.nonce,
"url": self.url + "acme/new-order",
"url": new_order_url,
"kid": self.kid,
}
self.debugrequest(protected, order)
token = jwt.JWS(payload=json.dumps(order))
token.add_signature(self.key, alg="ES256", protected=protected)
headers = {"Content-Type": "application/jose+json"}
response = requests.post(
self.url + "acme/new-order",
new_order_url,
data=token.serialize(),
headers=headers,
timeout=60,
Expand Down Expand Up @@ -132,13 +147,19 @@ def challenge(self, challengeurl):
token = jwt.JWS(payload="")
token.add_signature(self.key, alg="ES256", protected=protected)
headers = {"Content-Type": "application/jose+json"}
response = requests.post(
challengeurl, data=token.serialize(), headers=headers, timeout=60
)

# Request the challenge per PIV-slot from the ACME-server.
# This will return a random token, with the status of pending.
#
# Later on, these tokens from the challenges should be contained in the users' JWT.
response = requests.post(challengeurl, data=token.serialize(), headers=headers, timeout=60)
returned_json = response.json()

self.debugresponse(response)
self.nonce = response.headers["Replay-Nonce"]
assert response.json()["status"] in ["pending", "valid"]
return response.json()["challenges"], response.json()["status"]

assert returned_json["status"] in ["pending", "valid"]
return returned_json["challenges"], returned_json["status"]

def send_challenge_jwt(self, challenge, hw_attestation, uzi_jwt, f9_cert):
"""
Expand Down Expand Up @@ -167,9 +188,7 @@ def send_challenge_jwt(self, challenge, hw_attestation, uzi_jwt, f9_cert):
}
print(" headers")
print(headers)
response = requests.post(
challengeurl, data=token.serialize(), headers=headers, timeout=60
)
response = requests.post(challengeurl, data=token.serialize(), headers=headers, timeout=60)
self.nonce = response.headers["Replay-Nonce"]
self.debugresponse(response)

Expand All @@ -191,15 +210,13 @@ def notify(self, notifyurl):
token = jwt.JWS(payload=json.dumps({}))
token.add_signature(self.key, alg="ES256", protected=protected)
headers = {"Content-Type": "application/jose+json"}
response = requests.post(
notifyurl, data=token.serialize(), headers=headers, timeout=60
)
response = requests.post(notifyurl, data=token.serialize(), headers=headers, timeout=60)
self.nonce = response.headers["Replay-Nonce"]
self.debugresponse(response)
assert response.json()["status"] in ["pending", "valid"]
return response.json()["status"], response.json()["url"]

def final(self, keynum, csr):
def final(self, keynum, csr, jwt_token: str):
"""
There is an order, we are correct. Now we get to request a certificate.
To do this we provide a CSR and that gets signed with the root/sub-CA
Expand All @@ -213,18 +230,18 @@ def final(self, keynum, csr):
"kid": self.kid,
}
payload = {
# "csr": b64encode(csr).decode().replace('+','-').replace('/','_'),
"csr": urlsafe_b64encode(csr)
.decode()
.rstrip("="),
"csr": urlsafe_b64encode(csr).decode().rstrip("="),
}
self.debugrequest(protected, payload)
token = jwt.JWS(payload=json.dumps(payload))
token.add_signature(self.key, alg="ES256", protected=protected)
headers = {"Content-Type": "application/jose+json"}
response = requests.post(
self.finalize[keynum], data=token.serialize(), headers=headers, timeout=60
)
headers = {
"Content-Type": "application/jose+json",
"X-Acme-Jwt": jwt_token,
Copy link
Member

@ricklambrechts ricklambrechts Dec 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally the JWT is already sent as a challenge and we should not need to update the finalize request.

}

# This calls the finalize method, preparing the certificate
response = requests.post(self.finalize[keynum], data=token.serialize(), headers=headers, timeout=60)
self.nonce = response.headers["Replay-Nonce"]
self.debugresponse(response)
assert response.json()["status"] == "valid"
Expand All @@ -246,11 +263,8 @@ def getcert(self):
token = jwt.JWS(payload="")
token.add_signature(self.key, alg="ES256", protected=protected)
headers = {"Content-Type": "application/jose+json"}
response = requests.post(
self.certurl, data=token.serialize(), headers=headers, timeout=60
)
response = requests.post(self.certurl, data=token.serialize(), headers=headers, timeout=60)
self.nonce = response.headers["Replay-Nonce"]
self.debugresponse(response)
return response.text

def clean_headers(self, headers):
Expand Down Expand Up @@ -292,6 +306,4 @@ def pprint(self, data):
"""
A simple hack to learn pprint to add some spaces upfront. Better for viewing
"""
print(
"\n".join([" " + x for x in pprint.pformat(data, width=80).splitlines()])
)
print("\n".join([" " + x for x in pprint.pformat(data, width=80).splitlines()]))
13 changes: 13 additions & 0 deletions app/acme_directory_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from dataclasses import dataclass


@dataclass
class ACMEDirectoryConfiguration:
"""
This data is generated from the directory endpoint. These endpoints can be different per server.
"""

new_order_url: str
new_account_url: str
new_nonce_url: str
revoke_cert_url: str
Loading
Loading