Skip to content

Postgres custom root certificates#3381

Closed
itowlson wants to merge 4 commits intospinframework:mainfrom
itowlson:pg-certs-5
Closed

Postgres custom root certificates#3381
itowlson wants to merge 4 commits intospinframework:mainfrom
itowlson:pg-certs-5

Conversation

@itowlson
Copy link
Collaborator

Take two.

...

...

Fine. Fine. It's take six.

@itowlson itowlson force-pushed the pg-certs-5 branch 3 times, most recently from c09cd42 to 2539ba2 Compare February 4, 2026 22:33
…RNINGS INSTEAD OF A SEA OF RED

although

probably I should worry about more of those warnings

Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
@itowlson
Copy link
Collaborator Author

We need to make a call on whether to pursue this approach (where the root cert is a guest asset) or one of the previous approaches (where the root cert was part of runtime config). Some considerations:

  • The guest approach is architecturally novel. Previously, guest assets have been for the use of the guest, and host assets have part of the host configuration.
    • Specifically, root certs for socket operations are specified in runtime config, so it may seem weird to have a mix of approaches.
  • The guest approach may port more readily to hosts that don't support per-application runtime configuration. For example, it avoids the need for services to introduce new APIs like "configure root certs."
    • On the other hand, hosts may need to figure this out anyway, because sockets.
  • The guest approach means that the root cert is part of the app definition.
    • A user running the app from a registry won't be able to provide their own trusted root.
    • Rotating the root cert requires a re-deploy/re-push.
  • What works, what doesn't:
    • Guest approach works (but probably needs some tweaks around how the host gets the cert).
    • Original custom Postgres runtime config works.
    • Using the sockets runtime config doesn't work so far. I think something is amiss in the cert formats, but I may have muddled something up in my test config. So if we want to do this then I can look at it again, but I may need Lann on speed dial.
    • All these are "as far as I can tell" - I don't think anyone else has tried them.

Are we in a position to make a decision, so that we can move this forward?

@lann
Copy link
Collaborator

lann commented Feb 11, 2026

Given that the current postgres interface takes its connection string from the guest rather than some label indexing into runtime config, it seems consistent to me that the guest also be able to provide the root CA. I think this is somewhat specific to TLS for databases where it is (annoyingly) common for databases hosts to use private CAs.

@itowlson
Copy link
Collaborator Author

@lann Thanks. In that case, if you have a bit of bandwidth, would you be able to take a quick glance at the block starting at https://github.com/spinframework/spin/pull/3381/changes#diff-c1e22382ff034493d23bbce9900875142e6ba2bd5e0ddcfaaa7a71c3291048a8R136 please, and guide me on better ways to retrieve the guest file, because I'm pretty uncomfortable with what I have now! Thanks! (and if you don't have time then no worries)

@lann
Copy link
Collaborator

lann commented Feb 11, 2026

Faced with the stark reality of actual code implementing my theoretical suggestions I'm suddenly inspired to consider other options...

How would you feel about extending the WIT to allow specifying the root CA as a string?

resource connection-builder {
  constructor(address: string);
  set-root-ca: func(root-ca-pem: string) -> result<_, some-error>;
  // ...
  build: func() -> result<connection, error>;
}

@itowlson
Copy link
Collaborator Author

How would you feel about extending the WIT to allow specifying the root CA as a string?

Initially unenthusiastic. But I guess we could gussy it up in the SDKs to wrap up the builder and filesystem read calls (e.g. let conn = pg5::Connection::open("host=foo dbname=bar", Some("florp.pem")) expanding to 'fs read + builder new + set-ca + builder build'). So yeah maybe but I would reserve the right to wear a tragic, gloom-laden demeanour while implementing it.

I do worry it could be a trap for people who are used to writing connection strings. But I guess the logical conclusion is the SDK could parse out the relevant bit of the connection string and do shenanigans. I'd have to add 'haunted' to that demeanour though.

@itowlson itowlson closed this Feb 13, 2026
@github-project-automation github-project-automation bot moved this from Backlog to Done in Spin 4.0 Feb 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants