{"id":20498368,"url":"https://github.com/grapheneos/attestationserver","last_synced_at":"2025-04-04T18:06:12.892Z","repository":{"id":37692293,"uuid":"125600681","full_name":"GrapheneOS/AttestationServer","owner":"GrapheneOS","description":"attestation.app remote attestation server. Server code for use with the Auditor app: https://github.com/GrapheneOS/Auditor. It provides two services: submission of attestation data samples and a remote attestation implementation with email alerts to go along with the local implementation based on QR code scanning in the app.","archived":false,"fork":false,"pushed_at":"2025-03-27T16:08:29.000Z","size":3091,"stargazers_count":114,"open_issues_count":19,"forks_count":46,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-03-28T17:09:11.492Z","etag":null,"topics":["android","attestation","authenticity","cryptography","grapheneos","hsm","integrity","monitoring","remote-attestation","secure-boot","secureboot","security","strongbox","verifiedboot"],"latest_commit_sha":null,"homepage":"https://attestation.app/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GrapheneOS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"thestinger","custom":"https://grapheneos.org/donate"}},"created_at":"2018-03-17T05:46:22.000Z","updated_at":"2025-03-27T16:08:26.000Z","dependencies_parsed_at":"2023-09-24T17:20:17.107Z","dependency_job_id":"f83cc9e7-24f8-45ff-b3fe-1e98fa05579c","html_url":"https://github.com/GrapheneOS/AttestationServer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GrapheneOS%2FAttestationServer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GrapheneOS%2FAttestationServer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GrapheneOS%2FAttestationServer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GrapheneOS%2FAttestationServer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GrapheneOS","download_url":"https://codeload.github.com/GrapheneOS/AttestationServer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247226213,"owners_count":20904465,"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":["android","attestation","authenticity","cryptography","grapheneos","hsm","integrity","monitoring","remote-attestation","secure-boot","secureboot","security","strongbox","verifiedboot"],"created_at":"2024-11-15T18:13:57.634Z","updated_at":"2025-04-04T18:06:12.864Z","avatar_url":"https://github.com/GrapheneOS.png","language":"Java","readme":"See the overview of the project at https://attestation.app/about.\n\n## Installation guide\n\nThis is a generic guide on setting up the attestation server.\n\nSync submodules for sqlite4java prebuilt in libs/.\n\nYou need to set up nginx using the nginx configuration in the nginx directory in this repository.\nYou'll need to adjust it based on your domain name. The sample configuration relies on certbot,\n[nginx-rotate-session-ticket-keys](https://github.com/GrapheneOS/nginx-rotate-session-ticket-keys),\nand [certbot-ocsp-fetcher](https://github.com/tomwassenberg/certbot-ocsp-fetcher). Setting up the web server is out-of-scope for this guide.\n\nThe deploy and process scripts on the development machine require the following dependencies to be installed:\n\n    rsync, zopfli, parallel, yajl, brotli, nginx-mod-brotli, python3, python-pip, nodejs, npm, libxml2\n\n`validatornu` must be obtained manually\n[here](https://github.com/validator/validator/releases/tag/20.6.30) (vnu.linux.zip). Unzip it in\nthe same directory in AttestationServer and change the binary path in `process-static` from\n`validatornu` to `vnu-runtime-image/bin/vnu` using sed: `sed -i\n's+validatornu+vnu-runtime-image/bin/vnu+g' process-static`\n\nInstall a headless Java 18 runtime environment. The package name on Debian-based distributions is\n`openjdk-18-jre-headless` or `jre-openjdk-headless` on Arch Linux. Install `sqlite3` in order to\nset up the email configuration for the database.\n\nAs root, on the server:\n\n    useradd -m -s /bin/bash -b /var/lib attestation\n\n    mkdir -p /opt/attestation/deploy_{a,b}\n    ln -s /opt/attestation/deploy_a /opt/attestation/deploy\n\n    mkdir -p /srv/attestation.app_{a,b}\n    ln -s /srv/attestation.app_a /srv/attestation.app\n\nSet up ssh `authorized_keys` for the attestation user.\n\nCopy `attestation.service` to `/etc/systemd/system/attestation.service`.\n\nOn your development machine, you will need to change the `remote` variable in the deploy scripts\nto your server. You'll also need to change the\n[DOMAIN](https://github.com/GrapheneOS/AttestationServer/blob/df53e39706fdc6247ce497cb0776bf77fe931085/src/main/java/app/attestation/server/AttestationServer.java#L85)\nin AttestationServer.java to your server and the [app signing\nkey](https://github.com/GrapheneOS/AttestationServer/blob/df53e39706fdc6247ce497cb0776bf77fe931085/src/main/java/app/attestation/server/AttestationProtocol.java#L157-L162)\nand [app\nID](https://github.com/GrapheneOS/AttestationServer/blob/df53e39706fdc6247ce497cb0776bf77fe931085/src/main/java/app/attestation/server/AttestationProtocol.java#L154-L156).\nThen deploy the attestation server and static content:\n\n    npm i\n    python -m venv venv\n    source venv/bin/activate\n    pip install -r requirements.txt\n    ./deploy-server\n    ./deploy-static\n\nAs root on the server, enable and start the attestation server:\n\n    systemctl enable attestation\n    systemctl start attestation\n\nThe server will be listening on `[::1]:8080` by default which [can be changed](https://github.com/GrapheneOS/AttestationServer/blob/df53e39706fdc6247ce497cb0776bf77fe931085/src/main/java/app/attestation/server/AttestationServer.java#L320).\n\n## Email alert configuration\n\nIn order to send email alerts, AttestationServer needs to be configured with valid credentials for\nan SMTP server. The configuration is stored in the `Configuration` table in the database and can\nbe safely modified while the server is running to have it kick in for the next email alert cycle.\n\nOnly SMTPS (SMTP over TLS) with a valid certificate is supported for remote email servers.\nSTARTTLS is deliberately not supported because it's less secure unless encrypted is enforced, in\nwhich case it makes more sense to use SMTPS anyway. The username must also be the full address for\nsending emails.\n\nFor example, making an initial configuration:\n\n    sqlite3 attestation.db \"INSERT INTO Configuration VALUES ('emailUsername', 'alert@attestation.app'), ('emailPassword', '\u003cpassword\u003e'), ('emailHost', 'mail.grapheneos.org'), ('emailPort', '465')\"\n\nThe `attestation.service` unit only allows the service to communicate over `localhost` by default\nso the `IPAddressDeny`/`IPAddressAllow` configuration either needs to be removed or extended to\ninclude your DNS server and mail server IP addresses when using a remote mail server.\n\n### Handling abuse\n\nThe `emailBlacklistPatterns` array in\n[`src/main/java/app/attestation/server/AttestationServer.java`](https://github.com/GrapheneOS/AttestationServer/blob/df53e39706fdc6247ce497cb0776bf77fe931085/src/main/java/app/attestation/server/AttestationServer.java#L92-L94) can be used to blacklist email\naddresses using regular expressions. We plan to move this to a table in the database so that it\ncan be configured dynamically without modifying the sources, rebuilding and redeploying. For now,\nthis was added to quickly provide a way to counter abuse.\n\n## API for the Auditor app\n\n### QR code\n\nThe scanned QR code contains space-separated values in plain-text: `\u003cdomain\u003e \u003cuserId\u003e\n\u003csubscribeKey\u003e \u003cverifyInterval\u003e`. The `subscribeKey` should be treated as an opaque string rather\nthan assuming base64 encoding. Additional fields may be added in the future.\n\n### /auditor/challenge\n\n* Request method: POST\n* Request headers: n/a\n* Request body: n/a\n* Response body:\n\nReturns a standard challenge message in the same format as the Auditor app QR code. The challenge\ncan only be used once and expires in 1 minute.\n\nThe server challenge index is always zeroed out and the userId should be used instead.\n\n### /auditor/verify\n\n* Request method: POST\n* Request headers:\n\nThe `Authorization` header needs to be set to `Auditor \u003cuserId\u003e \u003csubscribeKey\u003e` for an unpaired\nattestation. That will also work for a paired attestation if the subscribeKey matches, but it\nshould be set to `Auditor \u003cuserId\u003e` to allow for subscribeKey rotation.\n\n* Request body:\n\nStandard attestation message in the same format as the Auditor app QR code.\n\n* Response body:\n\nReturns JSON with a `verifyInterval` field.\n\n## Logging\n\nLogs are written via stderr for journald. Log guidelines:\n\nemerg: filesystem or database corruption\nalert: service fully not functioning\ncrit: service partially not functioning\nerror: service side error for a specific request\nwarning: login failures, unexpected errors triggered by clients and missing setup for full functionality such as sending alerts\ninfo: security-relevant events such as logins, expected errors triggered by clients and status logging\ndebug: not used in production\n","funding_links":["https://github.com/sponsors/thestinger","https://grapheneos.org/donate"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrapheneos%2Fattestationserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrapheneos%2Fattestationserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrapheneos%2Fattestationserver/lists"}