itsi-server 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +950 -239
- data/README.md +2 -0
- data/exe/itsi +5 -5
- data/ext/itsi_acme/Cargo.toml +86 -0
- data/ext/itsi_acme/examples/high_level.rs +63 -0
- data/ext/itsi_acme/examples/high_level_warp.rs +52 -0
- data/ext/itsi_acme/examples/low_level.rs +87 -0
- data/ext/itsi_acme/examples/low_level_axum.rs +66 -0
- data/ext/itsi_acme/src/acceptor.rs +81 -0
- data/ext/itsi_acme/src/acme.rs +354 -0
- data/ext/itsi_acme/src/axum.rs +86 -0
- data/ext/itsi_acme/src/cache.rs +39 -0
- data/ext/itsi_acme/src/caches/boxed.rs +80 -0
- data/ext/itsi_acme/src/caches/composite.rs +69 -0
- data/ext/itsi_acme/src/caches/dir.rs +106 -0
- data/ext/itsi_acme/src/caches/mod.rs +11 -0
- data/ext/itsi_acme/src/caches/no.rs +78 -0
- data/ext/itsi_acme/src/caches/test.rs +136 -0
- data/ext/itsi_acme/src/config.rs +172 -0
- data/ext/itsi_acme/src/https_helper.rs +69 -0
- data/ext/itsi_acme/src/incoming.rs +142 -0
- data/ext/itsi_acme/src/jose.rs +161 -0
- data/ext/itsi_acme/src/lib.rs +142 -0
- data/ext/itsi_acme/src/resolver.rs +59 -0
- data/ext/itsi_acme/src/state.rs +424 -0
- data/ext/itsi_server/Cargo.toml +3 -3
- data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +2 -2
- data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +150 -19
- data/ext/itsi_server/src/ruby_types/itsi_server.rs +1 -0
- data/ext/itsi_server/src/server/binds/listener.rs +34 -29
- data/ext/itsi_server/src/server/binds/tls/locked_dir_cache.rs +2 -2
- data/ext/itsi_server/src/server/binds/tls.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middleware.rs +33 -28
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +56 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +179 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +25 -2
- data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +3 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +2 -1
- data/ext/itsi_server/src/server/middleware_stack/mod.rs +32 -34
- data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +10 -4
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +30 -7
- data/ext/itsi_server/src/server/thread_worker.rs +2 -2
- data/ext/itsi_server/src/services/static_file_server.rs +30 -28
- data/ext/itsi_tracing/src/lib.rs +39 -8
- data/lib/itsi/server/config/config_helpers.rb +93 -0
- data/lib/itsi/server/config/dsl.rb +81 -33
- data/lib/itsi/server/config/known_paths/KitchensinkDirectories.txt +2346 -0
- data/lib/itsi/server/config/known_paths/Randomfiles.txt +24 -0
- data/lib/itsi/server/config/known_paths/UnixDotfiles.txt +52 -0
- data/lib/itsi/server/config/known_paths/backdoors/ASP_CommonBackdoors.txt +29 -0
- data/lib/itsi/server/config/known_paths/backdoors/bot_control_panels.txt +1668 -0
- data/lib/itsi/server/config/known_paths/backdoors/shells.txt +1167 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST.txt +7 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST_Windows.txt +6 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_Microsoft.txt +79 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_XPlatform.txt +3948 -0
- data/lib/itsi/server/config/known_paths/cms/README.md +5 -0
- data/lib/itsi/server/config/known_paths/cms/drupal_plugins.txt +6320 -0
- data/lib/itsi/server/config/known_paths/cms/drupal_themes.txt +828 -0
- data/lib/itsi/server/config/known_paths/cms/joomla_plugins.txt +224 -0
- data/lib/itsi/server/config/known_paths/cms/joomla_themes.txt +30 -0
- data/lib/itsi/server/config/known_paths/cms/php-nuke.txt +2142 -0
- data/lib/itsi/server/config/known_paths/cms/wordpress.txt +1566 -0
- data/lib/itsi/server/config/known_paths/cms/wp_common_theme_files.txt +46 -0
- data/lib/itsi/server/config/known_paths/cms/wp_plugins.txt +13366 -0
- data/lib/itsi/server/config/known_paths/cms/wp_plugins_full.txt +68662 -0
- data/lib/itsi/server/config/known_paths/cms/wp_plugins_top225.txt +225 -0
- data/lib/itsi/server/config/known_paths/cms/wp_themes.readme +12 -0
- data/lib/itsi/server/config/known_paths/cms/wp_themes.txt +7336 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/3CharExtBrute.txt +17576 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/CommonWebExtensions.txt +80 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Backup.txt +14 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Common.txt +865 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Compressed.txt +186 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Mostcommon.txt +30 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Skipfish.txt +93 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/WordlistSkipfish.txt +1918 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/copy_of.txt +8 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories-lowercase.txt +56180 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories.txt +62290 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions-lowercase.txt +2367 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions.txt +2450 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files-lowercase.txt +35323 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files.txt +37037 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words-lowercase.txt +107982 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words.txt +119600 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories-lowercase.txt +26593 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories.txt +30009 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions-lowercase.txt +1233 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions.txt +1289 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files-lowercase.txt +16243 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files.txt +17128 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words-lowercase.txt +56293 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words.txt +63087 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories-lowercase.txt +17776 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories.txt +20122 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions-lowercase.txt +914 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions.txt +963 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files-lowercase.txt +10848 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files.txt +11424 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words-lowercase.txt +38267 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words.txt +43003 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/spanish.txt +445 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/test_demo.txt +36 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/upload_variants.txt +44 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/Logins.txt +71 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/cfm.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/html.txt +295 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/jsp.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/php.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/windows-asp.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/windows-aspx.txt +294 -0
- data/lib/itsi/server/config/known_paths/password-file-locations/Passwords.txt +47 -0
- data/lib/itsi/server/config/known_paths/php/PHP.txt +30 -0
- data/lib/itsi/server/config/known_paths/php/PHP_CommonBackdoors.txt +5 -0
- data/lib/itsi/server/config/known_paths/proxy-conf.txt +31 -0
- data/lib/itsi/server/config/known_paths/tftp.txt +79 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/ADFS.txt +86 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/AdobeXML.txt +16 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Apache.txt +101 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/ApacheTomcat.txt +47 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Apache_Axis.txt +16 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/ColdFusion.txt +111 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/FatwireCMS.txt +390 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Frontpage.txt +38 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/HP_System_Mgmt_Homepage.txt +239 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/HTTP_POST_Microsoft.txt +2 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Hyperion.txt +578 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/IIS.txt +187 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/JBoss.txt +5 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/JRun.txt +13 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/JavaServlets_Common.txt +3 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Joomla_exploitable.txt +1937 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/LotusNotes.txt +206 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Netware.txt +18 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Oracle9i.txt +60 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/OracleAppServer.txt +192 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/README.md +6 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Ruby_Rails.txt +121 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SAP.txt +463 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Sharepoint.txt +1707 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SiteMinder.txt +19 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SunAppServerGlassfish.txt +51 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SuniPlanet.txt +35 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Vignette.txt +73 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Weblogic.txt +160 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Websphere.txt +366 -0
- data/lib/itsi/server/config/known_paths/wellknown-rfc5785.txt +30 -0
- data/lib/itsi/server/config/known_paths.rb +17 -0
- data/lib/itsi/server/config/middleware/_index.md +54 -0
- data/lib/itsi/server/config/middleware/log_requests.md +63 -0
- data/lib/itsi/server/config/middleware/log_requests.rb +33 -0
- data/lib/itsi/server/config/middleware.rb +9 -0
- data/lib/itsi/server/config/option.rb +9 -0
- data/lib/itsi/server/config/options/_index.md +36 -0
- data/lib/itsi/server/config/options/fiber_scheduler.md +35 -0
- data/lib/itsi/server/config/options/fiber_scheduler.rb +18 -0
- data/lib/itsi/server/config/options/threads.md +39 -0
- data/lib/itsi/server/config/options/threads.rb +17 -0
- data/lib/itsi/server/config/options/workers.md +43 -0
- data/lib/itsi/server/config/options/workers.rb +17 -0
- data/lib/itsi/server/config/typed_struct.rb +203 -0
- data/lib/itsi/server/config.rb +124 -30
- data/lib/itsi/server/signal_trap.rb +5 -1
- data/lib/itsi/server/typed_handlers/source_parser.rb +1 -1
- data/lib/itsi/server/version.rb +1 -1
- data/lib/itsi/server.rb +27 -6
- data/lib/ruby_lsp/itsi/addon.rb +64 -48
- metadata +141 -5
- data/CHANGELOG.md +0 -10
- data/CODE_OF_CONDUCT.md +0 -139
- data/LICENSE.txt +0 -21
- data/_index.md +0 -6
@@ -7,8 +7,9 @@ use crate::{
|
|
7
7
|
},
|
8
8
|
};
|
9
9
|
use derive_more::Debug;
|
10
|
+
use futures::executor::block_on;
|
10
11
|
use itsi_rb_helpers::{call_with_gvl, print_rb_backtrace, HeapValue};
|
11
|
-
use itsi_tracing::{set_format, set_level, set_target};
|
12
|
+
use itsi_tracing::{set_format, set_level, set_target, set_target_filters};
|
12
13
|
use magnus::{
|
13
14
|
block::Proc,
|
14
15
|
error::Result,
|
@@ -27,6 +28,7 @@ use std::{
|
|
27
28
|
sync::{Arc, OnceLock},
|
28
29
|
time::Duration,
|
29
30
|
};
|
31
|
+
use tracing::{debug, error};
|
30
32
|
static DEFAULT_BIND: &str = "http://localhost:3000";
|
31
33
|
static ID_BUILD_CONFIG: LazyId = LazyId::new("build_config");
|
32
34
|
static ID_RELOAD_EXEC: LazyId = LazyId::new("reload_exec");
|
@@ -52,7 +54,9 @@ pub struct ServerParams {
|
|
52
54
|
pub preload: bool,
|
53
55
|
|
54
56
|
pub request_timeout: Option<Duration>,
|
57
|
+
pub header_read_timeout: Duration,
|
55
58
|
pub notify_watchers: Option<Vec<(String, Vec<Vec<String>>)>>,
|
59
|
+
|
56
60
|
/// Worker params
|
57
61
|
pub threads: u8,
|
58
62
|
pub scheduler_threads: Option<u8>,
|
@@ -69,26 +73,39 @@ pub struct ServerParams {
|
|
69
73
|
listener_info: Mutex<HashMap<String, i32>>,
|
70
74
|
}
|
71
75
|
|
76
|
+
pub struct SocketOpts {
|
77
|
+
pub reuse_address: bool,
|
78
|
+
pub reuse_port: bool,
|
79
|
+
pub listen_backlog: usize,
|
80
|
+
pub nodelay: bool,
|
81
|
+
pub recv_buffer_size: usize,
|
82
|
+
}
|
83
|
+
|
72
84
|
impl ServerParams {
|
73
85
|
pub fn preload_ruby(self: &Arc<Self>) -> Result<()> {
|
74
86
|
call_with_gvl(|ruby| -> Result<()> {
|
87
|
+
debug!("Preloading Ruby");
|
75
88
|
if self
|
76
89
|
.scheduler_class
|
77
90
|
.as_ref()
|
78
91
|
.is_some_and(|t| t == "Itsi::Scheduler")
|
79
92
|
{
|
93
|
+
debug!("Loading Itsi Scheduler");
|
80
94
|
ruby.require("itsi/scheduler")?;
|
81
95
|
}
|
82
|
-
let
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
}
|
90
|
-
|
91
|
-
|
96
|
+
let routes_raw = self
|
97
|
+
.middleware_loader
|
98
|
+
.call::<_, Option<Value>>(())
|
99
|
+
.inspect_err(|e| {
|
100
|
+
eprintln!("Error loading middleware: {:?}", e);
|
101
|
+
if let Some(err_value) = e.value() {
|
102
|
+
print_rb_backtrace(err_value);
|
103
|
+
}
|
104
|
+
})?
|
105
|
+
.map(|mw| mw.into());
|
106
|
+
debug!("Middleware routes returned");
|
107
|
+
let middleware = MiddlewareSet::new(routes_raw)?;
|
108
|
+
debug!("Middleware loaded");
|
92
109
|
self.middleware.set(middleware).map_err(|_| {
|
93
110
|
magnus::Error::new(
|
94
111
|
magnus::exception::runtime_error(),
|
@@ -100,6 +117,11 @@ impl ServerParams {
|
|
100
117
|
Ok(())
|
101
118
|
}
|
102
119
|
|
120
|
+
pub async fn initialize_middleware(self: &Arc<Self>) -> Result<()> {
|
121
|
+
self.middleware.get().unwrap().initialize_layers().await?;
|
122
|
+
Ok(())
|
123
|
+
}
|
124
|
+
|
103
125
|
fn from_rb_hash(rb_param_hash: RHash) -> Result<ServerParams> {
|
104
126
|
let workers = rb_param_hash
|
105
127
|
.fetch::<_, Option<u8>>("workers")?
|
@@ -134,6 +156,10 @@ impl ServerParams {
|
|
134
156
|
let preload: bool = rb_param_hash.fetch("preload")?;
|
135
157
|
let request_timeout: Option<u64> = rb_param_hash.fetch("request_timeout")?;
|
136
158
|
let request_timeout = request_timeout.map(Duration::from_secs);
|
159
|
+
let header_read_timeout: Duration = rb_param_hash
|
160
|
+
.fetch::<_, Option<u64>>("header_read_timeout")?
|
161
|
+
.map(Duration::from_secs)
|
162
|
+
.unwrap_or(Duration::from_secs(1));
|
137
163
|
|
138
164
|
let notify_watchers: Option<Vec<(String, Vec<Vec<String>>)>> =
|
139
165
|
rb_param_hash.fetch("notify_watchers")?;
|
@@ -147,6 +173,23 @@ impl ServerParams {
|
|
147
173
|
let log_level: Option<String> = rb_param_hash.fetch("log_level")?;
|
148
174
|
let log_target: Option<String> = rb_param_hash.fetch("log_target")?;
|
149
175
|
let log_format: Option<String> = rb_param_hash.fetch("log_format")?;
|
176
|
+
let log_target_filters: Option<Vec<String>> = rb_param_hash.fetch("log_target_filters")?;
|
177
|
+
|
178
|
+
let reuse_address: bool = rb_param_hash
|
179
|
+
.fetch::<_, Option<bool>>("reuse_address")?
|
180
|
+
.unwrap_or(true);
|
181
|
+
let reuse_port: bool = rb_param_hash
|
182
|
+
.fetch::<_, Option<bool>>("reuse_port")?
|
183
|
+
.unwrap_or(true);
|
184
|
+
let listen_backlog: usize = rb_param_hash
|
185
|
+
.fetch::<_, Option<usize>>("listen_backlog")?
|
186
|
+
.unwrap_or(1024);
|
187
|
+
let nodelay: bool = rb_param_hash
|
188
|
+
.fetch::<_, Option<bool>>("nodelay")?
|
189
|
+
.unwrap_or(true);
|
190
|
+
let recv_buffer_size: usize = rb_param_hash
|
191
|
+
.fetch::<_, Option<usize>>("recv_buffer_size")?
|
192
|
+
.unwrap_or(262_144);
|
150
193
|
|
151
194
|
if let Some(level) = log_level {
|
152
195
|
set_level(&level);
|
@@ -160,6 +203,22 @@ impl ServerParams {
|
|
160
203
|
set_format(&format);
|
161
204
|
}
|
162
205
|
|
206
|
+
if let Some(target_filters) = log_target_filters {
|
207
|
+
let target_filters = target_filters
|
208
|
+
.iter()
|
209
|
+
.filter_map(|filter| {
|
210
|
+
let mut parts = filter.splitn(2, '=');
|
211
|
+
if let (Some(target), Some(level_str)) = (parts.next(), parts.next()) {
|
212
|
+
if let Ok(level) = level_str.parse::<tracing::Level>() {
|
213
|
+
return Some((target, level));
|
214
|
+
}
|
215
|
+
}
|
216
|
+
None
|
217
|
+
})
|
218
|
+
.collect::<Vec<(&str, tracing::Level)>>();
|
219
|
+
set_target_filters(target_filters);
|
220
|
+
}
|
221
|
+
|
163
222
|
let binds: Option<Vec<String>> = rb_param_hash.fetch("binds")?;
|
164
223
|
let binds = binds
|
165
224
|
.unwrap_or_else(|| vec![DEFAULT_BIND.to_string()])
|
@@ -167,6 +226,13 @@ impl ServerParams {
|
|
167
226
|
.map(|s| s.parse())
|
168
227
|
.collect::<itsi_error::Result<Vec<Bind>>>()?;
|
169
228
|
|
229
|
+
let socket_opts = SocketOpts {
|
230
|
+
reuse_address,
|
231
|
+
reuse_port,
|
232
|
+
listen_backlog,
|
233
|
+
nodelay,
|
234
|
+
recv_buffer_size,
|
235
|
+
};
|
170
236
|
let listeners = if let Some(preexisting_listeners) =
|
171
237
|
rb_param_hash.delete::<_, Option<String>>("listeners")?
|
172
238
|
{
|
@@ -183,9 +249,9 @@ impl ServerParams {
|
|
183
249
|
.cloned()
|
184
250
|
.map(|bind| {
|
185
251
|
if let Some(fd) = bind_to_fd_map.get(&bind.listener_address_string()) {
|
186
|
-
Listener::inherit_fd(bind, *fd)
|
252
|
+
Listener::inherit_fd(bind, *fd, &socket_opts)
|
187
253
|
} else {
|
188
|
-
Listener::
|
254
|
+
Listener::build(bind, &socket_opts)
|
189
255
|
}
|
190
256
|
})
|
191
257
|
.collect::<std::result::Result<Vec<Listener>, _>>()?
|
@@ -195,7 +261,7 @@ impl ServerParams {
|
|
195
261
|
binds
|
196
262
|
.iter()
|
197
263
|
.cloned()
|
198
|
-
.map(Listener::
|
264
|
+
.map(|b| Listener::build(b, &socket_opts))
|
199
265
|
.collect::<std::result::Result<Vec<Listener>, _>>()?
|
200
266
|
.into_iter()
|
201
267
|
.collect::<Vec<_>>()
|
@@ -220,6 +286,7 @@ impl ServerParams {
|
|
220
286
|
hooks,
|
221
287
|
preload,
|
222
288
|
request_timeout,
|
289
|
+
header_read_timeout,
|
223
290
|
notify_watchers,
|
224
291
|
threads,
|
225
292
|
scheduler_threads,
|
@@ -249,6 +316,7 @@ impl ItsiServerConfig {
|
|
249
316
|
itsifile_path.as_ref(),
|
250
317
|
itsi_config_proc.clone(),
|
251
318
|
)?;
|
319
|
+
|
252
320
|
cli_params.delete::<_, Value>(Symbol::new("listeners"))?;
|
253
321
|
|
254
322
|
let watcher_fd = if let Some(watchers) = server_params.notify_watchers.clone() {
|
@@ -276,7 +344,6 @@ impl ItsiServerConfig {
|
|
276
344
|
self.itsi_config_proc.clone(),
|
277
345
|
)
|
278
346
|
})?;
|
279
|
-
|
280
347
|
let is_single_mode = self.server_params.read().workers == 1;
|
281
348
|
|
282
349
|
let requires_exec = if !is_single_mode && !server_params.preload {
|
@@ -305,10 +372,18 @@ impl ItsiServerConfig {
|
|
305
372
|
.as_ref()
|
306
373
|
.clone()
|
307
374
|
.map(|hv| hv.clone().inner());
|
308
|
-
let rb_param_hash: RHash =
|
309
|
-
|
310
|
-
|
311
|
-
|
375
|
+
let (rb_param_hash, errors): (RHash, Vec<String>) =
|
376
|
+
ruby.get_inner_ref(&ITSI_SERVER_CONFIG).funcall(
|
377
|
+
*ID_BUILD_CONFIG,
|
378
|
+
(cli_params, itsifile_path.cloned(), inner),
|
379
|
+
)?;
|
380
|
+
if !errors.is_empty() {
|
381
|
+
Self::print_config_errors(errors);
|
382
|
+
return Err(magnus::Error::new(
|
383
|
+
magnus::exception::standard_error(),
|
384
|
+
"Invalid server config",
|
385
|
+
));
|
386
|
+
}
|
312
387
|
Ok(Arc::new(ServerParams::from_rb_hash(rb_param_hash)?))
|
313
388
|
}
|
314
389
|
|
@@ -322,6 +397,47 @@ impl ItsiServerConfig {
|
|
322
397
|
Ok(())
|
323
398
|
}
|
324
399
|
|
400
|
+
pub fn get_config_errors(&self) -> Option<Vec<String>> {
|
401
|
+
let rb_param_hash = call_with_gvl(|ruby| {
|
402
|
+
let inner = self
|
403
|
+
.itsi_config_proc
|
404
|
+
.as_ref()
|
405
|
+
.clone()
|
406
|
+
.map(|hv| hv.clone().inner());
|
407
|
+
let cli_params = self.cli_params.cloned();
|
408
|
+
let itsifile_path = self.itsifile_path.clone();
|
409
|
+
|
410
|
+
let (rb_param_hash, errors): (RHash, Vec<String>) = ruby
|
411
|
+
.get_inner_ref(&ITSI_SERVER_CONFIG)
|
412
|
+
.funcall(*ID_BUILD_CONFIG, (cli_params, itsifile_path, inner))
|
413
|
+
.unwrap();
|
414
|
+
if !errors.is_empty() {
|
415
|
+
return Err(errors);
|
416
|
+
}
|
417
|
+
Ok(rb_param_hash)
|
418
|
+
});
|
419
|
+
match rb_param_hash {
|
420
|
+
Ok(rb_param_hash) => match ServerParams::from_rb_hash(rb_param_hash) {
|
421
|
+
Ok(test_params) => {
|
422
|
+
let params_arc = Arc::new(test_params);
|
423
|
+
if let Err(err) = params_arc.clone().preload_ruby() {
|
424
|
+
let err_val = call_with_gvl(|_| format!("{}", err));
|
425
|
+
return Some(vec![err_val]);
|
426
|
+
}
|
427
|
+
if let Err(err) =
|
428
|
+
block_on(params_arc.middleware.get().unwrap().initialize_layers())
|
429
|
+
{
|
430
|
+
let err_val = call_with_gvl(|_| format!("{}", err));
|
431
|
+
return Some(vec![err_val]);
|
432
|
+
}
|
433
|
+
None
|
434
|
+
}
|
435
|
+
Err(err) => Some(vec![format!("{:?}", err)]),
|
436
|
+
},
|
437
|
+
Err(err) => Some(err),
|
438
|
+
}
|
439
|
+
}
|
440
|
+
|
325
441
|
pub fn dup_fds(self: &Arc<Self>) -> Result<()> {
|
326
442
|
let binding = self.server_params.read();
|
327
443
|
let mut listener_info_guard = binding.listener_info.lock();
|
@@ -354,6 +470,21 @@ impl ItsiServerConfig {
|
|
354
470
|
Ok(())
|
355
471
|
}
|
356
472
|
|
473
|
+
pub fn print_config_errors(errors: Vec<String>) {
|
474
|
+
error!("Refusing to reload configuration due to fatal errors:");
|
475
|
+
for error in errors {
|
476
|
+
eprintln!("{}", error);
|
477
|
+
}
|
478
|
+
}
|
479
|
+
|
480
|
+
pub fn check_config(&self) -> bool {
|
481
|
+
if let Some(errors) = self.get_config_errors() {
|
482
|
+
Self::print_config_errors(errors);
|
483
|
+
return false;
|
484
|
+
}
|
485
|
+
true
|
486
|
+
}
|
487
|
+
|
357
488
|
pub fn reload_exec(self: &Arc<Self>) -> Result<()> {
|
358
489
|
let listener_json =
|
359
490
|
serde_json::to_string(&self.server_params.read().listener_info.lock().clone())
|
@@ -1,4 +1,5 @@
|
|
1
1
|
use crate::prelude::*;
|
2
|
+
use crate::ruby_types::itsi_server::itsi_server_config::SocketOpts;
|
2
3
|
use crate::server::io_stream::IoStream;
|
3
4
|
use crate::server::serve_strategy::single_mode::RunningPhase;
|
4
5
|
|
@@ -326,12 +327,12 @@ impl Listener {
|
|
326
327
|
}
|
327
328
|
}
|
328
329
|
|
329
|
-
pub fn inherit_fd(bind: Bind, fd: RawFd) -> Result<Self> {
|
330
|
+
pub fn inherit_fd(bind: Bind, fd: RawFd, socket_opts: &SocketOpts) -> Result<Self> {
|
330
331
|
let bound = match bind.address {
|
331
332
|
BindAddress::Ip(_) => match bind.protocol {
|
332
|
-
BindProtocol::Http => Listener::Tcp(revive_tcp_socket(fd)?),
|
333
|
+
BindProtocol::Http => Listener::Tcp(revive_tcp_socket(fd, socket_opts)?),
|
333
334
|
BindProtocol::Https => {
|
334
|
-
let tcp_listener = revive_tcp_socket(fd)?;
|
335
|
+
let tcp_listener = revive_tcp_socket(fd, socket_opts)?;
|
335
336
|
Listener::TcpTls((
|
336
337
|
tcp_listener,
|
337
338
|
bind.tls_config.unwrap().build_acceptor().unwrap(),
|
@@ -341,25 +342,25 @@ impl Listener {
|
|
341
342
|
},
|
342
343
|
BindAddress::UnixSocket(_) => match bind.tls_config {
|
343
344
|
Some(tls_config) => Listener::UnixTls((
|
344
|
-
revive_unix_socket(fd)?,
|
345
|
+
revive_unix_socket(fd, socket_opts)?,
|
345
346
|
tls_config.build_acceptor().unwrap(),
|
346
347
|
)),
|
347
|
-
None => Listener::Unix(revive_unix_socket(fd)?),
|
348
|
+
None => Listener::Unix(revive_unix_socket(fd, socket_opts)?),
|
348
349
|
},
|
349
350
|
};
|
350
351
|
Ok(bound)
|
351
352
|
}
|
352
353
|
}
|
353
354
|
|
354
|
-
impl
|
355
|
-
|
356
|
-
|
357
|
-
fn try_from(bind: Bind) -> std::result::Result<Self, Self::Error> {
|
355
|
+
impl Listener {
|
356
|
+
pub fn build(bind: Bind, socket_opts: &SocketOpts) -> Result<Self> {
|
358
357
|
let bound = match bind.address {
|
359
358
|
BindAddress::Ip(addr) => match bind.protocol {
|
360
|
-
BindProtocol::Http =>
|
359
|
+
BindProtocol::Http => {
|
360
|
+
Listener::Tcp(connect_tcp_socket(addr, bind.port.unwrap(), socket_opts)?)
|
361
|
+
}
|
361
362
|
BindProtocol::Https => {
|
362
|
-
let tcp_listener = connect_tcp_socket(addr, bind.port.unwrap())?;
|
363
|
+
let tcp_listener = connect_tcp_socket(addr, bind.port.unwrap(), socket_opts)?;
|
363
364
|
Listener::TcpTls((
|
364
365
|
tcp_listener,
|
365
366
|
bind.tls_config.unwrap().build_acceptor().unwrap(),
|
@@ -369,56 +370,60 @@ impl TryFrom<Bind> for Listener {
|
|
369
370
|
},
|
370
371
|
BindAddress::UnixSocket(path) => match bind.tls_config {
|
371
372
|
Some(tls_config) => Listener::UnixTls((
|
372
|
-
connect_unix_socket(&path)?,
|
373
|
+
connect_unix_socket(&path, socket_opts)?,
|
373
374
|
tls_config.build_acceptor().unwrap(),
|
374
375
|
)),
|
375
|
-
None => Listener::Unix(connect_unix_socket(&path)?),
|
376
|
+
None => Listener::Unix(connect_unix_socket(&path, socket_opts)?),
|
376
377
|
},
|
377
378
|
};
|
378
379
|
Ok(bound)
|
379
380
|
}
|
380
381
|
}
|
381
382
|
|
382
|
-
fn revive_tcp_socket(fd: RawFd) -> Result<TcpListener> {
|
383
|
+
fn revive_tcp_socket(fd: RawFd, socket_opts: &SocketOpts) -> Result<TcpListener> {
|
383
384
|
let socket = unsafe { Socket::from_raw_fd(fd) };
|
384
|
-
socket.set_reuse_port(
|
385
|
-
socket.set_reuse_address(
|
385
|
+
socket.set_reuse_port(socket_opts.reuse_port).ok();
|
386
|
+
socket.set_reuse_address(socket_opts.reuse_address).ok();
|
386
387
|
socket.set_nonblocking(true).ok();
|
387
|
-
socket.set_nodelay(
|
388
|
-
socket
|
388
|
+
socket.set_nodelay(socket_opts.nodelay).ok();
|
389
|
+
socket
|
390
|
+
.set_recv_buffer_size(socket_opts.recv_buffer_size)
|
391
|
+
.ok();
|
389
392
|
socket.set_cloexec(true)?;
|
390
|
-
socket.listen(
|
393
|
+
socket.listen(socket_opts.listen_backlog as i32)?;
|
391
394
|
Ok(socket.into())
|
392
395
|
}
|
393
396
|
|
394
|
-
fn revive_unix_socket(fd: RawFd) -> Result<UnixListener> {
|
397
|
+
fn revive_unix_socket(fd: RawFd, socket_opts: &SocketOpts) -> Result<UnixListener> {
|
395
398
|
let socket = unsafe { Socket::from_raw_fd(fd) };
|
396
399
|
socket.set_nonblocking(true).ok();
|
397
|
-
socket.listen(
|
400
|
+
socket.listen(socket_opts.listen_backlog as i32)?;
|
398
401
|
socket.set_cloexec(true)?;
|
399
402
|
|
400
403
|
Ok(socket.into())
|
401
404
|
}
|
402
405
|
|
403
|
-
fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
|
406
|
+
fn connect_tcp_socket(addr: IpAddr, port: u16, socket_opts: &SocketOpts) -> Result<TcpListener> {
|
404
407
|
let domain = match addr {
|
405
408
|
IpAddr::V4(_) => Domain::IPV4,
|
406
409
|
IpAddr::V6(_) => Domain::IPV6,
|
407
410
|
};
|
408
411
|
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
|
409
412
|
let socket_address: SocketAddr = SocketAddr::new(addr, port);
|
410
|
-
socket.set_reuse_address(
|
411
|
-
socket.set_reuse_port(
|
413
|
+
socket.set_reuse_address(socket_opts.reuse_address).ok();
|
414
|
+
socket.set_reuse_port(socket_opts.reuse_port).ok();
|
412
415
|
socket.set_nonblocking(true).ok();
|
413
|
-
socket.set_nodelay(
|
414
|
-
socket
|
416
|
+
socket.set_nodelay(socket_opts.nodelay).ok();
|
417
|
+
socket
|
418
|
+
.set_recv_buffer_size(socket_opts.recv_buffer_size)
|
419
|
+
.ok();
|
415
420
|
socket.set_only_v6(false).ok();
|
416
421
|
socket.bind(&socket_address.into())?;
|
417
|
-
socket.listen(
|
422
|
+
socket.listen(socket_opts.listen_backlog as i32)?;
|
418
423
|
Ok(socket.into())
|
419
424
|
}
|
420
425
|
|
421
|
-
fn connect_unix_socket(path: &PathBuf) -> Result<UnixListener> {
|
426
|
+
fn connect_unix_socket(path: &PathBuf, socket_opts: &SocketOpts) -> Result<UnixListener> {
|
422
427
|
let _ = std::fs::remove_file(path);
|
423
428
|
let socket = Socket::new(Domain::UNIX, Type::STREAM, None)?;
|
424
429
|
socket.set_nonblocking(true).ok();
|
@@ -426,7 +431,7 @@ fn connect_unix_socket(path: &PathBuf) -> Result<UnixListener> {
|
|
426
431
|
let socket_address = socket2::SockAddr::unix(path)?;
|
427
432
|
|
428
433
|
socket.bind(&socket_address)?;
|
429
|
-
socket.listen(
|
434
|
+
socket.listen(socket_opts.listen_backlog as i32)?;
|
430
435
|
|
431
436
|
Ok(socket.into())
|
432
437
|
}
|
@@ -1,11 +1,11 @@
|
|
1
1
|
use async_trait::async_trait;
|
2
2
|
use fs2::FileExt;
|
3
|
+
use itsi_acme::caches::DirCache;
|
4
|
+
use itsi_acme::{AccountCache, CertCache};
|
3
5
|
use parking_lot::Mutex;
|
4
6
|
use std::fs::{self, OpenOptions};
|
5
7
|
use std::io::Error as IoError;
|
6
8
|
use std::path::{Path, PathBuf};
|
7
|
-
use tokio_rustls_acme::caches::DirCache;
|
8
|
-
use tokio_rustls_acme::{AccountCache, CertCache};
|
9
9
|
|
10
10
|
use crate::env::ITSI_ACME_LOCK_FILE_NAME;
|
11
11
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
use base64::{engine::general_purpose, Engine as _};
|
2
|
+
use itsi_acme::{AcmeAcceptor, AcmeConfig, AcmeState};
|
2
3
|
use itsi_error::Result;
|
3
4
|
use itsi_tracing::info;
|
4
5
|
use locked_dir_cache::LockedDirCache;
|
@@ -18,7 +19,6 @@ use std::{
|
|
18
19
|
};
|
19
20
|
use tokio::sync::Mutex;
|
20
21
|
use tokio_rustls::{rustls::ServerConfig, TlsAcceptor};
|
21
|
-
use tokio_rustls_acme::{AcmeAcceptor, AcmeConfig, AcmeState};
|
22
22
|
|
23
23
|
use crate::env::{
|
24
24
|
ITSI_ACME_CACHE_DIR, ITSI_ACME_CA_PEM_PATH, ITSI_ACME_CONTACT_EMAIL, ITSI_ACME_DIRECTORY_URL,
|
@@ -8,30 +8,31 @@ use super::middlewares::*;
|
|
8
8
|
use async_trait::async_trait;
|
9
9
|
use either::Either;
|
10
10
|
use magnus::error::Result;
|
11
|
-
use std::cmp::Ordering;
|
11
|
+
use std::{cmp::Ordering, sync::Arc};
|
12
12
|
|
13
|
-
#[derive(Debug)]
|
13
|
+
#[derive(Debug, Clone)]
|
14
14
|
pub enum Middleware {
|
15
|
-
AllowList(AllowList),
|
16
|
-
AuthAPIKey(AuthAPIKey),
|
17
|
-
AuthBasic(AuthBasic),
|
18
|
-
AuthJwt(
|
19
|
-
CacheControl(CacheControl),
|
20
|
-
Compression(Compression),
|
21
|
-
Cors(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
15
|
+
AllowList(Arc<AllowList>),
|
16
|
+
AuthAPIKey(Arc<AuthAPIKey>),
|
17
|
+
AuthBasic(Arc<AuthBasic>),
|
18
|
+
AuthJwt(Arc<AuthJwt>),
|
19
|
+
CacheControl(Arc<CacheControl>),
|
20
|
+
Compression(Arc<Compression>),
|
21
|
+
Cors(Arc<Cors>),
|
22
|
+
Csp(Arc<Csp>),
|
23
|
+
DenyList(Arc<DenyList>),
|
24
|
+
ETag(Arc<ETag>),
|
25
|
+
IntrusionProtection(Arc<IntrusionProtection>),
|
26
|
+
LogRequests(Arc<LogRequests>),
|
27
|
+
MaxBody(Arc<MaxBody>),
|
28
|
+
Proxy(Arc<Proxy>),
|
29
|
+
RateLimit(Arc<RateLimit>),
|
30
|
+
Redirect(Arc<Redirect>),
|
31
|
+
RequestHeaders(Arc<RequestHeaders>),
|
32
|
+
ResponseHeaders(Arc<ResponseHeaders>),
|
33
|
+
RubyApp(Arc<RubyApp>),
|
34
|
+
StaticAssets(Arc<StaticAssets>),
|
35
|
+
StaticResponse(Arc<StaticResponse>),
|
35
36
|
}
|
36
37
|
|
37
38
|
#[async_trait]
|
@@ -51,6 +52,7 @@ impl MiddlewareLayer for Middleware {
|
|
51
52
|
Middleware::ResponseHeaders(filter) => filter.initialize().await,
|
52
53
|
Middleware::CacheControl(filter) => filter.initialize().await,
|
53
54
|
Middleware::Cors(filter) => filter.initialize().await,
|
55
|
+
Middleware::Csp(filter) => filter.initialize().await,
|
54
56
|
Middleware::ETag(filter) => filter.initialize().await,
|
55
57
|
Middleware::StaticAssets(filter) => filter.initialize().await,
|
56
58
|
Middleware::StaticResponse(filter) => filter.initialize().await,
|
@@ -80,6 +82,7 @@ impl MiddlewareLayer for Middleware {
|
|
80
82
|
Middleware::RateLimit(filter) => filter.before(req, context).await,
|
81
83
|
Middleware::CacheControl(filter) => filter.before(req, context).await,
|
82
84
|
Middleware::Cors(filter) => filter.before(req, context).await,
|
85
|
+
Middleware::Csp(filter) => filter.before(req, context).await,
|
83
86
|
Middleware::ETag(filter) => filter.before(req, context).await,
|
84
87
|
Middleware::StaticAssets(filter) => filter.before(req, context).await,
|
85
88
|
Middleware::StaticResponse(filter) => filter.before(req, context).await,
|
@@ -104,6 +107,7 @@ impl MiddlewareLayer for Middleware {
|
|
104
107
|
Middleware::RequestHeaders(filter) => filter.after(res, context).await,
|
105
108
|
Middleware::ResponseHeaders(filter) => filter.after(res, context).await,
|
106
109
|
Middleware::CacheControl(filter) => filter.after(res, context).await,
|
110
|
+
Middleware::Csp(filter) => filter.after(res, context).await,
|
107
111
|
Middleware::Cors(filter) => filter.after(res, context).await,
|
108
112
|
Middleware::ETag(filter) => filter.after(res, context).await,
|
109
113
|
Middleware::StaticAssets(filter) => filter.after(res, context).await,
|
@@ -134,12 +138,13 @@ impl Middleware {
|
|
134
138
|
Middleware::AuthAPIKey(_) => 11,
|
135
139
|
Middleware::RateLimit(_) => 12,
|
136
140
|
Middleware::ETag(_) => 13,
|
137
|
-
Middleware::
|
138
|
-
Middleware::
|
139
|
-
Middleware::
|
140
|
-
Middleware::
|
141
|
-
Middleware::
|
142
|
-
Middleware::
|
141
|
+
Middleware::Csp(_) => 14,
|
142
|
+
Middleware::Compression(_) => 15,
|
143
|
+
Middleware::Proxy(_) => 16,
|
144
|
+
Middleware::Cors(_) => 17,
|
145
|
+
Middleware::StaticResponse(_) => 18,
|
146
|
+
Middleware::StaticAssets(_) => 19,
|
147
|
+
Middleware::RubyApp(_) => 20,
|
143
148
|
}
|
144
149
|
}
|
145
150
|
}
|