{"id":13766711,"url":"https://github.com/coreos/fero","last_synced_at":"2026-01-14T13:39:51.099Z","repository":{"id":66191059,"uuid":"127056394","full_name":"coreos/fero","owner":"coreos","description":"YubiHSM2-backed signing server","archived":true,"fork":false,"pushed_at":"2018-11-12T15:26:12.000Z","size":169,"stargazers_count":209,"open_issues_count":0,"forks_count":12,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-06-09T13:41:50.665Z","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":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coreos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"code-of-conduct.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-03-27T23:12:52.000Z","updated_at":"2024-06-12T01:27:18.000Z","dependencies_parsed_at":"2023-03-07T10:15:52.711Z","dependency_job_id":null,"html_url":"https://github.com/coreos/fero","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/coreos/fero","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreos%2Ffero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreos%2Ffero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreos%2Ffero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreos%2Ffero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coreos","download_url":"https://codeload.github.com/coreos/fero/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreos%2Ffero/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28421498,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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-08-03T16:00:59.775Z","updated_at":"2026-01-14T13:39:51.080Z","avatar_url":"https://github.com/coreos.png","language":"Rust","readme":"# fero\n\nfero is a secure signing server built around the [YubiHSM2]. fero maintains a\nset of private RSA keys in the YubiHSM and uses them to produce PGP (or\nPKCS#1v1.5) signatures when an authorized signing request is received. It is\ndesigned to be a replacement for manual signing processes with `gpg` or `openssl\nrsautl -sign`.\n\n[YubiHSM2]: https://www.yubico.com/products/yubihsm/\n\n## Model\nfero makes a distinction between private keys it manages (called \"secrets\") and\npublic keys which can be used to manage and use secrets (called \"users\"). Each\nsecret has its own numerical threshold for performing signing or management\noperations, and each user has a weight for each individual secret. Thus, signing\npermissions can be controlled highly granularly - each user is explicitly\ngranted fractional control over any secrets they may have access to. This level\nof granularity can also be used to build a signing hierarchy - a project with\nartifacts produced by several different teams but signed by a single secret can\nassign weights for the top-level secret only to team-level secrets which are\nalso stored in fero. Individual team members are then assigned weight for their\nteam's secret only, and when all teams have individually signed an artifact, the\ntop-level secret can then be used to re-sign the artifact.\n\nSigning and online management operations with fero all follow the same basic\nworkflow:\n* The payload is generated.\n    * For signing operations, this is the actual artifact to sign.\n    * For management operations, this is a specially formatted payload generated\n      with the fero command-line client.\n* Each user who wishes to authorize the operation signs the payload with their\n  public key.\n* The user signatures are collected and submitted by a single party along with\n  the actual request to perform the operation.\n* The fero server verifies each submitted user signature, and sums their weights\n  for the requested secret.\n* If the secret's threshold is met or exceeded, the fero server performs the\n  operation and returns any artifact produced by the operation.\n    * For signing operations, this is the signature by the secret over the\n      payload.\n    * For management operations, there is no artifact produced.\n\n## Deployment\n\n### Structure and requirements\nfero is intended to be deployed on a machine which is not directly connected to\nthe Internet. To that end, there are three components to fero:\n* The fero server. This is run on a non-Internet-connected machine with the\n  YubiHSM2 present.\n* The fero bastion. This is run on a machine with limited network access that\n  must also have access to the non-Internet-connected server machine. It acts as\n  a simple proxy between clients and the server.\n* The fero client. This is run by fero users on any machine with access to the\n  fero bastion.\n\nThe fero server requires a system with `libyubihsm.so` from the [YubiHSM2 SDK]\ninstalled, and a YubiHSM2 device attached to the system.\n\n[YubiHSM2 SDK]: https://developers.yubico.com/YubiHSM2/Releases/\n\n### Setup\nBoth of these methods assume you are starting with a YubiHSM2 in the\nfactory-default configuration. If not, you should reset your YubiHSM2.\n\n#### Containerized setup (recommended)\nOn the `fero-server` host:\n1. Preload the fero-server and yubihsm-connector Docker images onto the host.\n   These can be built from `fero-server/Dockerfile` and\n   `fero-server/Dockerfile.connector`, respectively.\n2. Configure a Docker bridge network over which the connector and server can\n   communicate:\n```sh\ndocker network create --driver bridge fero\n```\n3. Create a container for the connector:\n```sh\ndocker create --name yubihsm-connector --network fero -v /dev:/dev --privileged=true yubihsm-connector\ndocker start yubihsm-connector\n```\n4. Provision the YubiHSM2 via fero-server's `provision` command:\n```sh\ndocker run -it --rm --network fero -v ${FERO_DATA_PATH}:/fero fero-server provision -y\n```\nYou will be prompted for two passwords, one for the new administrative AuthKey\nthat will be created on the YubiHSM2 and one for the application AuthKey that\nfero-server will use.\n\n5. Create and run the fero-server container:\n```sh\ndocker create --name fero-server --network fero -v ${FERO_DATA_PATH}:/fero -t fero-server serve -k 3 -w $YOUR_APP_PASSWORD\ndocker start fero-server\n```\n6. Add secrets and users as desired (see \"Management\" section).\n\nOn the `fero-bastion` host:\n1. Preload the fero-bastion Docker image onto the host. This can be built from\n   `fero-bastion/Dockerfile`.\n2. Create and run the fero-bastion container:\n```sh\ndocker create --name fero-bastion -t fero-bastion --server-address $FERO_SERVER_ADDRESS\ndocker start fero-bastion\n```\n\n#### Non-containerized setup\nOn the `fero-server` host: \n1. Configure [`yubihsm-connector`]. Make a note of its settings, as you'll need\n   to tell `fero-server` about them.\n2. If you haven't already configured your YubiHSM2, do so now with `fero-server -d /path/to/fero.db\n   provision -y`. Make a note of both passwords you enter here; you'll need the administrative\n   AuthKey if you ever need to reconfigure the YubiHSM2, and you'll need the application AuthKey to\n   use fero.\n4. Start `fero-server` with the options you've noted from the previous steps,\n   and the desired address/port to listen on: `fero-server -d /path/to/fero.db serve -a\n   ${LISTEN_ADDR} -k 3 -w ${APPLICATION_PASSWORD} -c ${CONNECTOR_URL} -p ${LISTEN_PORT}`\n\nOn the `fero-bastion` host:\n\n1. Run `fero-bastion -a ${BASTION_LISTEN_ADDRESS} -p ${BASTION_LISTEN_PORT} -s\n   ${SERVER_LISTEN_ADDRESS} -r ${SERVER_LISTEN_PORT}`.\n\n[`yubihsm-connector`]: https://developers.yubico.com/YubiHSM2/Component_Reference/yubihsm-connector/\n[`yubihsm-shell`]: https://developers.yubico.com/YubiHSM2/Component_Reference/yubihsm-shell/\n\n### Management\nThe examples given are for use with the containerized setup listed above. If\nyou're not using the containerized setup, just drop the Docker portions of the\nexamples and run `fero-server` directly. You will also need to provide the\nconnector URL and database path.\n\n#### Secrets \nFero supports both PGP and raw RSA private keys. Secrets can be added with\neither `add-pgp-secret` or `add-pem-secret`, depending on the type of secret you\nwish to add. Each also requires the AuthKey and database path. For PGP secrets,\nyou will also need to specify which subkey you wish to store.\n\n**Important**: Fero does not support ASCII-armored PGP data, so if your private\nkey is ASCII-armored you will need to dearmor it (`gpg2 --dearmor\narmored_key.gpg \u003e dearmored_key.gpg`).\n\n* PEM secrets:\n```sh\ndocker run -it --rm --network fero \\\n    -v ${FERO_DATA_PATH}:/fero -v $(pwd):/data fero-server add-pem-secret \\\n    -k 3 -w $YOUR_APP_PASSWORD \\\n    --name $SECRET_NAME \\\n    --threshold $SECRET_THRESHOLD \\\n    --file path/to/some.pem\n```\n* PGP secrets:\n```sh\ndocker run -it --rm --network fero \\\n    -v ${FERO_DATA_PATH}:/fero -v $(pwd):/data fero-server add-pgp-secret \\\n    -k 3 -w $YOUR_APP_PASSWORD \\\n    --name $SECRET_NAME \\\n    --threshold $SECRET_THRESHOLD \\\n    --subkey $DESIRED_SUBKEY \\\n    --file path/to/some_private_key.pgp\n```\n\n#### Users\nAdding users can be done with the `add-user` subcommand. \n\n**Important**: Fero does not support ASCII-armored PGP data, so if your public\nkey is ASCII-armored you will need to dearmor it (`gpg2 --dearmor\narmored_key.gpg \u003e dearmored_key.gpg`).\n```sh\ndocker run -it --rm --network fero \\\n    -v ${FERO_DATA_PATH}:/fero -v $(pwd):/data fero-server add-user \\\n    -k 3 -w $YOUR_APP_PASSWORD \\\n    --file path/to/some_public_key.pgp\n```\n\nSetting a user's weight for a key can be done with the `set-user-weight`\nsubcommand:\n```sh\ndocker run -it --rm --network fero \\\n    -v ${FERO_DATA_PATH}:/fero fero-server set-user-weight \\\n    --name $SECRET_NAME\n    --user $USER_PGP_FINGERPRINT \\\n    --weight $NEW_WEIGHT\n```\n\n## Usage\n\n### Signing\nOnce you've populated the server with your secrets and users, and set the\nappropriate weights and thresholds, signing is relatively straightforward.\nSimply use the `sign` subcommand of `fero-client` along with each user's\nsignature:\n```sh\nfero-client -a $BASTION_ADDRESS sign \\\n    -f myfile.txt \\\n    -o myfile.txt.sig \\\n    -k mysecret \\\n    -s myfile.txt.sig.1 -s myfile.txt.sig.2 -s myfile.txt.sig.3\n```\n\nFor PKCS signatures, there's a little more work to do. Fero expects the \"file\"\nfor PKCS signatures to be the actual SHA256 hash of the content you're signing:\n```sh\nopenssl dgst -sha256 -out myfile.txt.hash myfile.txt\n# Sign myfile.txt.hash as normal\nfero-client -a $BASTION_ADDRESS sign \\\n    -f myfile.txt.hash \\\n    -o myfile.txt.sig \\\n    -k mysecret \\\n    -s myfile.txt.sig.1 -s myfile.txt.sig.2 -s myfile.txt.sig.3\n```\n\n### User/secret management\nKey management operations use the same authentication method as signing\noperations, so any set of users which can sign with a given key can also manage\nit. `fero-client` includes subcommands for generating the appropriate payloads\nto sign for the various key management operations.\n\n#### Setting secret thresholds\n```sh\nfero-client -a $BASTION_ADDRESS threshold-payload -f threshold_payload -k mysecret -t 1000\n# Sign threshold_payload\nfero-client -a $BASTION_ADDRESS threshold -k mysecret -t 1000 \\\n    -s threshold_payload.sig.1 -s threshold_payload.sig.2 -s threshold_payload.sig.3\n```\n\n#### Updating users' weights\n```sh\nfero-client -a $BASTION_ADDRESS weight-payload -f weight_payload -k mysecret -u $USERID -w 300\n# Sign weight_payload\nfero-client -a $BASTION_ADDRESS weight -k mysecret -u $USERID -w 300 \\\n    -s weight_payload.sig.1 -s weight_payload.sig.2 -s weight_payload.sig.3\n```\n","funding_links":[],"categories":["Security","Hardening"],"sub_categories":["Hardening","Ghidra"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreos%2Ffero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoreos%2Ffero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreos%2Ffero/lists"}