-
Notifications
You must be signed in to change notification settings - Fork 262
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
feat: wrap secrets in custom types to prevent them from leaking #925
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What have you thought about common/src/lib.rs::DatabaseReadyInfo
(mainly its password field)? I think we usually need it when db resource information is requested, but we should defend against logging it accidentally.
I wrapped the password in |
I don't think so. I think it's the address that can be used internally by the backend. It might save some external network calls when compared to accessing the DB through the public URL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @AlphaKeks, thanks for this! I left a couple of small comments, and clippy also has a suggestion in the CI failure
common/src/secrets.rs
Outdated
|
||
#[test] | ||
fn secret_struct() { | ||
#[allow(dead_code)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: is this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially I didn't have tests for it as I figured it's unnecessary (since everything we could test is basically already enforced by the compiler), but there was a point about having them to prevent regressions in the future. I wasn't entirely sure what to do with that, so if you think we should remove them, I will remove them again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry! I just meant the allow(dead_code) annotation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yeah. The compiler was complaining about the struct being unused.
A user in our discord brought up that using SharedDB will print out the database connection string when running or deploying a project, which in my opinion shouldn't be the default. What do you guys think about adding a CLI flag to both |
I would include the secrets exposing flagging for the DB connections as well. At the same time, maybe a global flag will do better? It's gonna be accounted for both |
Are you talking about a flag for I will start implementing the functionality for |
resources/static-folder/Cargo.toml
Outdated
@@ -11,6 +11,7 @@ async-trait = "0.1.56" | |||
dunce = "1.0.3" | |||
fs_extra = "1.3.0" | |||
serde = { version = "1.0.148", features = ["derive"] } | |||
shuttle-common = { path = "../../common", version = "0.18.0", default-features = false } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this as a static-folder
dep?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests were failing because of a type mismatch on this function.
cargo-shuttle/src/args.rs
Outdated
Secrets { | ||
#[arg(long)] | ||
/// Reveal the values of the secrets | ||
show: bool, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We considered lately that we would prefer not to show secrets at all. It's best to remain hidden after deploying, having the user deploy again if they want to change them. The idea is simple: if the user wants to display the previous secrets used for the deployment, shouldn't use Shuttle for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I will remove the flags.
@AlphaKeks Do you want more feedback or help with finishing this? I can take a look if needed. |
Oh yeah, kinda forgot about this, my bad! Will take a look tomorrow and get this up to date, then ask for review. I'm pretty sure this was basically finished. |
We've been discussing polishing this a bit before merging but it is almost there. Please take a look at my last review. |
9d83696
to
c4138a7
Compare
Hey @AlphaKeks, I hope you're doing alright :) Sorry for the delay and back and forth with the review, we're still interested in getting this merged, if you're also still interested in working on it and getting this through. After discussing it with the team, there are still a few changes we would like to make:
If you don't want to or don't have the time to continue working on it that's perfectly fine, just let us know and we'll take over. Thank you very much ! |
Not really interested anymore, sorry. |
No worries, thank you for your work ! |
5e66e58
to
afba827
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just that we'll need to investigate why tests are failing.
c26649f
to
8ca577e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we can not remove the .collect()
call for the into_iter()
that easily. LGTM now, just that we need to fix the conflicts.
Related to shuttle-hq#890. This adds a custom wrapper type for secrets, which will be used to prevent them from leaking anywhere. To ensure that API Keys in the CLI never get leaked we wrap them in the new `Secret` type.
Description of change
This aims to close #890. I looked into secrecy and tried to integrate it into the code base and found some odd trait bound issues that wouldn't allow using them in structs that implement
Serialize
orDeserialize
. The crate provides aserde
feature that should enable exactly this, but this still would lead to weird issues of standard library types not implementing traits from thesecrecy
crate. This file seems to be the issue. They require the wrapped type to implementSerializableSecret
which they never implement for standard library types anywhere?Anyway, instead I decided to replicate the functionality of the crate myself by creating a wrapper type that makes sure to not expose the inner value unless by calling the
expose
function explicitly. The underlying data will also be zeroed out in memory when the type is dropped to ensure it won't leak afterwards.I have looked through the code base searching for places where this type could be useful and made some changes. If you know other places where secrets are being used that I missed, please let me know.