.gitbay/wiki/Architecture/06-Data-and-Cryptography.org

v1.41.0
gitbay/.gitbay/wiki/Architecture/06-Data-and-Cryptography.org rendered · source · history · blame · raw

120 lines · 9243 bytes

  1#+title: Data and cryptography
  2
  3* Data inventory
  4
  5Schema: =internal/store/migrations/=, 66 migrations. Classification:
  6*C* credential or secret, *P* personal data, *R* private repository
  7content (as confidential as the repository), *O* operational.
  8
  9| Domain          | Tables                                                                                      | Class | Notes                                           |
 10|-----------------+---------------------------------------------------------------------------------------------+-------+-------------------------------------------------|
 11| Identity        | =users=, =emails=, =ssh_keys=, =pgp_keys=, =orgs=, =org_members=, =teams=, =team_members=   | P     | email addresses in clear; keys are public       |
 12| Credentials     | =api_tokens=, =web_sessions=, =login_tokens=, =email_tokens=, =invites=                    | C     | SHA-256 hashes only                              |
 13| Repositories    | =repos=, =repo_access=, =team_repos=, =repo_topics=, =repo_watchers=, =repo_pins=, =repo_bookmarks=, =page_domains= | O |                                  |
 14| Collaboration   | =issues=, =issue_*=, =merge_requests=, =mr_*=, =labels=, =milestones=, =mentions=           | R     | bodies of issues, comments and reviews          |
 15| Releases, snippets | =releases=, =release_assets=, =snippets=, =snippet_files=                                | R     |                                                 |
 16| CI              | =builds= (includes logs), =build_schedules=, =runner_repos=, =runner_seen=                  | R     | build logs can echo anything a step prints      |
 17| CI secrets      | =build_secrets=                                                                             | C     | sealed (AES-256-GCM)                            |
 18| Integrations    | =webhooks= (secret), =webhook_deliveries=, =mirrors= (username, token)                      | C     | webhook secret and mirror token sealed          |
 19| Notifications   | =notifications= (mail queue), =inbox=, =push_devices= (APNs token), =push_queue=, =mail_replies= (Message-IDs of posted replies) | P     | device tokens sealed; looked up by SHA-256      |
 20| Signatures      | =commit_signatures=, =settings.key_epoch=                                                   | O     | verification cache                              |
 21| Audit and feed  | =audit_log=, =events=                                                                       | O, P  | actor ids, pruned argv, fingerprints and IPs in some audit rows, a hash chain (=prev_hash=, =hash=) |
 22| Dependencies    | =dep_checks=, =dep_reports=                                                                 | O     |                                                 |
 23
 24Outside the database:
 25
 26| Data                       | Location                          | Class |
 27|----------------------------+-----------------------------------+-------|
 28| Repository contents        | =<root>/repos=                    | R     |
 29| LFS objects                | =<root>/lfs=                      | R     |
 30| SSH host key               | =<root>/ssh/host_ed25519=         | C     |
 31| TLS keys (ACME)            | =<root>/acme=                     | C     |
 32| SMTP password              | =/etc/gitbay/config.toml=         | C     |
 33| APNs signing key (.p8)     | path in =push.key_file=           | C     |
 34| IMAP password              | path in =mail.inbound.password_file= | C  |
 35| Secret key file            | =server.secret_key_file= (=/etc/gitbay/secret.key=) | C |
 36| Backups                    | =/var/backups/gitbay=, offsite    | all of the above |
 37
 38No table stores client IP addresses as a column. The daemon writes a
 39client IP into an audit row only for authentication failures and
 40throttling (=internal/sshd/sshd.go=).
 41
 42* At rest
 43
 44| Item                                  | Protection                                                     |
 45|---------------------------------------+----------------------------------------------------------------|
 46| API tokens, sessions, login links, email codes, invites | SHA-256 of a 256-bit random value; the value is shown once and never stored (=internal/store/sessions.go=) |
 47| CI secrets, webhook secrets, mirror tokens, APNs device tokens | AES-256-GCM under a key file outside the database and outside =server.root=; additional data binds table, column and row (=internal/seal=, =internal/store/secrets.go=) |
 48| SQLite file                           | mode 0640, directory 0750                                      |
 49| Backups                               | local archives age-encrypted when =[backup] age_recipients= is set; restic encrypts the offsite copy; neither carries the secret key file, which is copied off the host by hand until a separate keys repository is set up |
 50| Disk                                  | no application-level encryption; any disk encryption is the host's |
 51
 52The database file or a backup read by anyone other than the =gitbay=
 53user discloses no CI secret, webhook secret, mirror token or device
 54token without the key file, which neither carries. Rotation:
 55=gitbayd admin secrets rotate= (Admin wiki).
 56
 57* In transit
 58
 59| Channel                  | Protection                                                   |
 60|--------------------------+--------------------------------------------------------------|
 61| SSH                      | Go =x/crypto/ssh=; ed25519 host key generated on first start |
 62| HTTPS                    | TLS 1.2 minimum (=cmd/gitbayd/tls.go=), ACME or operator certificates; HSTS one year |
 63| HTTP port 80             | ACME challenges and redirect only                            |
 64| git://                   | none (public data only; off by default)                      |
 65| Runner ↔ server          | SSH                                                           |
 66| SMTP                     | STARTTLS required unless the relay is local (=mail.require_tls=), or implicit TLS (=mail.tls=) |
 67| APNs                     | TLS, HTTP/2                                                  |
 68| IMAP                     | implicit TLS or STARTTLS, TLS 1.2 minimum, certificate verified (=internal/imapc=) |
 69| Webhooks                 | TLS when the URL is https; HMAC-SHA256 body signature in =X-Gitbay-Signature-256= (=internal/webhook/webhook.go=) |
 70| Mirrors                  | per URL; token passed through =GIT_ASKPASS=, never argv (=internal/mirror/mirror.go=) |
 71
 72TLS 1.2 is the minimum, set in code (=serverTLS= in
 73=cmd/gitbayd/tls.go=); cipher suites are Go's defaults.
 74
 75* Cryptographic primitives
 76
 77| Use                             | Primitive                                  | Code                               |
 78|---------------------------------+--------------------------------------------+------------------------------------|
 79| Token generation                | =crypto/rand=, 32 bytes                    | =internal/store/sessions.go=    |
 80| Token storage                   | SHA-256                                    | =sessions.go=                   |
 81| LFS transfer tokens             | HMAC-SHA256, secret in =settings=          | =internal/lfs/lfs.go=      |
 82| Webhook signatures              | HMAC-SHA256                                | =internal/webhook/webhook.go=  |
 83| APNs provider token             | ES256 JWT (ECDSA P-256)                    | =internal/push/token.go=           |
 84| SSH host key                    | ed25519                                    | =internal/sshd/sshd.go=     |
 85| Commit and tag signatures       | verify OpenPGP (ProtonMail go-crypto) and SSHSIG | =internal/sig=               |
 86| LFS object ids                  | SHA-256                                    | =internal/lfs/lfs.go=           |
 87
 88Signature verification results are cached in =commit_signatures= with
 89the global =key_epoch= at the time of verification. Any change to a
 90trust input (a key added or removed, an email verified) bumps the
 91epoch, which invalidates every cached result (=internal/store/users.go=,
 92=internal/control/sig.go=).
 93
 94The server holds no signing key and signs nothing. A "verified" badge
 95means a user's own key signed the commit.
 96
 97* Secret handling rules
 98
 99- Secrets enter only on stdin. A command must set =ReadsStdin=
100  to receive stdin at all; =TestStdinCommandsReadStdin= enforces it.
101  Examples: =repo secret set=, =repo deploy-key add=, =repo import
102  --token-stdin= (=internal/control/build.go=, =import.go=).
103- Secrets are listed by name, never echoed back.
104- The audit log stores argv with flag values stripped
105  (=internal/control/control.go=).
106- Mail errors are logged with addresses redacted
107  (=internal/notify/notify.go=).
108- CI secrets travel in the runner's claim only for trusted builds and
109  reach the container as environment variables through a 0600 env file
110  or podman's =--env NAME= pass-through, never argv
111  (=cmd/gitbay-runner/isolate.go=).
112
113* Retention
114
115Configured under =[retention]= for =audit=, =events=,
116=webhook_deliveries=, =mail= and =push=; unset means keep forever.
117Expired sessions and tokens are swept hourly regardless
118(=internal/config/config.go=, =cmd/gitbayd/main.go=).
119Accounts that never verify are removed after
120=registration.pending_expiry=. =account export= gives a user their data.