Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finer SMTP TLS certificate control #4385

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

JosefSchoenberger
Copy link

This PR adds two new SMTP configurations regarding TLS:

  • SMTP_ADDITIONAL_ROOT_CERTS allows an admin to add new root certificates that Vaultwarden accepts for the SMTP server. This can be useful if the SMTP server only offers a self-signed certificate. Example: SMTP_ADDITIONAL_ROOT_CERTS=/etc/ssl/certs/mail1.pem;/etc/ssl/certs/mail2.pem
  • SMTP_USE_SYSTEM_ROOT_CERTS disables the system's root certificate store for TLS. This can be used in combination with SMTP_ADDITIONAL_ROOT_CERTS for certificate pinning.

@williamdes
Copy link
Contributor

Very interesting feature!

Copy link
Collaborator

@BlackDex BlackDex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine by me. This would even work if we want to switch to rustls instead of native.
Just a few comments.

Comment on lines +33 to +46
static SMTP_ADDITIONAL_ROOT_CERTS: Lazy<Option<Vec<Certificate>>> = Lazy::new(|| {
Some(
CONFIG
.smtp_additional_root_certs()?
.split(';')
.filter(|path| !path.is_empty())
.map(|path| {
let cert = std::fs::read(path)
.unwrap_or_else(|e| panic!("Error loading additional SMTP root certificate file {path}.\n{e}"));
Certificate::from_pem(&cert).unwrap_or_else(|e| panic!("Error decoding certificate file {path}.\n{e}"))
})
.collect(),
)
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to have this checked in config.rs.
There it should check upon loading the config if those certs exists or not and and there it may panic.
Causing a panic here is probably not really wanted in my opinion.

Same goes for validating of those certs are valid certs.
So best to move this to the validate_config function there i think.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that panicing only upon sending the first mail is not appropriate.

I'm not sure if I understand you correctly. I'm not familiar with Vaultwarden's codebase, but how should I proceed? I currently see three different options. Which do you prefer? Do you have something else in mind?

  1. SMTP_ADDITIONAL_ROOT_CERTS remains remain a static global variable, just that it is moved into config.rs and that verify_config reads it first, such that the Lazy evaluates instantly upon config verification. I dislike this option since (a) it uses a global variable and (b) any calls to update_config never actually reload the certificate (something that I missed in this pull request, too).
  2. I can also move the reading and parsing into verify_config and store the resulting certificate list in an internal Option config item upon success. That's fine considering that SMTP_ADDITIONAL_ROOT_CERTS is an Option anyway. The only disadvantage is that the name verify_config becomes misleading as a verification function typically has no side effects.
  3. I can also create a new internal gen config option of type Result<Option<Vec<Certificate>>, Box<dyn Error>> in which the generating function read and parse the certificates. Any errors that occur there are then stored as an Box<dyn Error> which is then caught in validate_config. The disadvantage of this approach is that the config is of type Result, yet it is never Err during runtime, so any uses of this config option will always need an additional call to unwrap first.

What is your opinion on that matter? Am I missing something totally obvious?

.env.template Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants