{"id":20286995,"url":"https://github.com/psf/psf-tuf-runbook","last_synced_at":"2025-04-11T09:37:28.061Z","repository":{"id":38300247,"uuid":"248815499","full_name":"psf/psf-tuf-runbook","owner":"psf","description":"A runbook for the PSF, for TUF key setup and initial signing operations to bootstrap signing for PyPI.","archived":false,"fork":false,"pushed_at":"2022-06-07T17:35:19.000Z","size":13524,"stargazers_count":15,"open_issues_count":6,"forks_count":7,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-10T06:49:42.162Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/psf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-20T17:34:10.000Z","updated_at":"2024-08-18T07:21:43.000Z","dependencies_parsed_at":"2022-09-08T08:50:13.160Z","dependency_job_id":null,"html_url":"https://github.com/psf/psf-tuf-runbook","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psf%2Fpsf-tuf-runbook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psf%2Fpsf-tuf-runbook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psf%2Fpsf-tuf-runbook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psf%2Fpsf-tuf-runbook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/psf","download_url":"https://codeload.github.com/psf/psf-tuf-runbook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248368701,"owners_count":21092436,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T14:37:45.513Z","updated_at":"2025-04-11T09:37:28.040Z","avatar_url":"https://github.com/psf.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"psf-tuf-runbook\n===============\n\nThis repository contains a runbook and supporting program for the Python Software Foundation's\nTUF key generation and signing ceremonies.\nThe procedures documented here are designed to implement the security policies for offline keys defined in\n[PEP 458 - Secure PyPI downloads with signed repository metadata](https://www.python.org/dev/peps/pep-0458/)\n\n**Due to COVID-19, this document has been modified for a two person, remote ceremony.**\n\n## Notation\n\nThis document is designed to be read as a *runbook* -- a collection of discrete instructions\nwith remediation steps that, if followed correctly, should result in the intended effects.\n\nWe use the following notation:\n\n* **DO** *actions*: Perform the following actions.\n* **IF** *condition* **THEN** *actions*: If *condition* is met, then perform the following *actions*.\n* **GO TO** *heading*: Go to the referenced heading in the runbook and perform the stated actions\nthereon.\n* **END**: You've reached an end state.\n\nIn addition, this document uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119)\nto describe optional and mandatory steps.\n\n## Start\n\n1. **DO GO TO** [Prepare the environment](#prepare-the-environment).\n\n## Prepare the environment\n\n1. **DO** perform the [pre-ceremony](PRE-CEREMONY.md).\n\n1. **DO** Start streaming the ceremony using the communication computer.\n\n1. **IF** you have a phone or other personal devices, **THEN** set them on airplane mode.\n\n1. **DO** boot the trusted offline machine (the Raspberry Pi \"ceremony computer\"), and log into it using the credentials provided\nduring the pre-ceremony.\n\n1. **DO** mount the flash storage stick:\n\n    ```bash\n    $ sudo mount -t vfat /dev/sda1 /media/ceremony-products -o umask=000\n    ```\n\n1. **DO** change directory to the runbook directory:\n\n    ```bash\n    $ cd ~/psf-tuf-runbook\n    ```\n\n1. **DO** take pictures of each HSM, in their tamper-evident bags.\n\n1. **DO** remove `YubiHSM2-1` (keytype: P-256) from its tamper-evident bag and **GO TO**\n[Provisioning the YubiHSM 2](#provisioning-the-yubihsm-2)\n\n1. **DO** remove `YubiHSM2-2` (keytype: P-384) from its tamper-evident bag and **GO TO**\n[Provisioning the YubiHSM 2](#provisioning-the-yubihsm-2)\n\n1. **DO** remove `YubiHSM2-3` (keytype: P-256) from its tamper-evident bag and **GO TO**\n[Provisioning the YubiHSM 2](#provisioning-the-yubihsm-2)\n\n1. **DO** remove `Nitrokey HSM-4` (keytype: P-384) from its tamper-evident bag and **GO TO**\n[Provisioning the Nitrokey HSM](#provisioning-the-nitrokey-hsm)\n\n1. **DO** remove `Nitrokey HSM-5` (keytype: P-256) from its tamper-evident bag and **GO TO**\n[Provisioning the Nitrokey HSM](#provisioning-the-nitrokey-hsm)\n\n1. **DO** remove `Nitrokey HSM-6` (keytype: P-384) from its tamper-evident bag and **GO TO**\n[Provisioning the Nitrokey HSM](#provisioning-the-nitrokey-hsm)\n\n1. **DO** copy the ceremony products to the flash storage stick:\n\n    ```bash\n    cp -R ./ceremony-products /media/ceremony-products\n    ```\n\n1. **DO** unmount the flash storage stick:\n\n    ```bash\n    $ sync\n    $ sudo umount /media/ceremony-products\n    ```\n\n1. **DO** perform the [post-ceremony steps](#post-ceremony).\n\n1. **END**\n\n## Provisioning the YubiHSM 2\n\n*Time estimate: 10 minutes*.\n\n1. **DO** locate and write down the serial number printed on the YubiHSM 2. Refer to the picture below:\n\n    ![A YubiHSM 2](./assets/yubihsm2.jpg)\n\n    In this picture, the serial number is `7550054`. Note that in later steps the serial number will\n    be 0-padded to 10 digits, like `0007550054`.\n\n1. **IF** the YubiHSM 2 is being reprovisioned due to a compromise or failed ceremony, **THEN** you\nmust perform a physical reset.\n\n    1. **DO** touch and hold the metal contact of the YubiHSM 2 for ten (10) seconds as you insert\n    it into the trusted offline computer.\n\n1. **IF** the YubiHSM 2 is being provisioned for the first time, **THEN** insert it into the trusted\noffline computer.\n\n1. **DO** ensure that exactly 1 (one) YubiHSM 2 is inserted into the trusted offline computer.\n\n1. **DO** run the `yubihsm-provision` binary, using your key type according to the following rules:\n\n    * **IF** your keytype is \"P-256\", **THEN** pass `--type p256`\n    * **IF** your keytype is \"P-384\", **THEN** pass `--type p384`\n\n    ```bash\n    $ yubihsm-provision --type KEY-TYPE\n    ```\n\n1. **DO** wait for this prompt:\n\n    ```\n    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n    !!!                    DANGER!                    !!!\n    !!!                                               !!!\n    !!!   This program will reset and reprovision     !!!\n    !!!   your YubiHSM 2 for TUF purposes.            !!!\n    !!!                                               !!!\n    !!!   Make sure to read the runbook before        !!!\n    !!!   using this program. Failure to do so        !!!\n    !!!   will cause PERMANENT key loss.              !!!\n    !!!                                               !!!\n    !!!   Hit \"y\" (case insensitive) to continue.     !!!\n    !!!                                               !!!\n    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n    ```\n\n1. **DO** hit `y` once ready to continue.\n\n1. **DO** wait for the following output and prompt:\n\n    ```\n    Discovered a Yubico YubiHSM with serial number XXXXXXXXXX\n    We've successfully authenticated with the HSM!\n    Continue with factory reset? This step is IRREVERSIBLE! [y/N]\n    ```\n\n1. **DO** confirm that the serial number in the output matches the serial number written down.\n\n1. **DO** hit `y` once ready to continue.\n\n1. **DO** wait for the following output and prompt:\n\n    ```\n    Success! Giving the HSM 10 seconds to come back online...\n\n    #####################################################\n    ###                                               ###\n    ###   We're going to create a new \"auth key\"      ###\n    ###   on your YubiHSM.                            ###\n    ###                                               ###\n    ###   This \"auth key\" will                        ###\n    ###   have a password that you MUST remember      ###\n    ###   OR store securely and will protect the      ###\n    ###   TUF keys that are going to be created.      ###\n    ###                                               ###\n    ###   Hit \"y\" (case insensitive) to continue.     ###\n    ###                                               ###\n    #####################################################\n    ```\n\n1. **DO** hit `y` once ready to continue.\n\n1. **DO** enter the new authentication key password generated for this YubiHSM during the pre-ceremony.\n\n1. **DO** re-enter the authentication key password.\n\n1. **DO** wait for the following output:\n\n    ```\n    Success! Provisioned a new authentication key as object 2 and deleted the default key\n    Success!\n    We're creating our TUF keys and attestation certificates now.\n    ```\n\n1. **DO** re-enter the authentication key password.\n\n1. **DO** wait for the program to exit.\n\n1. **DO** check for the following files in the runbook directory:\n\n    ```\n    ceremony-products/XXXXXXXXXX/XXXXXXXXXX_cert.der\n    ceremony-products/XXXXXXXXXX/XXXXXXXXXX_root_attestation.der\n    ceremony-products/XXXXXXXXXX/XXXXXXXXXX_root_pubkey.pub\n    ceremony-products/XXXXXXXXXX/XXXXXXXXXX_targets_attestation.der\n    ceremony-products/XXXXXXXXXX/XXXXXXXXXX_targets_pubkey.pub\n    ```\n\n    Where `XXXXXXXXXX` is the 0-prefixed serial number.\n\n1. **DO** change directories to the products directory for the current HSM:\n\n    ```bash\n    cd ceremony-products/XXXXXXXXXX\n    ```\n\n    Where `XXXXXXXXXX` is the 0-prefixed serial number.\n\n1. **DO** run the `raw-ec-points-to-pem` script with each public key generated above, using your key type according to the following rules:\n\n    * **IF** your keytype is \"P-256\", **THEN** pass `--type p256`\n    * **IF** your keytype is \"P-384\", **THEN** pass `--type p384`\n\n    ```bash\n    $ raw-ec-points-to-pem --type KEY-TYPE XXXXXXXXXX_root_pubkey.pub\n    $ raw-ec-points-to-pem --type KEY-TYPE XXXXXXXXXX_targets_pubkey.pub\n    ```\n\n1. **DO** confirm that the following files have been generated:\n\n    ```\n    ceremony-products/XXXXXXXXXX/XXXXXXXXXX_root_pubkey.pem\n    ceremony-products/XXXXXXXXXX/XXXXXXXXXX_targets_pubkey.pem\n    ```\n\n1. **DO** change directories back to the runbook directory.\n\n    ```bash\n    cd ~/psf-tuf-runbook\n    ```\n\n1. **DO** remove the HSM.\n\n1. **DO** label a tamper-evident bag with the HSM's signing body ID and 0-prefixed serial number.\n\n1. **DO** seal the provisioned HSM and folded authentication key password in the tamper-evident bag.\n\n1. **DO** hold the sealed tamper-evident bag up to the camera of the communication computer.\n\n## Provisioning the Nitrokey HSM\n\n*Time estimate: 10 minutes*.\n\n1. **DO** determine the current Security Officer PIN (\"SO-PIN\"):\n\n    1. **IF** the Nitrokey has not been provisioned before, **THEN** the SO-PIN is `3537363231383830`.\n\n    1. **IF** the Nitrokey has been previously provisioned, **THEN** the SO-PIN should have been retained from the previous provisoning.\n\n1. **DO** insert the Nitrokey HSM into the trusted offline computer.\n\n1. **DO** ensure that exactly one (1) Nitrokey HSM is inserted into the trusted offline computer.\n\n1. **DO** run the `nitrohsm-provision` script, using your SO-PIN:\n\n    ```bash\n    $ nitrohsm-provision --so-pin SO-PIN\n    ```\n\n1. **DO** wait for this prompt:\n\n    ```\n    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n    !!!                    DANGER!                    !!!\n    !!!                                               !!!\n    !!!   This program will reset and reprovision     !!!\n    !!!   your Nitrokey HSM for TUF purposes.         !!!\n    !!!                                               !!!\n    !!!   Make sure to read the runbook before        !!!\n    !!!   using this program. Failure to do so        !!!\n    !!!   will cause PERMANENT key loss and MAY       !!!\n    !!!   leave your HSM in an unusable state.        !!!\n    !!!                                               !!!\n    !!!   Hit \"y\" (case insensitive) to continue.     !!!\n    !!!                                               !!!\n    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n    ```\n\n1. **DO** hit `y` once ready to continue.\n\n1. **DO** wait for the following output and prompt:\n\n    ```\n    Successfully discovered a Nitrokey HSM with Slot #0\n    Continue with factory reset? This step is IRREVERSIBLE! [y/N]\n    ```\n\n1. **DO** hit `y` once ready to continue.\n\n1. **DO** wait for the following output and prompt:\n\n    ```\n    Success! Reinitialized the HSM.\n    Enter your NEW Security Officer PIN:\n    ```\n\n1. **DO** enter the *new* Security Officer PIN generated for this Nitrokey during the pre-ceremony.\n\n1. **DO** wait for the following prompt:\n\n    ```\n    Re-enter your NEW Security Officer PIN:\n    ```\n\n1. **DO** re-enter the *new* Security Officer PIN.\n\n1. **DO** wait for the following prompt:\n\n    ```\n    Enter your NEW user PIN:\n    ```\n\n1. **DO** enter the *new* user PIN generated for this Nitrokey during the pre-ceremony.\n\n1. **DO** wait for the following prompt:\n\n    ```\n    Re-enter your NEW user PIN:\n    ```\n\n1. **DO** re-enter the *new* user PIN.\n\n1. **DO** wait for the following output:\n\n    ```\n    Success! We've reinitialized the Nitrokey with a new SO PIN and user PIN.\n    Use this serial number when doing key generation: XXXXXXXXXXX\n    ```\n\n1. **DO** write down the serial number printed above on a *separate* piece of loose-leaf.\n\n1. **DO** run the `generate-nitrohsm-keys` script, using your key type according to the following rules:\n\n    * **IF** your keytype is \"P-256\", **THEN** pass `--type p256`\n    * **IF** your keytype is \"P-384\", **THEN** pass `--type p384`\n\n    ```bash\n    $ generate-nitrohsm-keys --type KEY-TYPE --serial XXXXXXXXXXX\n    ```\n\n1. **DO** wait for the following prompt:\n\n    ```\n    Enter your user PIN:\n    ```\n\n1. **DO** enter the *new* user PIN.\n\n1. **DO** check for the following files in the runbook directory:\n\n    ```\n    ceremony-products/XXXXXXXXXXX/XXXXXXXXXXX_root_pubkey.pub\n    ceremony-products/XXXXXXXXXXX/XXXXXXXXXXX_root_pubkey.pem\n    ceremony-products/XXXXXXXXXXX/XXXXXXXXXXX_targets_pubkey.pub\n    ceremony-products/XXXXXXXXXXX/XXXXXXXXXXX_targets_pubkey.pem\n    ```\n\n1. **DO** remove the HSM.\n\n1. **DO** label a tamper-evident bag with the HSM's signing body ID and serial number.\n\n1. **DO** seal the provisioned HSM and folded Security Officer and user PINs in the tamper-evident bag.\n\n1. **DO** hold the sealed tamper-evident bag up to the camera of the communication computer.\n\n## Post-ceremony\n\n1. **DO** insert the flash stick into the communication computer.\n\n1. **DO** navigate to the runbook repository in a new terminal.\n\n1. **DO** create a new branch:\n\n    ```bash\n    git checkout -b ceremony-YYYY-MM-DD\n    ```\n\n    Where `YYYY-MM-DD` is the current date.\n\n1. **DO** create the following new subdirectories:\n\n    ```bash\n    mkdir -p ceremony/YYYY-MM-DD/ceremony-products\n    mkdir -p ceremony/YYYY-MM-DD/images\n    ```\n\n    Where `YYYY-MM-DD` is the current date.\n\n1. **DO** copy the contents of the ceremony flash stick into the `ceremony-products` subdirectory.\n\n1. **DO** copy all images taken of the HSMs and tamper-evident bags into the `images` subdirectory.\n\n1. **DO** commit the results, signing with a publicly announced PGP key:\n\n    ```bash\n    git add ceremony/YYYY-MM-DD\n    git commit -S\n    ```\n\n    Where `YYYY-MM-DD` is the current date.\n\n1. **DO** push the branch to [psf/psf-tuf-runbook](https://github.com/psf/psf-tuf-runbook) and open\na PR for review.\n\n    ```bash\n    git push origin ceremony-YYYY-MM-DD\n    ```\n\n    Where `YYYY-MM-DD` is the current date.\n\n1. **DO** await for PR approval, and confirm that the branch is merged into the `main` branch.\n\n    * You **MAY** delete the original ceremony branch once merged.\n\n1. **DO** securely destroy the SD card used for the runbook image **OR** zero it:\n\n    ```bash\n    $ diskutil unmountDisk /dev/rdiskN\n    $ sudo dd bs=4m if=/dev/zero of=/dev/rdiskN\n    ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsf%2Fpsf-tuf-runbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpsf%2Fpsf-tuf-runbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsf%2Fpsf-tuf-runbook/lists"}