Support requesting certificates using ACME#1026
Conversation
1e6ff82 to
02f682d
Compare
Pull Request Test Coverage Report for Build 18357389084Details
💛 - Coveralls |
|
Thinking more about how to feature gate this more nicely, i think the appropriate thing is to make acme support opt-in through config even if the feature is enabled, that would require some refactoring, and to also make |
|
cACK 22081a4 I was able to successfully get the certificate when running |
How about default to Let’s Encrypt production when ACME is enabled but add a one-switch
Let's just not do this until a request to do so comes in. KISS.
Let's not make it optional because it's simpler. |
i just renamed it to
👍
i kinda disagree, because then enabling the option breaks things if acme not in used, making it effectively mandatory, and that doesn't make much sense as a default enabled option, which it probably should be? we already have manual TLS (just not exposed in the CLI) |
|
(if you feel strongly about acme being mandatory then my last fixup commit can be discarded instead of squashed, the code is kinda ugly for it due to clap limitations wrt |
|
I don't feel strongly about acme support being mandatory. It makes more sense to be opt-in at runtime. I misunderstood on first read. |
DanGould
left a comment
There was a problem hiding this comment.
Looks like caching must be implemented in order to accept this change
| #[cfg(feature = "acme")] | ||
| pub async fn serve_acme<EC, EA>(self, listener: TcpListener, acme_config: AcmeConfig<EC, EA>) | ||
| where | ||
| EC: 'static + std::fmt::Debug, | ||
| EA: 'static + std::fmt::Debug, | ||
| { | ||
| let tcp_incoming = TcpListenerStream::new(listener); | ||
|
|
||
| let tls_incoming = acme_config.incoming(tcp_incoming, Vec::new()); | ||
|
|
||
| self.serve_connections(tls_incoming).await; | ||
| } |
There was a problem hiding this comment.
better in a feature gated file imo but that's a nit
There was a problem hiding this comment.
as an extension trait? or can a second impl block be added in a separate mod?
There was a problem hiding this comment.
i believe a second impl block may be added in a separate mod and then imported at the top level in the parent.
There was a problem hiding this comment.
writing impl<D: crate::Db> crate::Service<D> { works from an acme.rs submodule for this. It's something that could be done to the manual_tls implementations too. @zealsham perhaps you'd like to pick this up as a follow up?
fwiw why i intended by possibly making it optional is to provide a default path instead of requiring an explicit path, but yes, storing the certificate state on disk is a requirement otherwise you get throttled by let's encrypt |
|
See clap-rs/clap#5687 for context about |
Couldn't a specific acme subommand be used with args `required to fix this grouping? |
|
i guess --cache-dir should definitely be --acme-cache-dir, but should--domain and --contact be prefixed as well? leaning towards yes. --lets-encrypt-staging seems sufficient as is though. |
|
prefix sounds good |
84abaca to
4dbacb7
Compare
|
Hmm, I failed to consider when CLI options are used as overrides... I'm leaning towards removing the |
|
also there's a bug in the handling of the ohttp-keys, since it has a clap default value, it will always override the config file even if not specified explicitly, i'm gonna fix it in this PR since it's basically the same change for --lets-encrypt-staging |
|
Have you considered an enum to prevent boolean hell?
|
yeah, but that seems like a lot of boilerplate, not sure it's any improvement in readability |
Makes all CLI args `Option<T>`, because unless explicitly provided, args shouldn't override config values.
971b5d6 to
0c9c56f
Compare
Currently the certificate cache directory is mandatory. In principle it doesn't have to be.
|
rebased on top of #1157 |
DanGould
left a comment
There was a problem hiding this comment.
Booleans in f8a147d seem sane to me.
uTACK f8a147d, but I know @spacebear21 said he'd give a review as well
spacebear21
left a comment
There was a problem hiding this comment.
utACK f8a147d (I tested the command with various arg combinations but haven't tested with an actually valid acme configuration).
| help = "A directory for writing mailbox data." | ||
| )] | ||
| pub storage_dir: PathBuf, | ||
| pub storage_dir: Option<PathBuf>, |
There was a problem hiding this comment.
This one is a special case because it's actually a required field. When not provided it now produces a less legible error message:
❯ cargo run
Compiling payjoin-directory v0.0.3 (/Users/spacebear/Projects/rust-payjoin/payjoin-directory)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 5.23s
Running `/Users/spacebear/Projects/rust-payjoin/target/debug/payjoin-directory`
Logging initialized
Error: configuration property "storage_dir" not found
vs. before:
❯ cargo run
Blocking waiting for file lock on build directory
Compiling payjoin-directory v0.0.3 (/Users/spacebear/Projects/rust-payjoin/payjoin-directory)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.03s
Running `/Users/spacebear/Projects/rust-payjoin/target/debug/payjoin-directory`
Logging initialized
error: the following required arguments were not provided:
--storage-dir <STORAGE_DIR>
Usage: payjoin-directory --storage-dir <STORAGE_DIR>
Maybe the solution is to just print a custom message if a storage_dir is not found in either config the file or cli args. Weird that clap doesn't really support these seemingly obvious usecases...
There was a problem hiding this comment.
yeah the error kind of sucks, but the change is intentional, with the previous behavior if it was provided in the config file then it would still error on the CLI
the CLI args are provided as overrides to the config which relies on Option
i'm not sure how to make the error more legible without adding a ton of boilerplate and changing this approach to composing cli & config
There was a problem hiding this comment.
I think it's fine for now, if we get more people running directories and getting confused by this message I'd consider it a good problem to have.

The first commit adds a
serve_acmemethod to the directory service struct using thetokio_rustls_acmecrate, feature gated behindacme.The second commit adds configuration fields (with no environment variable support, but see #1023), and uses
serve_acmeunconditionally if theacmefeature is enabled.TODO:
acmebuilds should make acme listening optionalPull Request Checklist
Please confirm the following before requesting review:
AI
in the body of this PR.