SpacetimeDB icon indicating copy to clipboard operation
SpacetimeDB copied to clipboard

[poc] SSL/TLS for standalone server

Open dare3path opened this issue 7 months ago • 3 comments
trafficstars

EDIT: future updates of this patch will be here: https://github.com/dare3path/spacetimedb-tls-patch because it's becoming too dependent on locally cloned modified/patched repos(for crates like rustls-pki-types, hyper-util) and these shouldn't have to be like a requirement for this PR to work.

Description of Changes

(description is a bit outdated)

This is just a proof-of-concept patch to add TLS (and mTLS) support for the standalone server and thus addresses issue https://github.com/clockworklabs/SpacetimeDB/issues/1076 It's here in the hope the it might be useful for others, to give an idea, or show it's possible this way, but it's not intended to be merged (it's not of expected quality, it was made with grok3 and grok2 's help), it's just what I intend to use locally for myself before delving more deeply into SpacetimeDB. Thus, this PR is submitted as draft.

How to use after patched:

  • generate server private and public keys (maybe sign by your own local CA), can use this helper scripts for that https://github.com/dare3path/spacetimedb-cert-gen or just make sure you have the certificate (contains public key) server.crt and private key server.key and the certificate(contains public key) of the CA that signed the server's certificate as ca.crt or if it's a self-signed server certificate then use serverSS.crt instead(but you can't use server.crt(instead of ca.crt) because it was signed by a CA thus it's not self-signed) in all places where --cert is used (so where ca.crt and server.crt is used).
  • start the spacetimedb standalone server in TLS mode:
    spacetime start --edition standalone --listen-addr 127.0.0.1:3000 --ssl --cert ../spacetimedb-cert-gen/server.crt --key ../spacetimedb-cert-gen/server.key
    • can use --ssl, --tls, --https or --secure, they're aliases of the same thing.
  • start a rust client from a different terminal and connect to the server in TLS mode:
    cd ./crates/sdk/ && cargo run --example quickstart-chat -- --cert ../../../spacetimedb-cert-gen/ca.crt
    this will 404 if you haven't published it yet(see below)
  • use cli commands:
    spacetime version list
    spacetime version use 1.1.0
    spacetime server list
    spacetime server add --url https://127.0.0.1:3000 slocal --no-fingerprint
    spacetime server set-default slocal (can use https://127.0.0.1:3000 instead of slocal here)
    spacetime server list, should show this:
WARNING: This command is UNSTABLE and subject to breaking changes.

 DEFAULT  HOSTNAME                   PROTOCOL  NICKNAME  
          maincloud.spacetimedb.com  https     maincloud 
          127.0.0.1:3000             http      local     
     ***  127.0.0.1:3000             https     slocal    

assuming you're still inside ./crates/sdk/:

$ spacetime login --server-issued-login slocal --cert ../../../my/spacetimedb-cert-gen/ca.crt
WARNING: the server that you specified here as 'slocal' isn't the one that will be used by commands like 'spacetime publish' but instead it's the one listed on 'spacetime server list' as the default (3 stars) that will be used, eg. 127.0.0.1:3000 if you haven't manually added any via 'spacetime server add'.

We will log in directly to your target server.
We have logged in directly to your target server.
WARNING: This login will NOT work for any other servers.
Saving config to /home/user/.config/spacetime/cli.toml.
$ spacetime publish -p ../../modules/quickstart-chat/ --cert ../../../my/spacetimedb-cert-gen/ca.crt quickstart-chat
    Finished `release` profile [optimized] target(s) in 0.22s
Optimising module with wasm-opt...
Build finished successfully.
Uploading to slocal => https://127.0.0.1:3000
Publishing module...
Created new database with name: quickstart-chat, identity: c200ba48494b35ab616cea275571f895d0ac6bf6e16b391238bf59ec65d1410d
$ cargo run --example quickstart-chat -- --cert ../../../my/spacetimedb-cert-gen/ca.crt    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.48s
     Running `/home/user/SOURCE/SpacetimeDB/target/debug/examples/quickstart-chat --cert ../../../my/spacetimedb-cert-gen/ca.crt`
Fully connected and all subscriptions applied.
Use /name to set your name, or type a message!
User c2001e6a388eaebd connected.
message here
c2001e6a388eaebd: message here
message2 here
c2001e6a388eaebd: message2 here

(Ctrl+D(+Z on Windows) to exit, or Ctrl+C)

  • other cli commands you can run, in another terminal:
$ spacetime logs quickstart-chat --cert ../../../my/spacetimedb-cert-gen/ca.crt --follow
2025-04-13T05:10:45.901825Z  INFO: spacetimedb: Creating table `message`
2025-04-13T05:10:45.902506Z  INFO: spacetimedb: Creating table `user`
2025-04-13T05:10:45.904265Z  INFO: spacetimedb: Invoking `init` reducer
2025-04-13T05:10:45.906885Z  INFO: spacetimedb: Database initialized
$ spacetime server ping slocal --cert ../../../my/spacetimedb-cert-gen/ca.crt
WARNING: This command is UNSTABLE and subject to breaking changes.

Server is online: https://127.0.0.1:3000
$ spacetime server fingerprint slocal --cert ../../../my/spacetimedb-cert-gen/ca.crt
WARNING: This command is UNSTABLE and subject to breaking changes.

Fingerprint is unchanged for server slocal:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfwAqvSbxMUZKdCsvzr9tdQJOhuG/
24jZ+oMN18FS6Py9CDNzGeAzu2kqjlybtpYRqkchYqv8o44khX9TZlhyWA==
-----END PUBLIC KEY-----

Can use all relevant cli commands (that I'm aware of) that require server access by passing args --cert ca.crt(or --cert serverSS.crt if server was started with --cert serverSS.crt --key server.key --ssl), otherwise, without --cert, you'd have to have the public certificate of the CA(certificate authority) that signed the server's public key in your cert root store (eg. somewhere in /etc/ssl/ on Linux).

API and ABI breaking changes

TODO: evaluate this.

Expected complexity level and risk

3

Testing

TODO:

  • [ ] zeroize private keys, on drop. (needs patched rustls-pki-types crate)
  • [ ] fix load_root_cert's bad logic for the 1MiB limit read file(ie. this is wrong if reader.limit() == 0 && reader.get_ref().get_ref().metadata().await.is_ok() {), just like read_file_limit got fixed already .
  • [ ] possibly other fixes seen in the location where this actually gets updated from now on.

dare3path avatar Apr 12 '25 12:04 dare3path

Thank you for putting this together as an example!

bfops avatar Apr 14 '25 15:04 bfops

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar May 03 '25 18:05 CLAassistant

erm, this isn't meant to be merged, it's just a proof-of-concept, also it's outdated and some things remained unfixed. I stopped updating it here(in this PR) because I wanted to modify some dep crates (eg. ring,pki-types) (for the purpose of zeroize-ing the private keys) and thus I've had to use modified forks of them which shouldn't be in this PR via [patch.crates-io] section.

Did anyone only want to run the CI on it? I should probably rebase it first, but please let me know.

EDIT: Ah that comment must just be because you've just added CLAassistant and it's auto-commenting with that on all PRs. Carry on:)

dare3path avatar May 03 '25 19:05 dare3path