-
Notifications
You must be signed in to change notification settings - Fork 21
feat: bound incoming request and add postgres service #76
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
base: main
Are you sure you want to change the base?
feat: bound incoming request and add postgres service #76
Conversation
|
👋 Thanks for assigning @tankyleo as a reviewer! |
4bfb403 to
a163ae7
Compare
rust/server/src/vss_service.rs
Outdated
| use std::pin::Pin; | ||
| use std::sync::Arc; | ||
|
|
||
| const MAXIMUM_REQUEST_BODY_SIZE: u16 = 65_535; |
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.
This seems very conservative, given that monitors could get quite large. Given that the VSS service is actually a storage service, it also might make sense to make this configurable (in contrast to lightningdevkit/ldk-server#80, but even there we set the limit to 10MB).
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.
As mentioned elsewhere: I guess a static upper bound is a good first step, but if we're really concerned about DoS we might need some dynamic rate limiting on a per-IP basis. Although then the question becomes how much of that should be considered the concern of the VSS service itself, and how much we'd just expect users to slap a load balancer/Cloudflare in front of the service to handle that for them
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.
I've made the configuration changes suggested here, capping at 20 MB for the maximum size.
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.
No, as mentioned elsewhere, individual values might be quite a bit larger than 10 or 20MB. I think something along the lines of 100MB would be a more reasonable maximum, though per request it raises the question of how much a DoS protection this actually is.
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.
I've updated the max to 1GB per Matt's recommendation. We get basic protection with this but I could spent some time on this and propose a coherent strategy.
5d391cc to
fbdd957
Compare
|
🔔 1st Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 3rd Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 4th Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 5th Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 6th Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 7th Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 8th Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 9th Reminder Hey @tankyleo! This PR has been waiting for your review. |
tnull
left a comment
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.
Can we also add some test coverage to ensure the database / backends actually support the configured maximum values, i.e., that we're not otherwise limited somehow?
rust/server/src/vss_service.rs
Outdated
| use std::pin::Pin; | ||
| use std::sync::Arc; | ||
|
|
||
| const MAXIMUM_REQUEST_BODY_SIZE: u16 = 65_535; |
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.
No, as mentioned elsewhere, individual values might be quite a bit larger than 10 or 20MB. I think something along the lines of 100MB would be a more reasonable maximum, though per request it raises the question of how much a DoS protection this actually is.
|
🔔 10th Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 11th Reminder Hey @tankyleo! This PR has been waiting for your review. |
97b6b25 to
93faf38
Compare
|
Thanks for the review @tnull and @TheBlueMatt. I have updated the maximum request body size and added a test to check that our backend(s) support the configured value. It's ready for another look when you have the time. |
|
🔔 12th Reminder Hey @tankyleo! This PR has been waiting for your review. |
tnull
left a comment
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.
Generally looks good, mod some comments.
As noted above already, I do wonder how much we're gaining at all we we're limiting to 1GB per request. In any case, probably better than nothing. So generally concept ACK from my side, but I'll leave it to @tankyleo to decide.
|
I mean at least it avoids someone being able to OOM us by just sending us trash 🤷♂️ Of course VSS exposed directly would probably still be OOM'able with a few parallel requests, but hopefully a decent frontend proxy can limit the impact by buffering the requests first. |
15417ec to
7121dcc
Compare
|
🔔 13th Reminder Hey @tankyleo! This PR has been waiting for your review. |
tankyleo
left a comment
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.
Thank your for the PR sorry for the delay on my part, a few bits, looking good !
rust/server/src/vss_service.rs
Outdated
|
|
||
| impl VssServiceConfig { | ||
| pub fn new(maximum_request_body_size: usize) -> Self { | ||
| Self { maximum_request_body_size: maximum_request_body_size.min(MAXIMUM_REQUEST_BODY_SIZE) } |
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.
Instead of silently taking the min here, I would prefer we abort startup in case the user sets a value greater than 1 GiB to avoid surprises.
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.
Addressed this by adding a validation of this after loading configuration.
7121dcc to
f061dc1
Compare
f061dc1 to
8a49df9
Compare
|
Hi @tankyleo |
rust/server/src/util/config.rs
Outdated
| let maximum_request_body_size = read_config( | ||
| maximum_request_body_size_env, | ||
| max_request_body_size_config, | ||
| "VSS server maximum request body size", | ||
| MAX_REQUEST_BODY_SIZE, | ||
| )?; |
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.
Let's not make this parameter mandatory. In case it's not set, let's set it to None in the Configuration struct.
rust/server/src/vss_service.rs
Outdated
| pub struct VssService { | ||
| store: Arc<dyn KvStore>, | ||
| authorizer: Arc<dyn Authorizer>, | ||
| config: Arc<VssServiceConfig>, |
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.
I'd prefer we remove the Arc<> here, and do #[derive(Clone, Copy)] on VssServiceConfig
rust/server/src/main.rs
Outdated
| Ok(config) => Arc::new(config), | ||
| Err(e) => { | ||
| eprintln!("Configuration validation error: {}", e); | ||
| return; |
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.
One more thing, let's do an std::process:exit(-1) here like we do elsewhere
rust/server/vss-server-config.toml
Outdated
| @@ -1,5 +1,6 @@ | |||
| [server_config] | |||
| bind_address = "127.0.0.1:8080" # Optional in TOML, can be overridden by env var `VSS_BIND_ADDRESS` | |||
| maximum_request_body_size = 1073741824 # Optional in TOML: maximum request body size in bytes capped at 1 GB, can be overriden by env var 'VSS_MAX_REQUEST_BODY_SIZE' | |||
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.
Let's keep this commented out to highlight to people that this parameter is optional; we'll default to 1GiB in case it is not set anywhere.
564f34a to
5d0d841
Compare
tankyleo
left a comment
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.
Thanks a few more nits below, feel free to squash the fixups
rust/server/src/util/config.rs
Outdated
| "VSS server maximum request body size", | ||
| MAX_REQUEST_BODY_SIZE, | ||
| ) | ||
| .ok(); |
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.
here let's do a maximum_request_body_size_env.or(max_request_body_size_config); we shouldn't pass parameters for a function to create an error that we later ignore :)
rust/server/src/util/config.rs
Outdated
| use std::net::SocketAddr; | ||
|
|
||
| const BIND_ADDR_VAR: &str = "VSS_BIND_ADDRESS"; | ||
| const MAX_REQUEST_BODY_SIZE: &str = "VSS_MAX_REQUEST_BODY_SIZE"; |
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.
Let's keep things consistent here, how about MAX_REQUEST_BODY_SIZE_VAR ? feel free to pick a shorter name
rust/server/src/util/config.rs
Outdated
| // Encapsulates the result of reading both the environment variables and the config file. | ||
| pub(crate) struct Configuration { | ||
| pub(crate) bind_address: SocketAddr, | ||
| pub(crate) maximum_request_body_size: Option<usize>, |
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: would you mind using max_request_body_size here and in ServerConfig ? would like to shorten the name if we can since it's user facing :)
rust/server/src/main.rs
Outdated
| Ok((stream, _)) => { | ||
| let io_stream = TokioIo::new(stream); | ||
| let vss_service = VssService::new(Arc::clone(&store), Arc::clone(&authorizer)); | ||
| let vss_service = VssService::new(Arc::clone(&store), Arc::clone(&authorizer), vss_service_config.clone()); |
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.
Let's add the Copy trait on VssServiceConfig so that we don't have to call clone here; VsServiceConfig is just a single usize at the moment, so it can be cheaply copied.
rust/server/vss-server-config.toml
Outdated
| # Maximum request body size in bytes. Can be set here or be overridden by env var 'VSS_MAX_REQUEST_BODY_SIZE' | ||
| # Defaults to 1 GB if unset. | ||
| # maximum_request_body_size = 1073741824 |
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.
Here let people know the max value they can set here is 1GiB
rust/server/vss-server-config.toml
Outdated
| bind_address = "127.0.0.1:8080" # Optional in TOML, can be overridden by env var `VSS_BIND_ADDRESS` | ||
| # Maximum request body size in bytes. Can be set here or be overridden by env var 'VSS_MAX_REQUEST_BODY_SIZE' | ||
| # Defaults to 1 GB if unset. | ||
| # maximum_request_body_size = 1073741824 |
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 one more thing, please delete the trailing whitespace on this line thanks
Add VssServiceConfig to make the maximum request body size configurable through the server configuration file, with a hard limit of 1GB. Additionally, add test coverage for 1GB maximum supported value size and verifies that storage backends can handle the configured maximum value size.
5d0d841 to
04a9213
Compare
|
Hi @tankyleo, |
tankyleo
left a comment
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 two nits, good to consolidate everything into two commits, one for the docker file, and one for the max_request_body_size feature.
As with the other PR, please remove the prefixes, and capitalize the first word of the commit message.
| } | ||
|
|
||
| #[cfg(test)] | ||
|
|
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.
Should have caught this, we don't need an additional line here
|
|
||
| # Maximum request body size in bytes. Can be set here or be overridden by env var 'VSS_MAX_REQUEST_BODY_SIZE' | ||
| # Defaults to the maximum possible value of 1 GB if unset. | ||
| # max_request_body_size = 1073741824 |
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.
hmm sounds like the trailing whitespace is still there ? feel free to use something like git diff --check to check
What this PR does
TODOmaximum_request_body_sizein [server_config] or via environment variable