itsi 0.1.19 → 0.2.2

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.
Files changed (645) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Cargo.lock +942 -242
  4. data/LICENSE.txt +698 -0
  5. data/README.md +77 -54
  6. data/Rakefile +9 -5
  7. data/crates/itsi_acme/.gitignore +4 -0
  8. data/crates/itsi_acme/Cargo.toml +86 -0
  9. data/crates/itsi_acme/LICENSE-APACHE +201 -0
  10. data/crates/itsi_acme/LICENSE-MIT +23 -0
  11. data/crates/itsi_acme/README.md +9 -0
  12. data/crates/itsi_acme/examples/high_level.rs +63 -0
  13. data/crates/itsi_acme/examples/high_level_warp.rs +52 -0
  14. data/crates/itsi_acme/examples/low_level.rs +87 -0
  15. data/crates/itsi_acme/examples/low_level_axum.rs +66 -0
  16. data/crates/itsi_acme/src/acceptor.rs +81 -0
  17. data/crates/itsi_acme/src/acme.rs +354 -0
  18. data/crates/itsi_acme/src/axum.rs +86 -0
  19. data/crates/itsi_acme/src/cache.rs +39 -0
  20. data/crates/itsi_acme/src/caches/boxed.rs +80 -0
  21. data/crates/itsi_acme/src/caches/composite.rs +69 -0
  22. data/crates/itsi_acme/src/caches/dir.rs +106 -0
  23. data/crates/itsi_acme/src/caches/mod.rs +11 -0
  24. data/crates/itsi_acme/src/caches/no.rs +78 -0
  25. data/crates/itsi_acme/src/caches/test.rs +136 -0
  26. data/crates/itsi_acme/src/config.rs +172 -0
  27. data/crates/itsi_acme/src/https_helper.rs +69 -0
  28. data/crates/itsi_acme/src/incoming.rs +142 -0
  29. data/crates/itsi_acme/src/jose.rs +161 -0
  30. data/crates/itsi_acme/src/lib.rs +142 -0
  31. data/crates/itsi_acme/src/resolver.rs +59 -0
  32. data/crates/itsi_acme/src/state.rs +424 -0
  33. data/crates/itsi_rb_helpers/src/lib.rs +4 -3
  34. data/crates/itsi_scheduler/Cargo.toml +1 -1
  35. data/crates/itsi_scheduler/src/itsi_scheduler.rs +8 -2
  36. data/crates/itsi_scheduler/src/lib.rs +1 -0
  37. data/crates/itsi_server/Cargo.toml +3 -3
  38. data/crates/itsi_server/src/lib.rs +2 -1
  39. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +20 -3
  40. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +11 -3
  41. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +255 -65
  42. data/crates/itsi_server/src/ruby_types/itsi_server.rs +3 -0
  43. data/crates/itsi_server/src/server/binds/bind.rs +3 -0
  44. data/crates/itsi_server/src/server/binds/listener.rs +44 -32
  45. data/crates/itsi_server/src/server/binds/tls/locked_dir_cache.rs +2 -2
  46. data/crates/itsi_server/src/server/binds/tls.rs +14 -6
  47. data/crates/itsi_server/src/server/middleware_stack/middleware.rs +33 -28
  48. data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +12 -5
  49. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +8 -1
  50. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +9 -1
  51. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +95 -37
  52. data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +11 -2
  53. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +39 -12
  54. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +36 -27
  55. data/crates/itsi_server/src/server/middleware_stack/middlewares/csp.rs +193 -0
  56. data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +12 -3
  57. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +74 -72
  58. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +15 -1
  59. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +11 -8
  60. data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +19 -11
  61. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +5 -5
  62. data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +2 -2
  63. data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +31 -2
  64. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +17 -20
  65. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +19 -8
  66. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +16 -37
  67. data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +22 -12
  68. data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +26 -11
  69. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +3 -3
  70. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +9 -2
  71. data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +14 -4
  72. data/crates/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +19 -0
  73. data/crates/itsi_server/src/server/middleware_stack/mod.rs +69 -35
  74. data/crates/itsi_server/src/server/mod.rs +1 -0
  75. data/crates/itsi_server/src/server/redirect_type.rs +26 -0
  76. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +30 -18
  77. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +77 -17
  78. data/crates/itsi_server/src/server/signal.rs +1 -0
  79. data/crates/itsi_server/src/server/size_limited_incoming.rs +6 -0
  80. data/crates/itsi_server/src/server/thread_worker.rs +6 -2
  81. data/crates/itsi_server/src/services/itsi_http_service.rs +20 -2
  82. data/crates/itsi_server/src/services/rate_limiter.rs +15 -4
  83. data/crates/itsi_server/src/services/static_file_server.rs +63 -47
  84. data/crates/itsi_tracing/src/lib.rs +80 -29
  85. data/docker/Dockerfile +12 -0
  86. data/docs/content/_index.md +17 -10
  87. data/docs/content/acknowledgements/_index.md +46 -0
  88. data/docs/content/configuration/_index.md +101 -0
  89. data/docs/content/contact/_index.md +14 -0
  90. data/docs/content/faqs/_index.md +29 -0
  91. data/docs/content/features/_index.md +291 -0
  92. data/docs/content/getting_started/_index.md +73 -0
  93. data/docs/content/getting_started/local_development.md +100 -0
  94. data/docs/content/getting_started/logging.md +23 -0
  95. data/docs/content/getting_started/running_itsi_in_production.md +26 -0
  96. data/docs/content/getting_started/signals.md +38 -0
  97. data/docs/content/itsi-server-100.png +0 -0
  98. data/docs/content/itsi_scheduler/_index.md +106 -0
  99. data/docs/content/itsi_scheduler/itsi-scheduler-100.png +0 -0
  100. data/docs/content/ruby-lsp.png +0 -0
  101. data/docs/content/ruby.svg +948 -0
  102. data/docs/content/utilities/_index.md +13 -0
  103. data/docs/content/utilities/config_file_testing.md +17 -0
  104. data/docs/content/utilities/passfile_generator.md +41 -0
  105. data/docs/content/utilities/route_testing.md +27 -0
  106. data/docs/content/utilities/secrets_management.md +30 -0
  107. data/docs/data/icons.yaml +949 -0
  108. data/docs/hugo.yaml +27 -28
  109. data/fairytale.txt +33 -0
  110. data/gems/scheduler/Cargo.lock +47 -47
  111. data/gems/scheduler/README.md +52 -24
  112. data/gems/scheduler/Rakefile +0 -4
  113. data/gems/scheduler/itsi-scheduler-100.png +0 -0
  114. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  115. data/gems/scheduler/lib/itsi/scheduler.rb +9 -4
  116. data/gems/scheduler/test/test_active_record.rb +12 -7
  117. data/gems/server/Cargo.lock +950 -239
  118. data/gems/server/README.md +2 -0
  119. data/gems/server/Rakefile +0 -4
  120. data/gems/server/exe/itsi +16 -5
  121. data/gems/server/lib/itsi/http_request/response_status_shortcodes.rb +2 -0
  122. data/gems/server/lib/itsi/http_request.rb +40 -9
  123. data/gems/server/lib/itsi/http_response.rb +2 -1
  124. data/gems/server/lib/itsi/passfile.rb +0 -1
  125. data/gems/server/lib/itsi/server/config/config_helpers.rb +105 -0
  126. data/gems/server/lib/itsi/server/config/dsl.rb +44 -411
  127. data/gems/server/lib/itsi/server/config/known_paths/KitchensinkDirectories.txt +2346 -0
  128. data/gems/server/lib/itsi/server/config/known_paths/Randomfiles.txt +24 -0
  129. data/gems/server/lib/itsi/server/config/known_paths/UnixDotfiles.txt +52 -0
  130. data/gems/server/lib/itsi/server/config/known_paths/backdoors/ASP_CommonBackdoors.txt +29 -0
  131. data/gems/server/lib/itsi/server/config/known_paths/backdoors/bot_control_panels.txt +1668 -0
  132. data/gems/server/lib/itsi/server/config/known_paths/backdoors/shells.txt +1167 -0
  133. data/gems/server/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST.txt +7 -0
  134. data/gems/server/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST_Windows.txt +6 -0
  135. data/gems/server/lib/itsi/server/config/known_paths/cgi/CGI_Microsoft.txt +79 -0
  136. data/gems/server/lib/itsi/server/config/known_paths/cgi/CGI_XPlatform.txt +3948 -0
  137. data/gems/server/lib/itsi/server/config/known_paths/cms/README.md +5 -0
  138. data/gems/server/lib/itsi/server/config/known_paths/cms/drupal_plugins.txt +6320 -0
  139. data/gems/server/lib/itsi/server/config/known_paths/cms/drupal_themes.txt +828 -0
  140. data/gems/server/lib/itsi/server/config/known_paths/cms/joomla_plugins.txt +224 -0
  141. data/gems/server/lib/itsi/server/config/known_paths/cms/joomla_themes.txt +30 -0
  142. data/gems/server/lib/itsi/server/config/known_paths/cms/php-nuke.txt +2142 -0
  143. data/gems/server/lib/itsi/server/config/known_paths/cms/wordpress.txt +1566 -0
  144. data/gems/server/lib/itsi/server/config/known_paths/cms/wp_common_theme_files.txt +46 -0
  145. data/gems/server/lib/itsi/server/config/known_paths/cms/wp_plugins.txt +13366 -0
  146. data/gems/server/lib/itsi/server/config/known_paths/cms/wp_plugins_full.txt +68662 -0
  147. data/gems/server/lib/itsi/server/config/known_paths/cms/wp_plugins_top225.txt +225 -0
  148. data/gems/server/lib/itsi/server/config/known_paths/cms/wp_themes.readme +12 -0
  149. data/gems/server/lib/itsi/server/config/known_paths/cms/wp_themes.txt +7336 -0
  150. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/3CharExtBrute.txt +17576 -0
  151. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/CommonWebExtensions.txt +80 -0
  152. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Backup.txt +14 -0
  153. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Common.txt +865 -0
  154. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Compressed.txt +186 -0
  155. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Mostcommon.txt +30 -0
  156. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Skipfish.txt +93 -0
  157. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/WordlistSkipfish.txt +1918 -0
  158. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/copy_of.txt +8 -0
  159. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories-lowercase.txt +56180 -0
  160. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories.txt +62290 -0
  161. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions-lowercase.txt +2367 -0
  162. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions.txt +2450 -0
  163. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files-lowercase.txt +35323 -0
  164. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files.txt +37037 -0
  165. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words-lowercase.txt +107982 -0
  166. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words.txt +119600 -0
  167. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories-lowercase.txt +26593 -0
  168. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories.txt +30009 -0
  169. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions-lowercase.txt +1233 -0
  170. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions.txt +1289 -0
  171. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files-lowercase.txt +16243 -0
  172. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files.txt +17128 -0
  173. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words-lowercase.txt +56293 -0
  174. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words.txt +63087 -0
  175. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories-lowercase.txt +17776 -0
  176. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories.txt +20122 -0
  177. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions-lowercase.txt +914 -0
  178. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions.txt +963 -0
  179. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files-lowercase.txt +10848 -0
  180. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files.txt +11424 -0
  181. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words-lowercase.txt +38267 -0
  182. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words.txt +43003 -0
  183. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/spanish.txt +445 -0
  184. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/test_demo.txt +36 -0
  185. data/gems/server/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/upload_variants.txt +44 -0
  186. data/gems/server/lib/itsi/server/config/known_paths/login-file-locations/Logins.txt +71 -0
  187. data/gems/server/lib/itsi/server/config/known_paths/login-file-locations/cfm.txt +294 -0
  188. data/gems/server/lib/itsi/server/config/known_paths/login-file-locations/html.txt +295 -0
  189. data/gems/server/lib/itsi/server/config/known_paths/login-file-locations/jsp.txt +294 -0
  190. data/gems/server/lib/itsi/server/config/known_paths/login-file-locations/php.txt +294 -0
  191. data/gems/server/lib/itsi/server/config/known_paths/login-file-locations/windows-asp.txt +294 -0
  192. data/gems/server/lib/itsi/server/config/known_paths/login-file-locations/windows-aspx.txt +294 -0
  193. data/gems/server/lib/itsi/server/config/known_paths/password-file-locations/Passwords.txt +47 -0
  194. data/gems/server/lib/itsi/server/config/known_paths/php/PHP.txt +30 -0
  195. data/gems/server/lib/itsi/server/config/known_paths/php/PHP_CommonBackdoors.txt +5 -0
  196. data/gems/server/lib/itsi/server/config/known_paths/proxy-conf.txt +31 -0
  197. data/gems/server/lib/itsi/server/config/known_paths/tftp.txt +79 -0
  198. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/ADFS.txt +86 -0
  199. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/AdobeXML.txt +16 -0
  200. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Apache.txt +101 -0
  201. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/ApacheTomcat.txt +47 -0
  202. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Apache_Axis.txt +16 -0
  203. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/ColdFusion.txt +111 -0
  204. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/FatwireCMS.txt +390 -0
  205. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Frontpage.txt +38 -0
  206. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/HP_System_Mgmt_Homepage.txt +239 -0
  207. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/HTTP_POST_Microsoft.txt +2 -0
  208. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Hyperion.txt +578 -0
  209. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/IIS.txt +187 -0
  210. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/JBoss.txt +5 -0
  211. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/JRun.txt +13 -0
  212. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/JavaServlets_Common.txt +3 -0
  213. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Joomla_exploitable.txt +1937 -0
  214. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/LotusNotes.txt +206 -0
  215. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Netware.txt +18 -0
  216. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Oracle9i.txt +60 -0
  217. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/OracleAppServer.txt +192 -0
  218. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/README.md +6 -0
  219. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Ruby_Rails.txt +121 -0
  220. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/SAP.txt +463 -0
  221. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Sharepoint.txt +1707 -0
  222. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/SiteMinder.txt +19 -0
  223. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/SunAppServerGlassfish.txt +51 -0
  224. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/SuniPlanet.txt +35 -0
  225. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Vignette.txt +73 -0
  226. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Weblogic.txt +160 -0
  227. data/gems/server/lib/itsi/server/config/known_paths/webservers-appservers/Websphere.txt +366 -0
  228. data/gems/server/lib/itsi/server/config/known_paths/wellknown-rfc5785.txt +30 -0
  229. data/gems/server/lib/itsi/server/config/known_paths.rb +20 -0
  230. data/gems/server/lib/itsi/server/config/middleware/_index.md +56 -0
  231. data/gems/server/lib/itsi/server/config/middleware/allow_list.md +46 -0
  232. data/gems/server/lib/itsi/server/config/middleware/allow_list.rb +42 -0
  233. data/gems/server/lib/itsi/server/config/middleware/auth_api_key.md +90 -0
  234. data/gems/server/lib/itsi/server/config/middleware/auth_api_key.rb +51 -0
  235. data/gems/server/lib/itsi/server/config/middleware/auth_basic.md +45 -0
  236. data/gems/server/lib/itsi/server/config/middleware/auth_basic.rb +44 -0
  237. data/gems/server/lib/itsi/server/config/middleware/auth_jwt.md +82 -0
  238. data/gems/server/lib/itsi/server/config/middleware/auth_jwt.rb +38 -0
  239. data/gems/server/lib/itsi/server/config/middleware/cache_control.md +78 -0
  240. data/gems/server/lib/itsi/server/config/middleware/cache_control.rb +45 -0
  241. data/gems/server/lib/itsi/server/config/middleware/cidr_to_regex.rb +50 -0
  242. data/gems/server/lib/itsi/server/config/middleware/compression.md +50 -0
  243. data/gems/server/lib/itsi/server/config/middleware/compression.rb +37 -0
  244. data/gems/server/lib/itsi/server/config/middleware/cors.md +93 -0
  245. data/gems/server/lib/itsi/server/config/middleware/cors.rb +32 -0
  246. data/gems/server/lib/itsi/server/config/middleware/csp.md +37 -0
  247. data/gems/server/lib/itsi/server/config/middleware/csp.rb +44 -0
  248. data/gems/server/lib/itsi/server/config/middleware/deny_list.md +45 -0
  249. data/gems/server/lib/itsi/server/config/middleware/deny_list.rb +42 -0
  250. data/gems/server/lib/itsi/server/config/middleware/endpoint/_index.md +159 -0
  251. data/gems/server/lib/itsi/server/config/middleware/endpoint/controller.md +186 -0
  252. data/gems/server/lib/itsi/server/config/middleware/endpoint/controller.rb +33 -0
  253. data/gems/server/lib/itsi/server/config/middleware/endpoint/delete.md +12 -0
  254. data/gems/server/lib/itsi/server/config/middleware/endpoint/delete.rb +42 -0
  255. data/gems/server/lib/itsi/server/config/middleware/endpoint/endpoint.rb +99 -0
  256. data/gems/server/lib/itsi/server/config/middleware/endpoint/get.md +12 -0
  257. data/gems/server/lib/itsi/server/config/middleware/endpoint/get.rb +42 -0
  258. data/gems/server/lib/itsi/server/config/middleware/endpoint/http_request.md +44 -0
  259. data/gems/server/lib/itsi/server/config/middleware/endpoint/http_response.md +39 -0
  260. data/gems/server/lib/itsi/server/config/middleware/endpoint/patch.md +12 -0
  261. data/gems/server/lib/itsi/server/config/middleware/endpoint/patch.rb +42 -0
  262. data/gems/server/lib/itsi/server/config/middleware/endpoint/post.md +12 -0
  263. data/gems/server/lib/itsi/server/config/middleware/endpoint/post.rb +42 -0
  264. data/gems/server/lib/itsi/server/config/middleware/endpoint/put.md +12 -0
  265. data/gems/server/lib/itsi/server/config/middleware/endpoint/put.rb +42 -0
  266. data/gems/server/lib/itsi/server/config/middleware/endpoint/schemas.md +122 -0
  267. data/gems/server/lib/itsi/server/config/middleware/error_response.md +61 -0
  268. data/gems/server/lib/itsi/server/config/middleware/error_response.rb +36 -0
  269. data/gems/server/lib/itsi/server/config/middleware/etag.md +59 -0
  270. data/gems/server/lib/itsi/server/config/middleware/etag.rb +27 -0
  271. data/gems/server/lib/itsi/server/config/middleware/grpc.md +172 -0
  272. data/gems/server/lib/itsi/server/config/middleware/grpc.rb +54 -0
  273. data/gems/server/lib/itsi/server/config/middleware/intrusion_protection.md +124 -0
  274. data/gems/server/lib/itsi/server/config/middleware/intrusion_protection.rb +61 -0
  275. data/gems/server/lib/itsi/server/config/middleware/location.md +107 -0
  276. data/gems/server/lib/itsi/server/config/middleware/location.rb +99 -0
  277. data/gems/server/lib/itsi/server/config/middleware/log_requests.md +65 -0
  278. data/gems/server/lib/itsi/server/config/middleware/log_requests.rb +31 -0
  279. data/gems/server/lib/itsi/server/config/middleware/max_body.md +18 -0
  280. data/gems/server/lib/itsi/server/config/middleware/max_body.rb +21 -0
  281. data/gems/server/lib/itsi/server/config/middleware/proxy.md +62 -0
  282. data/gems/server/lib/itsi/server/config/middleware/proxy.rb +41 -0
  283. data/gems/server/lib/itsi/server/config/middleware/rackup_file.md +54 -0
  284. data/gems/server/lib/itsi/server/config/middleware/rackup_file.rb +44 -0
  285. data/gems/server/lib/itsi/server/config/middleware/rate_limit.md +126 -0
  286. data/gems/server/lib/itsi/server/config/middleware/rate_limit.rb +34 -0
  287. data/gems/server/lib/itsi/server/config/middleware/rate_limit_store.rb +25 -0
  288. data/gems/server/lib/itsi/server/config/middleware/redirect.md +55 -0
  289. data/gems/server/lib/itsi/server/config/middleware/redirect.rb +25 -0
  290. data/gems/server/lib/itsi/server/config/middleware/request_headers.md +34 -0
  291. data/gems/server/lib/itsi/server/config/middleware/request_headers.rb +24 -0
  292. data/gems/server/lib/itsi/server/config/middleware/response_headers.md +33 -0
  293. data/gems/server/lib/itsi/server/config/middleware/response_headers.rb +25 -0
  294. data/gems/server/lib/itsi/server/config/middleware/run.md +60 -0
  295. data/gems/server/lib/itsi/server/config/middleware/run.rb +43 -0
  296. data/gems/server/lib/itsi/server/config/middleware/static_assets.md +73 -0
  297. data/gems/server/lib/itsi/server/config/middleware/static_assets.rb +87 -0
  298. data/gems/server/lib/itsi/server/config/middleware/static_response.md +44 -0
  299. data/gems/server/lib/itsi/server/config/middleware/static_response.rb +29 -0
  300. data/gems/server/lib/itsi/server/config/middleware/string_rewrite.md +67 -0
  301. data/gems/server/lib/itsi/server/config/middleware/token_source.rb +32 -0
  302. data/gems/server/lib/itsi/server/config/middleware.rb +13 -0
  303. data/gems/server/lib/itsi/server/config/option.rb +14 -0
  304. data/gems/server/lib/itsi/server/config/options/_index.md +37 -0
  305. data/gems/server/lib/itsi/server/config/options/auto_reload_config.md +13 -0
  306. data/gems/server/lib/itsi/server/config/options/auto_reload_config.rb +41 -0
  307. data/gems/server/lib/itsi/server/config/options/bind.md +71 -0
  308. data/gems/server/lib/itsi/server/config/options/bind.rb +26 -0
  309. data/gems/server/lib/itsi/server/config/options/certificates.md +65 -0
  310. data/gems/server/lib/itsi/server/config/options/daemonize.md +14 -0
  311. data/gems/server/lib/itsi/server/config/options/daemonize.rb +19 -0
  312. data/gems/server/lib/itsi/server/config/options/fiber_scheduler.md +34 -0
  313. data/gems/server/lib/itsi/server/config/options/fiber_scheduler.rb +21 -0
  314. data/gems/server/lib/itsi/server/config/options/header_read_timeout.md +17 -0
  315. data/gems/server/lib/itsi/server/config/options/header_read_timeout.rb +19 -0
  316. data/gems/server/lib/itsi/server/config/options/hooks/_index.md +11 -0
  317. data/gems/server/lib/itsi/server/config/options/hooks/after_fork.md +13 -0
  318. data/gems/server/lib/itsi/server/config/options/hooks/after_fork.rb +28 -0
  319. data/gems/server/lib/itsi/server/config/options/hooks/after_memory_limit_reached.md +14 -0
  320. data/gems/server/lib/itsi/server/config/options/hooks/after_memory_limit_reached.rb +28 -0
  321. data/gems/server/lib/itsi/server/config/options/hooks/after_start.md +12 -0
  322. data/gems/server/lib/itsi/server/config/options/hooks/after_start.rb +28 -0
  323. data/gems/server/lib/itsi/server/config/options/hooks/before_fork.md +13 -0
  324. data/gems/server/lib/itsi/server/config/options/hooks/before_fork.rb +28 -0
  325. data/gems/server/lib/itsi/server/config/options/hooks/before_restart.md +12 -0
  326. data/gems/server/lib/itsi/server/config/options/hooks/before_restart.rb +28 -0
  327. data/gems/server/lib/itsi/server/config/options/hooks/before_shutdown.md +12 -0
  328. data/gems/server/lib/itsi/server/config/options/hooks/before_shutdown.rb +28 -0
  329. data/gems/server/lib/itsi/server/config/options/include.md +20 -0
  330. data/gems/server/lib/itsi/server/config/options/include.rb +36 -0
  331. data/gems/server/lib/itsi/server/config/options/listen_backlog.md +11 -0
  332. data/gems/server/lib/itsi/server/config/options/listen_backlog.rb +19 -0
  333. data/gems/server/lib/itsi/server/config/options/log_format.md +18 -0
  334. data/gems/server/lib/itsi/server/config/options/log_format.rb +19 -0
  335. data/gems/server/lib/itsi/server/config/options/log_level.md +34 -0
  336. data/gems/server/lib/itsi/server/config/options/log_level.rb +20 -0
  337. data/gems/server/lib/itsi/server/config/options/log_target.md +38 -0
  338. data/gems/server/lib/itsi/server/config/options/log_target.rb +19 -0
  339. data/gems/server/lib/itsi/server/config/options/log_target_filters.md +17 -0
  340. data/gems/server/lib/itsi/server/config/options/log_target_filters.rb +19 -0
  341. data/gems/server/lib/itsi/server/config/options/multithreaded_reactor.md +27 -0
  342. data/gems/server/lib/itsi/server/config/options/multithreaded_reactor.rb +24 -0
  343. data/gems/server/lib/itsi/server/config/options/nodelay.md +16 -0
  344. data/gems/server/lib/itsi/server/config/options/nodelay.rb +19 -0
  345. data/gems/server/lib/itsi/server/config/options/oob_gc_responses_threshold.md +19 -0
  346. data/gems/server/lib/itsi/server/config/options/oob_gc_responses_threshold.rb +18 -0
  347. data/gems/server/lib/itsi/server/config/options/pin_worker_cores.md +17 -0
  348. data/gems/server/lib/itsi/server/config/options/pin_worker_cores.rb +19 -0
  349. data/gems/server/lib/itsi/server/config/options/preload.md +21 -0
  350. data/gems/server/lib/itsi/server/config/options/preload.rb +18 -0
  351. data/gems/server/lib/itsi/server/config/options/recv_buffer_size.md +15 -0
  352. data/gems/server/lib/itsi/server/config/options/recv_buffer_size.rb +19 -0
  353. data/gems/server/lib/itsi/server/config/options/redirect_http_to_https.md +21 -0
  354. data/gems/server/lib/itsi/server/config/options/redirect_http_to_https.rb +30 -0
  355. data/gems/server/lib/itsi/server/config/options/request_timeout.md +23 -0
  356. data/gems/server/lib/itsi/server/config/options/request_timeout.rb +19 -0
  357. data/gems/server/lib/itsi/server/config/options/reuse_address.md +16 -0
  358. data/gems/server/lib/itsi/server/config/options/reuse_address.rb +19 -0
  359. data/gems/server/lib/itsi/server/config/options/reuse_port.md +16 -0
  360. data/gems/server/lib/itsi/server/config/options/reuse_port.rb +19 -0
  361. data/gems/server/lib/itsi/server/config/options/scheduler_threads.md +34 -0
  362. data/gems/server/lib/itsi/server/config/options/scheduler_threads.rb +17 -0
  363. data/gems/server/lib/itsi/server/config/options/shutdown_timeout.md +17 -0
  364. data/gems/server/lib/itsi/server/config/options/shutdown_timeout.rb +19 -0
  365. data/gems/server/lib/itsi/server/config/options/stream_body.md +32 -0
  366. data/gems/server/lib/itsi/server/config/options/stream_body.rb +18 -0
  367. data/gems/server/lib/itsi/server/config/options/threads.md +44 -0
  368. data/gems/server/lib/itsi/server/config/options/threads.rb +17 -0
  369. data/gems/server/lib/itsi/server/config/options/watch.md +16 -0
  370. data/gems/server/lib/itsi/server/config/options/watch.rb +28 -0
  371. data/gems/server/lib/itsi/server/config/options/worker_memory_limit.md +22 -0
  372. data/gems/server/lib/itsi/server/config/options/worker_memory_limit.rb +18 -0
  373. data/gems/server/lib/itsi/server/config/options/workers.md +42 -0
  374. data/gems/server/lib/itsi/server/config/options/workers.rb +17 -0
  375. data/gems/server/lib/itsi/server/config/typed_struct.rb +242 -0
  376. data/gems/server/lib/itsi/server/config.rb +134 -11
  377. data/gems/server/lib/itsi/server/default_config/Itsi.rb +3 -3
  378. data/gems/server/lib/itsi/server/grpc/grpc_call.rb +1 -1
  379. data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +11 -4
  380. data/gems/server/lib/itsi/server/rack/handler/itsi.rb +3 -3
  381. data/gems/server/lib/itsi/server/route_tester.rb +58 -8
  382. data/gems/server/lib/itsi/server/signal_trap.rb +5 -1
  383. data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +14 -18
  384. data/gems/server/lib/itsi/server/typed_handlers/source_parser.rb +6 -5
  385. data/gems/server/lib/itsi/server/typed_handlers.rb +12 -4
  386. data/gems/server/lib/itsi/server/version.rb +1 -1
  387. data/gems/server/lib/itsi/server.rb +122 -17
  388. data/gems/server/lib/ruby_lsp/itsi/addon.rb +66 -48
  389. data/gems/server/test/helpers/test_helper.rb +130 -11
  390. data/gems/server/test/middleware/allow_list.rb +128 -0
  391. data/gems/server/test/middleware/auth_api_key.rb +141 -0
  392. data/gems/server/test/middleware/auth_basic.rb +91 -0
  393. data/gems/server/test/middleware/auth_jwt.rb +214 -0
  394. data/gems/server/test/middleware/cache_control.rb +82 -0
  395. data/gems/server/test/middleware/cidr_to_regex.rb +46 -0
  396. data/gems/server/test/middleware/compression.rb +89 -0
  397. data/gems/server/test/middleware/cors.rb +113 -0
  398. data/gems/server/test/middleware/csp.rb +62 -0
  399. data/gems/server/test/middleware/deny_list.rb +131 -0
  400. data/gems/server/test/middleware/endpoint.rb +300 -0
  401. data/gems/server/test/middleware/etag.rb +75 -0
  402. data/gems/server/test/middleware/grpc/grpc.rb +158 -0
  403. data/gems/server/test/middleware/grpc/test_service.proto +32 -0
  404. data/gems/server/test/middleware/grpc/test_service_impl.rb +28 -0
  405. data/gems/server/test/middleware/grpc/test_service_pb.rb +18 -0
  406. data/gems/server/test/middleware/grpc/test_service_services_pb.rb +30 -0
  407. data/gems/server/test/middleware/header_interpolation.rb +35 -0
  408. data/gems/server/test/middleware/intrusion_protection.rb +259 -0
  409. data/gems/server/test/middleware/location.rb +220 -0
  410. data/gems/server/test/middleware/max_body.rb +20 -0
  411. data/gems/server/test/middleware/proxy.rb +415 -0
  412. data/gems/server/test/middleware/rate_limit.rb +211 -0
  413. data/gems/server/test/middleware/redirect.rb +85 -0
  414. data/gems/server/test/middleware/request_headers.rb +50 -0
  415. data/gems/server/test/middleware/response_headers.rb +50 -0
  416. data/gems/server/test/middleware/static_assets.rb +374 -0
  417. data/gems/server/test/middleware/static_response.rb +56 -0
  418. data/gems/server/test/middleware/string_rewrite.rb +112 -0
  419. data/gems/server/test/middleware/test_log_requests.rb +17 -0
  420. data/gems/server/test/options/bind.rb +47 -0
  421. data/gems/server/test/options/header_read_timeout.rb +23 -0
  422. data/gems/server/test/options/test_request_timeout.rb +16 -0
  423. data/gems/server/test/options/test_threads.rb +15 -0
  424. data/gems/server/test/options/test_workers.rb +16 -0
  425. data/gems/server/test/{test_itsi_server.rb → rack/test_rack_server.rb} +82 -95
  426. data/grpc_test/Itsi.rb +11 -0
  427. data/grpc_test/echo.proto +14 -0
  428. data/grpc_test/echo_pb.rb +16 -0
  429. data/grpc_test/echo_service_impl.rb +8 -0
  430. data/{sandbox/itsi_file/echo_service_nonitsi → grpc_test}/echo_services_pb.rb +0 -7
  431. data/itsi-scheduler-100.png +0 -0
  432. data/itsi-server-100.png +0 -0
  433. data/lib/itsi/version.rb +1 -1
  434. data/tasks.txt +17 -66
  435. metadata +352 -217
  436. data/crates/_index.md +0 -0
  437. data/crates/itsi_server/src/ruby_types/README.md +0 -21
  438. data/crates/itsi_server/test.md +0 -14
  439. data/docs/Itsi.rb +0 -17
  440. data/docs/content/about.md +0 -6
  441. data/docs/content/docs/_index.md +0 -18
  442. data/docs/content/docs/first-page.md +0 -9
  443. data/docs/content/docs/folder/_index.md +0 -10
  444. data/docs/content/docs/folder/leaf.md +0 -7
  445. data/foo/Itsi.rb +0 -122
  446. data/gems/_index.md +0 -18
  447. data/gems/scheduler/CHANGELOG.md +0 -5
  448. data/gems/scheduler/CODE_OF_CONDUCT.md +0 -139
  449. data/gems/scheduler/LICENSE.txt +0 -21
  450. data/gems/scheduler/_index.md +0 -7
  451. data/gems/server/CHANGELOG.md +0 -10
  452. data/gems/server/CODE_OF_CONDUCT.md +0 -139
  453. data/gems/server/LICENSE.txt +0 -21
  454. data/gems/server/_index.md +0 -6
  455. data/gems/server/lib/itsi/server/default_config/Itsi-rackup.rb +0 -119
  456. data/sandbox/README.md +0 -5
  457. data/sandbox/deploy/main.tf +0 -238
  458. data/sandbox/deploy/outputs.tf +0 -4
  459. data/sandbox/deploy/vars.tf +0 -11
  460. data/sandbox/falcon_benchmark/Gemfile +0 -10
  461. data/sandbox/falcon_benchmark/Gemfile.lock +0 -140
  462. data/sandbox/falcon_benchmark/config.ru +0 -54
  463. data/sandbox/itsi_file/Gemfile +0 -13
  464. data/sandbox/itsi_file/Gemfile.lock +0 -111
  465. data/sandbox/itsi_file/Itsi.rb +0 -474
  466. data/sandbox/itsi_file/call.json +0 -1
  467. data/sandbox/itsi_file/echo_client/Gemfile +0 -10
  468. data/sandbox/itsi_file/echo_client/Gemfile.lock +0 -27
  469. data/sandbox/itsi_file/echo_client/README.md +0 -95
  470. data/sandbox/itsi_file/echo_client/echo_client.rb +0 -164
  471. data/sandbox/itsi_file/echo_client/gen_proto.sh +0 -17
  472. data/sandbox/itsi_file/echo_client/lib/echo_pb.rb +0 -16
  473. data/sandbox/itsi_file/echo_client/lib/echo_services_pb.rb +0 -29
  474. data/sandbox/itsi_file/echo_client/run_client.rb +0 -64
  475. data/sandbox/itsi_file/echo_client/test_compressions.sh +0 -20
  476. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile +0 -10
  477. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile.lock +0 -79
  478. data/sandbox/itsi_file/echo_service_nonitsi/echo.proto +0 -26
  479. data/sandbox/itsi_file/echo_service_nonitsi/echo_pb.rb +0 -16
  480. data/sandbox/itsi_file/echo_service_nonitsi/server.rb +0 -52
  481. data/sandbox/itsi_file/error.html +0 -2
  482. data/sandbox/itsi_file/organisations_controller.rb +0 -20
  483. data/sandbox/itsi_file/public/assets/image.png +0 -0
  484. data/sandbox/itsi_sandbox_async/Gemfile +0 -10
  485. data/sandbox/itsi_sandbox_async/Gemfile.lock +0 -69
  486. data/sandbox/itsi_sandbox_async/config.ru +0 -9
  487. data/sandbox/itsi_sandbox_hanami/.env +0 -2
  488. data/sandbox/itsi_sandbox_hanami/.gitignore +0 -6
  489. data/sandbox/itsi_sandbox_hanami/.rspec +0 -1
  490. data/sandbox/itsi_sandbox_hanami/Gemfile +0 -49
  491. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +0 -440
  492. data/sandbox/itsi_sandbox_hanami/Guardfile +0 -9
  493. data/sandbox/itsi_sandbox_hanami/Procfile.dev +0 -2
  494. data/sandbox/itsi_sandbox_hanami/README.md +0 -1
  495. data/sandbox/itsi_sandbox_hanami/Rakefile +0 -3
  496. data/sandbox/itsi_sandbox_hanami/app/action.rb +0 -12
  497. data/sandbox/itsi_sandbox_hanami/app/actions/.keep +0 -0
  498. data/sandbox/itsi_sandbox_hanami/app/assets/css/app.css +0 -5
  499. data/sandbox/itsi_sandbox_hanami/app/assets/images/favicon.ico +0 -0
  500. data/sandbox/itsi_sandbox_hanami/app/assets/js/app.js +0 -1
  501. data/sandbox/itsi_sandbox_hanami/app/db/relation.rb +0 -10
  502. data/sandbox/itsi_sandbox_hanami/app/db/repo.rb +0 -10
  503. data/sandbox/itsi_sandbox_hanami/app/db/struct.rb +0 -10
  504. data/sandbox/itsi_sandbox_hanami/app/operation.rb +0 -9
  505. data/sandbox/itsi_sandbox_hanami/app/relations/.keep +0 -0
  506. data/sandbox/itsi_sandbox_hanami/app/repos/.keep +0 -0
  507. data/sandbox/itsi_sandbox_hanami/app/structs/.keep +0 -0
  508. data/sandbox/itsi_sandbox_hanami/app/templates/layouts/app.html.erb +0 -14
  509. data/sandbox/itsi_sandbox_hanami/app/view.rb +0 -9
  510. data/sandbox/itsi_sandbox_hanami/app/views/helpers.rb +0 -10
  511. data/sandbox/itsi_sandbox_hanami/bin/dev +0 -8
  512. data/sandbox/itsi_sandbox_hanami/config/app.rb +0 -8
  513. data/sandbox/itsi_sandbox_hanami/config/assets.js +0 -16
  514. data/sandbox/itsi_sandbox_hanami/config/db/migrate/.keep +0 -0
  515. data/sandbox/itsi_sandbox_hanami/config/db/seeds.rb +0 -15
  516. data/sandbox/itsi_sandbox_hanami/config/puma.rb +0 -47
  517. data/sandbox/itsi_sandbox_hanami/config/routes.rb +0 -7
  518. data/sandbox/itsi_sandbox_hanami/config/settings.rb +0 -9
  519. data/sandbox/itsi_sandbox_hanami/config.ru +0 -5
  520. data/sandbox/itsi_sandbox_hanami/db/.keep +0 -0
  521. data/sandbox/itsi_sandbox_hanami/lib/itsi_hanami/types.rb +0 -11
  522. data/sandbox/itsi_sandbox_hanami/lib/tasks/.keep +0 -0
  523. data/sandbox/itsi_sandbox_hanami/package-lock.json +0 -946
  524. data/sandbox/itsi_sandbox_hanami/package.json +0 -8
  525. data/sandbox/itsi_sandbox_hanami/spec/requests/root_spec.rb +0 -11
  526. data/sandbox/itsi_sandbox_hanami/spec/spec_helper.rb +0 -9
  527. data/sandbox/itsi_sandbox_hanami/spec/support/db/cleaning.rb +0 -42
  528. data/sandbox/itsi_sandbox_hanami/spec/support/db.rb +0 -10
  529. data/sandbox/itsi_sandbox_hanami/spec/support/features.rb +0 -5
  530. data/sandbox/itsi_sandbox_hanami/spec/support/operations.rb +0 -8
  531. data/sandbox/itsi_sandbox_hanami/spec/support/requests.rb +0 -13
  532. data/sandbox/itsi_sandbox_hanami/spec/support/rspec.rb +0 -61
  533. data/sandbox/itsi_sandbox_rack/Gemfile +0 -17
  534. data/sandbox/itsi_sandbox_rack/Gemfile.lock +0 -153
  535. data/sandbox/itsi_sandbox_rack/config.ru +0 -5
  536. data/sandbox/itsi_sandbox_rack_lint/Gemfile +0 -7
  537. data/sandbox/itsi_sandbox_rack_lint/Gemfile.lock +0 -27
  538. data/sandbox/itsi_sandbox_rack_lint/config.ru +0 -3
  539. data/sandbox/itsi_sandbox_rails/.dockerignore +0 -48
  540. data/sandbox/itsi_sandbox_rails/.gitattributes +0 -9
  541. data/sandbox/itsi_sandbox_rails/.github/dependabot.yml +0 -12
  542. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +0 -90
  543. data/sandbox/itsi_sandbox_rails/.gitignore +0 -35
  544. data/sandbox/itsi_sandbox_rails/.rubocop.yml +0 -8
  545. data/sandbox/itsi_sandbox_rails/.ruby-version +0 -1
  546. data/sandbox/itsi_sandbox_rails/Dockerfile +0 -69
  547. data/sandbox/itsi_sandbox_rails/Gemfile +0 -66
  548. data/sandbox/itsi_sandbox_rails/Gemfile.lock +0 -429
  549. data/sandbox/itsi_sandbox_rails/README.md +0 -24
  550. data/sandbox/itsi_sandbox_rails/Rakefile +0 -6
  551. data/sandbox/itsi_sandbox_rails/app/assets/config/manifest.js +0 -4
  552. data/sandbox/itsi_sandbox_rails/app/assets/images/.keep +0 -0
  553. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +0 -15
  554. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/channel.rb +0 -4
  555. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/connection.rb +0 -4
  556. data/sandbox/itsi_sandbox_rails/app/controllers/application_controller.rb +0 -4
  557. data/sandbox/itsi_sandbox_rails/app/controllers/concerns/.keep +0 -0
  558. data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +0 -66
  559. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +0 -40
  560. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +0 -29
  561. data/sandbox/itsi_sandbox_rails/app/helpers/application_helper.rb +0 -2
  562. data/sandbox/itsi_sandbox_rails/app/javascript/application.js +0 -3
  563. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/application.js +0 -9
  564. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/hello_controller.js +0 -7
  565. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/index.js +0 -4
  566. data/sandbox/itsi_sandbox_rails/app/jobs/application_job.rb +0 -7
  567. data/sandbox/itsi_sandbox_rails/app/mailers/application_mailer.rb +0 -4
  568. data/sandbox/itsi_sandbox_rails/app/models/application_record.rb +0 -3
  569. data/sandbox/itsi_sandbox_rails/app/models/concerns/.keep +0 -0
  570. data/sandbox/itsi_sandbox_rails/app/models/post.rb +0 -2
  571. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +0 -23
  572. data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.html.erb +0 -13
  573. data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.text.erb +0 -1
  574. data/sandbox/itsi_sandbox_rails/app/views/pwa/manifest.json.erb +0 -22
  575. data/sandbox/itsi_sandbox_rails/app/views/pwa/service-worker.js +0 -26
  576. data/sandbox/itsi_sandbox_rails/bin/brakeman +0 -7
  577. data/sandbox/itsi_sandbox_rails/bin/bundle +0 -109
  578. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +0 -13
  579. data/sandbox/itsi_sandbox_rails/bin/importmap +0 -4
  580. data/sandbox/itsi_sandbox_rails/bin/rails +0 -4
  581. data/sandbox/itsi_sandbox_rails/bin/rake +0 -4
  582. data/sandbox/itsi_sandbox_rails/bin/rubocop +0 -8
  583. data/sandbox/itsi_sandbox_rails/bin/setup +0 -37
  584. data/sandbox/itsi_sandbox_rails/config/application.rb +0 -27
  585. data/sandbox/itsi_sandbox_rails/config/boot.rb +0 -4
  586. data/sandbox/itsi_sandbox_rails/config/cable.yml +0 -10
  587. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +0 -1
  588. data/sandbox/itsi_sandbox_rails/config/database.yml +0 -30
  589. data/sandbox/itsi_sandbox_rails/config/environment.rb +0 -5
  590. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +0 -82
  591. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +0 -106
  592. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +0 -67
  593. data/sandbox/itsi_sandbox_rails/config/importmap.rb +0 -7
  594. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +0 -12
  595. data/sandbox/itsi_sandbox_rails/config/initializers/content_security_policy.rb +0 -25
  596. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +0 -8
  597. data/sandbox/itsi_sandbox_rails/config/initializers/inflections.rb +0 -16
  598. data/sandbox/itsi_sandbox_rails/config/initializers/permissions_policy.rb +0 -13
  599. data/sandbox/itsi_sandbox_rails/config/locales/en.yml +0 -31
  600. data/sandbox/itsi_sandbox_rails/config/puma.rb +0 -34
  601. data/sandbox/itsi_sandbox_rails/config/routes.rb +0 -23
  602. data/sandbox/itsi_sandbox_rails/config/storage.yml +0 -34
  603. data/sandbox/itsi_sandbox_rails/config.ru +0 -6
  604. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +0 -10
  605. data/sandbox/itsi_sandbox_rails/db/schema.rb +0 -23
  606. data/sandbox/itsi_sandbox_rails/db/seeds.rb +0 -9
  607. data/sandbox/itsi_sandbox_rails/lib/assets/.keep +0 -0
  608. data/sandbox/itsi_sandbox_rails/lib/tasks/.keep +0 -0
  609. data/sandbox/itsi_sandbox_rails/log/.keep +0 -0
  610. data/sandbox/itsi_sandbox_rails/public/404.html +0 -67
  611. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +0 -66
  612. data/sandbox/itsi_sandbox_rails/public/422.html +0 -67
  613. data/sandbox/itsi_sandbox_rails/public/500.html +0 -66
  614. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  615. data/sandbox/itsi_sandbox_rails/public/icon.svg +0 -3
  616. data/sandbox/itsi_sandbox_rails/public/robots.txt +0 -1
  617. data/sandbox/itsi_sandbox_rails/storage/.keep +0 -0
  618. data/sandbox/itsi_sandbox_rails/test/application_system_test_case.rb +0 -5
  619. data/sandbox/itsi_sandbox_rails/test/channels/application_cable/connection_test.rb +0 -13
  620. data/sandbox/itsi_sandbox_rails/test/controllers/.keep +0 -0
  621. data/sandbox/itsi_sandbox_rails/test/fixtures/files/.keep +0 -0
  622. data/sandbox/itsi_sandbox_rails/test/helpers/.keep +0 -0
  623. data/sandbox/itsi_sandbox_rails/test/integration/.keep +0 -0
  624. data/sandbox/itsi_sandbox_rails/test/mailers/.keep +0 -0
  625. data/sandbox/itsi_sandbox_rails/test/models/.keep +0 -0
  626. data/sandbox/itsi_sandbox_rails/test/system/.keep +0 -0
  627. data/sandbox/itsi_sandbox_rails/test/test_helper.rb +0 -15
  628. data/sandbox/itsi_sandbox_rails/tmp/.keep +0 -0
  629. data/sandbox/itsi_sandbox_rails/tmp/pids/.keep +0 -0
  630. data/sandbox/itsi_sandbox_rails/tmp/storage/.keep +0 -0
  631. data/sandbox/itsi_sandbox_rails/vendor/.keep +0 -0
  632. data/sandbox/itsi_sandbox_rails/vendor/javascript/.keep +0 -0
  633. data/sandbox/itsi_sandbox_roda/Gemfile +0 -5
  634. data/sandbox/itsi_sandbox_roda/Gemfile.lock +0 -37
  635. data/sandbox/itsi_sandbox_roda/config.ru +0 -39
  636. data/sandbox/itsi_sinatra/Gemfile +0 -9
  637. data/sandbox/itsi_sinatra/Gemfile.lock +0 -81
  638. data/sandbox/itsi_sinatra/app.rb +0 -8
  639. data/sandbox/pebble/docker-compose.yml +0 -11
  640. data/sandbox/static_files/.env +0 -1
  641. data/sandbox/static_files/404.html +0 -25
  642. data/sandbox/static_files/_DSC0102.NEF.jpg +0 -0
  643. data/sandbox/static_files/about.html +0 -68
  644. data/sandbox/static_files/tiny.html +0 -1
  645. data/sandbox/static_files/writebook.zip +0 -0
@@ -1,9 +1,12 @@
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;
6
+ use rcgen::ExtendedKeyUsagePurpose;
5
7
  use rcgen::{
6
- BasicConstraints, CertificateParams, DistinguishedName, DnType, IsCa, KeyPair, SanType,
8
+ BasicConstraints, CertificateParams, DistinguishedName, DnType, IsCa, KeyPair, KeyUsagePurpose,
9
+ SanType,
7
10
  };
8
11
  use rustls::{
9
12
  pki_types::{CertificateDer, PrivateKeyDer},
@@ -18,7 +21,6 @@ use std::{
18
21
  };
19
22
  use tokio::sync::Mutex;
20
23
  use tokio_rustls::{rustls::ServerConfig, TlsAcceptor};
21
- use tokio_rustls_acme::{AcmeAcceptor, AcmeConfig, AcmeState};
22
24
 
23
25
  use crate::env::{
24
26
  ITSI_ACME_CACHE_DIR, ITSI_ACME_CA_PEM_PATH, ITSI_ACME_CONTACT_EMAIL, ITSI_ACME_DIRECTORY_URL,
@@ -228,13 +230,14 @@ pub fn generate_ca_signed_cert(
228
230
  .push(DnType::CommonName, domains[0].clone());
229
231
 
230
232
  ee_params.use_authority_key_identifier_extension = true;
233
+ ee_params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ServerAuth];
231
234
 
232
235
  let ee_cert = ee_params.signed_by(&ee_key, &ca_cert, &ca_kp).unwrap();
233
236
  let ee_cert_der = ee_cert.der().to_vec();
234
237
  let ee_cert = CertificateDer::from(ee_cert_der);
235
- let ca_cert = CertificateDer::from(ca_cert.der().to_vec());
238
+
236
239
  Ok((
237
- vec![ee_cert, ca_cert],
240
+ vec![ee_cert],
238
241
  PrivateKeyDer::try_from(ee_key.serialize_der()).unwrap(),
239
242
  ))
240
243
  }
@@ -253,12 +256,17 @@ fn get_or_create_local_dev_ca() -> Result<(String, String)> {
253
256
 
254
257
  Ok((key_pem, cert_pem))
255
258
  } else {
256
- let subject_alt_names = vec!["dev.itsi.fyi".to_string(), "localhost".to_string()];
259
+ let subject_alt_names = vec!["ca.itsi.fyi".to_string(), "localhost".to_string()];
257
260
  let mut params = CertificateParams::new(subject_alt_names)?;
258
261
  let mut distinguished_name = DistinguishedName::new();
259
- distinguished_name.push(DnType::CommonName, "Itsi Development CA");
262
+ distinguished_name.push(DnType::CommonName, "ca.itsi.fyi");
260
263
  params.distinguished_name = distinguished_name;
261
264
  params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
265
+ params.key_usages = vec![
266
+ KeyUsagePurpose::KeyCertSign,
267
+ KeyUsagePurpose::CrlSign,
268
+ KeyUsagePurpose::DigitalSignature, // useful for OCSP/CRL signing
269
+ ];
262
270
  let key_pair = KeyPair::generate()?;
263
271
  let cert = params.self_signed(&key_pair)?;
264
272
 
@@ -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(Box<AuthJwt>),
19
- CacheControl(CacheControl),
20
- Compression(Compression),
21
- Cors(Box<Cors>),
22
- DenyList(DenyList),
23
- ETag(ETag),
24
- IntrusionProtection(IntrusionProtection),
25
- LogRequests(LogRequests),
26
- MaxBody(MaxBody),
27
- Proxy(Proxy),
28
- RateLimit(RateLimit),
29
- Redirect(Redirect),
30
- RequestHeaders(RequestHeaders),
31
- ResponseHeaders(ResponseHeaders),
32
- RubyApp(RubyApp),
33
- StaticAssets(StaticAssets),
34
- StaticResponse(StaticResponse),
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::Compression(_) => 14,
138
- Middleware::Proxy(_) => 15,
139
- Middleware::Cors(_) => 16,
140
- Middleware::StaticResponse(_) => 17,
141
- Middleware::StaticAssets(_) => 18,
142
- Middleware::RubyApp(_) => 19,
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
  }
@@ -1,23 +1,23 @@
1
+ use super::{token_source::TokenSource, ErrorResponse, FromValue, MiddlewareLayer};
1
2
  use crate::{
2
3
  server::http_message_types::{HttpRequest, HttpResponse, RequestExt},
3
4
  services::itsi_http_service::HttpRequestContext,
4
5
  };
5
-
6
- use super::{ErrorResponse, FromValue, MiddlewareLayer};
7
-
8
6
  use async_trait::async_trait;
9
7
  use either::Either;
10
8
  use itsi_error::ItsiError;
11
9
  use magnus::error::Result;
12
10
  use regex::RegexSet;
13
11
  use serde::Deserialize;
14
- use std::sync::OnceLock;
12
+ use std::{collections::HashMap, sync::OnceLock};
13
+ use tracing::debug;
15
14
 
16
15
  #[derive(Debug, Clone, Deserialize)]
17
16
  pub struct AllowList {
18
17
  #[serde(skip_deserializing)]
19
18
  pub allowed_ips: OnceLock<RegexSet>,
20
19
  pub allowed_patterns: Vec<String>,
20
+ pub trusted_proxies: HashMap<String, TokenSource>,
21
21
  #[serde(default = "forbidden_error_response")]
22
22
  pub error_response: ErrorResponse,
23
23
  }
@@ -42,7 +42,14 @@ impl MiddlewareLayer for AllowList {
42
42
  context: &mut HttpRequestContext,
43
43
  ) -> Result<Either<HttpRequest, HttpResponse>> {
44
44
  if let Some(allowed_ips) = self.allowed_ips.get() {
45
- if !allowed_ips.is_match(&context.addr) {
45
+ let addr = if self.trusted_proxies.contains_key(&context.addr) {
46
+ let source = self.trusted_proxies.get(&context.addr).unwrap();
47
+ source.extract_token(&req).unwrap_or(&context.addr)
48
+ } else {
49
+ &context.addr
50
+ };
51
+ if !allowed_ips.is_match(addr) {
52
+ debug!(target: "middleware::allow_list", "IP address {} is not allowed", addr);
46
53
  return Ok(Either::Right(
47
54
  self.error_response
48
55
  .to_http_response(req.accept().into())
@@ -11,6 +11,7 @@ use async_trait::async_trait;
11
11
  use either::Either;
12
12
  use magnus::error::Result;
13
13
  use serde::Deserialize;
14
+ use tracing::debug;
14
15
 
15
16
  type PasswordHash = String;
16
17
 
@@ -51,6 +52,8 @@ impl MiddlewareLayer for AuthAPIKey {
51
52
  }
52
53
  TokenSource::Query(query_name) => req.query_param(query_name),
53
54
  } {
55
+ debug!(target: "middleware::auth_api_key", "API Key Retrieved. Anonymous {}", self.key_id_source.is_none());
56
+
54
57
  if let Some(key_id) = self.key_id_source.as_ref() {
55
58
  let key_id = match &key_id {
56
59
  TokenSource::Header { name, prefix } => {
@@ -66,17 +69,21 @@ impl MiddlewareLayer for AuthAPIKey {
66
69
  }
67
70
  TokenSource::Query(query_name) => req.query_param(query_name),
68
71
  };
72
+ debug!(target: "middleware::auth_api_key", "Key ID Retrieved");
69
73
  if let Some(hash) = key_id.and_then(|kid| self.valid_keys.get(kid)) {
74
+ debug!(target: "middleware::auth_api_key", "Key for ID found");
70
75
  if password_hasher::verify_password_hash(submitted_key, hash).is_ok_and(|v| v) {
71
76
  return Ok(Either::Left(req));
72
77
  }
73
78
  }
74
- } else if self.valid_keys.iter().any(|(_key_id, key)| {
79
+ } else if self.valid_keys.values().any(|key| {
75
80
  password_hasher::verify_password_hash(submitted_key, key).is_ok_and(|v| v)
76
81
  }) {
77
82
  return Ok(Either::Left(req));
78
83
  }
79
84
  }
85
+
86
+ debug!(target: "middleware::auth_api_key", "Failed to authenticate API key");
80
87
  Ok(Either::Right(
81
88
  self.error_response
82
89
  .to_http_response(req.accept().into())
@@ -8,6 +8,7 @@ use magnus::error::Result;
8
8
  use serde::{Deserialize, Serialize};
9
9
  use std::collections::HashMap;
10
10
  use std::str;
11
+ use tracing::debug;
11
12
 
12
13
  use crate::{
13
14
  server::http_message_types::{HttpRequest, HttpResponse, RequestExt},
@@ -48,6 +49,7 @@ impl MiddlewareLayer for AuthBasic {
48
49
  let auth_header = req.header("Authorization");
49
50
 
50
51
  if !auth_header.is_some_and(|header| header.starts_with("Basic ")) {
52
+ debug!(target: "middleware::auth_basic", "Basic auth failed. Authorization Header doesn't start with 'Basic '");
51
53
  return Ok(Either::Right(self.basic_auth_failed_response()));
52
54
  }
53
55
 
@@ -57,6 +59,7 @@ impl MiddlewareLayer for AuthBasic {
57
59
  let decoded = match general_purpose::STANDARD.decode(encoded_credentials) {
58
60
  Ok(bytes) => bytes,
59
61
  Err(_) => {
62
+ debug!(target: "middleware::auth_basic", "Basic auth failed. Decoding failed");
60
63
  return Ok(Either::Right(self.basic_auth_failed_response()));
61
64
  }
62
65
  };
@@ -64,6 +67,7 @@ impl MiddlewareLayer for AuthBasic {
64
67
  let decoded_str = match str::from_utf8(&decoded) {
65
68
  Ok(s) => s,
66
69
  Err(_) => {
70
+ debug!(target: "middleware::auth_basic", "Basic auth failed. Decoding failed");
67
71
  return Ok(Either::Right(self.basic_auth_failed_response()));
68
72
  }
69
73
  };
@@ -71,6 +75,7 @@ impl MiddlewareLayer for AuthBasic {
71
75
  let mut parts = decoded_str.splitn(2, ':');
72
76
  let username = parts.next().unwrap_or("");
73
77
  let password = parts.next().unwrap_or("");
78
+
74
79
  match self.credential_pairs.get(username) {
75
80
  Some(expected_password_hash) => {
76
81
  match verify_password_hash(password, expected_password_hash) {
@@ -78,7 +83,10 @@ impl MiddlewareLayer for AuthBasic {
78
83
  _ => Ok(Either::Right(self.basic_auth_failed_response())),
79
84
  }
80
85
  }
81
- None => Ok(Either::Right(self.basic_auth_failed_response())),
86
+ None => {
87
+ debug!(target: "middleware::auth_basic", "Basic auth failed. Username {} not found", username);
88
+ Ok(Either::Right(self.basic_auth_failed_response()))
89
+ }
82
90
  }
83
91
  }
84
92
  }
@@ -18,7 +18,7 @@ use std::{
18
18
  collections::{HashMap, HashSet},
19
19
  sync::OnceLock,
20
20
  };
21
- use tracing::error;
21
+ use tracing::debug;
22
22
 
23
23
  #[derive(Debug, Clone, Deserialize)]
24
24
  pub struct AuthJwt {
@@ -32,6 +32,10 @@ pub struct AuthJwt {
32
32
  pub audiences: Option<HashSet<String>>,
33
33
  pub subjects: Option<HashSet<String>>,
34
34
  pub issuers: Option<HashSet<String>>,
35
+ #[serde(skip_deserializing)]
36
+ pub audience_vec: OnceLock<Option<Vec<String>>>,
37
+ #[serde(skip_deserializing)]
38
+ pub issuer_vec: OnceLock<Option<Vec<String>>>,
35
39
  pub leeway: Option<u64>,
36
40
  #[serde(default = "unauthorized_error_response")]
37
41
  pub error_response: ErrorResponse,
@@ -91,7 +95,7 @@ impl JwtAlgorithm {
91
95
  /// Given a base64-encoded key string, decode and construct a jsonwebtoken::DecodingKey.
92
96
  pub fn key_from(&self, base64: &str) -> itsi_error::Result<DecodingKey> {
93
97
  match self {
94
- // For HMAC algorithms, use the secret directly.
98
+ // For HMAC algorithms, expect a base64 encoded secret.
95
99
  JwtAlgorithm::Hs256 | JwtAlgorithm::Hs384 | JwtAlgorithm::Hs512 => {
96
100
  Ok(DecodingKey::from_secret(
97
101
  &general_purpose::STANDARD
@@ -118,15 +122,16 @@ impl JwtAlgorithm {
118
122
 
119
123
  #[derive(Debug, Deserialize)]
120
124
  #[serde(untagged)]
125
+ #[allow(dead_code)]
121
126
  enum Audience {
122
127
  Single(String),
123
128
  Multiple(Vec<String>),
124
129
  }
125
130
 
126
131
  #[derive(Debug, Deserialize)]
132
+ #[allow(dead_code)]
127
133
  struct Claims {
128
134
  // Here we assume the token includes an expiration.
129
- #[allow(dead_code)]
130
135
  exp: usize,
131
136
  // The audience claim may be a single string or an array.
132
137
  aud: Option<Audience>,
@@ -137,6 +142,11 @@ struct Claims {
137
142
  #[async_trait]
138
143
  impl MiddlewareLayer for AuthJwt {
139
144
  async fn initialize(&self) -> Result<()> {
145
+ debug!(
146
+ target: "middleware::auth_jwt",
147
+ "Instantiating auth_jwt with {} verifiers", self.verifiers.len()
148
+ );
149
+
140
150
  let keys: HashMap<JwtAlgorithm, Vec<DecodingKey>> = self
141
151
  .verifiers
142
152
  .iter()
@@ -145,24 +155,54 @@ impl MiddlewareLayer for AuthJwt {
145
155
  let keys: itsi_error::Result<Vec<DecodingKey>> = key_strings
146
156
  .iter()
147
157
  .map(|key_string| algorithm.key_from(key_string))
158
+ .inspect(|key_result| {
159
+ if key_result.is_err() {
160
+ debug!(
161
+ target: "middleware::auth_jwt",
162
+ "Failed to load key for algorithm {:?}", algorithm
163
+ )
164
+ } else {
165
+ debug!(
166
+ target: "middleware::auth_jwt",
167
+ "Loaded key for algorithm {:?}", algorithm
168
+ )
169
+ }
170
+ })
148
171
  .collect();
149
172
  keys.map(|keys| (algo, keys))
150
173
  })
151
174
  .collect::<itsi_error::Result<HashMap<JwtAlgorithm, Vec<DecodingKey>>>>()?;
175
+
152
176
  self.keys
153
177
  .set(keys)
154
178
  .map_err(|_| ItsiError::new("Failed to set keys"))?;
179
+
180
+ if let Some(audiences) = self.audiences.as_ref() {
181
+ self.audience_vec
182
+ .set(Some(audiences.iter().cloned().collect::<Vec<_>>()))
183
+ .ok();
184
+ }
185
+ if let Some(issuers) = self.issuers.as_ref() {
186
+ self.issuer_vec
187
+ .set(Some(issuers.iter().cloned().collect::<Vec<_>>()))
188
+ .ok();
189
+ }
155
190
  Ok(())
156
191
  }
157
192
 
158
193
  async fn before(
159
194
  &self,
160
195
  req: HttpRequest,
161
- _context: &mut HttpRequestContext,
196
+ _: &mut HttpRequestContext,
162
197
  ) -> Result<Either<HttpRequest, HttpResponse>> {
163
198
  // Retrieve the JWT token from either a header or a query parameter.
164
199
  let token_str = match &self.token_source {
165
200
  TokenSource::Header { name, prefix } => {
201
+ debug!(
202
+ target: "middleware::auth_jwt",
203
+ "Extracting JWT from header: {}, prefix: {:?}",
204
+ name, prefix
205
+ );
166
206
  if let Some(header) = req.header(name) {
167
207
  if let Some(prefix) = prefix {
168
208
  Some(header.strip_prefix(prefix).unwrap_or("").trim_ascii())
@@ -173,10 +213,21 @@ impl MiddlewareLayer for AuthJwt {
173
213
  None
174
214
  }
175
215
  }
176
- TokenSource::Query(query_name) => req.query_param(query_name),
216
+ TokenSource::Query(query_name) => {
217
+ debug!(
218
+ target: "middleware::auth_jwt",
219
+ "Extracting JWT from query parameter: {}",
220
+ query_name
221
+ );
222
+ req.query_param(query_name)
223
+ }
177
224
  };
178
225
 
179
226
  if token_str.is_none() {
227
+ debug!(
228
+ target: "middleware::auth_jwt",
229
+ "No JWT found in headers or query parameters"
230
+ );
180
231
  return Ok(Either::Right(
181
232
  self.error_response
182
233
  .to_http_response(req.accept().into())
@@ -184,10 +235,24 @@ impl MiddlewareLayer for AuthJwt {
184
235
  ));
185
236
  }
186
237
  let token_str = token_str.unwrap();
187
- let header =
188
- decode_header(token_str).map_err(|_| ItsiError::new("Invalid token header"))?;
238
+ let header = match decode_header(token_str) {
239
+ Ok(header) => header,
240
+ Err(_) => {
241
+ debug!(target: "middleware::auth_jwt", "JWT decoding failed");
242
+ return Ok(Either::Right(
243
+ self.error_response
244
+ .to_http_response(req.accept().into())
245
+ .await,
246
+ ));
247
+ }
248
+ };
249
+
189
250
  let alg: JwtAlgorithm = header.alg.into();
190
251
 
252
+ debug!(
253
+ target: "middleware::auth_jwt",
254
+ "Matched algorithm {:?}", alg
255
+ );
191
256
  if !self.verifiers.contains_key(&alg) {
192
257
  return Ok(Either::Right(
193
258
  self.error_response
@@ -216,15 +281,32 @@ impl MiddlewareLayer for AuthJwt {
216
281
  validation.leeway = leeway;
217
282
  }
218
283
 
284
+ if let Some(Some(auds)) = &self.audience_vec.get() {
285
+ validation.set_audience(auds);
286
+ validation.required_spec_claims.insert("aud".to_owned());
287
+ } else {
288
+ validation.validate_aud = false;
289
+ }
290
+
291
+ if let Some(Some(issuers)) = &self.issuer_vec.get() {
292
+ validation.set_issuer(issuers);
293
+ validation.required_spec_claims.insert("iss".to_owned());
294
+ }
295
+
296
+ if self.subjects.is_some() {
297
+ validation.required_spec_claims.insert("sub".to_owned());
298
+ }
299
+
219
300
  let token_data: Option<TokenData<Claims>> =
220
301
  keys.iter()
221
302
  .find_map(|key| match decode::<Claims>(token_str, key, &validation) {
222
303
  Ok(data) => Some(data),
223
304
  Err(e) => {
224
- error!("Token validation failed: {:?}", e);
305
+ debug!("Token validation failed: {:?}", e);
225
306
  None
226
307
  }
227
308
  });
309
+
228
310
  let token_data = if let Some(data) = token_data {
229
311
  data
230
312
  } else {
@@ -237,38 +319,14 @@ impl MiddlewareLayer for AuthJwt {
237
319
 
238
320
  let claims = token_data.claims;
239
321
 
240
- if let Some(expected_audiences) = &self.audiences {
241
- if let Some(aud) = &claims.aud {
242
- let token_auds: HashSet<String> = match aud {
243
- Audience::Single(s) => [s.clone()].into_iter().collect(),
244
- Audience::Multiple(v) => v.iter().cloned().collect(),
245
- };
246
- if expected_audiences.is_disjoint(&token_auds) {
247
- return Ok(Either::Right(
248
- self.error_response
249
- .to_http_response(req.accept().into())
250
- .await,
251
- ));
252
- }
253
- }
254
- }
255
-
256
322
  if let Some(expected_subjects) = &self.subjects {
257
323
  if let Some(sub) = &claims.sub {
258
324
  if !expected_subjects.contains(sub) {
259
- return Ok(Either::Right(
260
- self.error_response
261
- .to_http_response(req.accept().into())
262
- .await,
263
- ));
264
- }
265
- }
266
- }
267
-
268
- // Verify expected issuer.
269
- if let Some(expected_issuers) = &self.issuers {
270
- if let Some(iss) = &claims.iss {
271
- if !expected_issuers.contains(iss) {
325
+ debug!(
326
+ target: "middleware::auth_jwt",
327
+ "SUB check failed, token_sub: {:?}, expected_subjects: {:?}",
328
+ sub, expected_subjects
329
+ );
272
330
  return Ok(Either::Right(
273
331
  self.error_response
274
332
  .to_http_response(req.accept().into())
@@ -8,8 +8,9 @@ use http::{HeaderName, HeaderValue};
8
8
  use magnus::error::Result;
9
9
  use serde::Deserialize;
10
10
  use std::{collections::HashMap, sync::OnceLock};
11
+ use tracing::debug;
11
12
 
12
- #[derive(Debug, Clone, Deserialize)]
13
+ #[derive(Debug, Deserialize)]
13
14
  pub struct CacheControl {
14
15
  #[serde(default)]
15
16
  pub max_age: Option<u64>,
@@ -87,6 +88,7 @@ impl MiddlewareLayer for CacheControl {
87
88
  // Set the Cache-Control header if we have directives
88
89
  if !directives.is_empty() {
89
90
  let cache_control_value = directives.join(", ");
91
+ debug!(target: "middleware::cache_control", "Built cache-control directive {}", cache_control_value);
90
92
  self.cache_control_str.set(cache_control_value).unwrap();
91
93
  }
92
94
 
@@ -97,20 +99,27 @@ impl MiddlewareLayer for CacheControl {
97
99
  // Skip for statuses where caching doesn't make sense
98
100
  let status = resp.status().as_u16();
99
101
  if matches!(status, 401 | 403 | 500..=599) {
102
+ debug!(target: "middleware::cache_control", "Skipping cache-control for status {}", status);
100
103
  return resp;
101
104
  }
102
105
 
103
106
  // Set the Cache-Control header if we have directives
104
107
  if let Some(cache_control_value) = self.cache_control_str.get() {
105
108
  if let Ok(value) = HeaderValue::from_str(cache_control_value) {
109
+ debug!(target: "middleware::cache_control", "Setting cache-control header to {}", cache_control_value);
106
110
  resp.headers_mut().insert("Cache-Control", value);
111
+ } else {
112
+ debug!(target: "middleware::cache_control", "Failed to parse cache-control value {}", cache_control_value);
107
113
  }
114
+ } else {
115
+ debug!(target: "middleware::cache_control", "No cache-control value provided");
108
116
  }
109
117
 
110
118
  // Set Expires header based on max-age if present
111
119
  if let Some(max_age) = self.max_age {
112
120
  // Set the Expires header based on max-age
113
121
  // Use a helper to format the HTTP date correctly
122
+ debug!(target: "middleware::cache_control", "Setting expires header to {}", max_age);
114
123
  let expires = chrono::Utc::now() + chrono::Duration::seconds(max_age as i64);
115
124
  let expires_str = expires.format("%a, %d %b %Y %H:%M:%S GMT").to_string();
116
125
  if let Ok(value) = HeaderValue::from_str(&expires_str) {
@@ -118,7 +127,6 @@ impl MiddlewareLayer for CacheControl {
118
127
  }
119
128
  }
120
129
 
121
- // Set Vary header
122
130
  if !self.vary.is_empty() {
123
131
  let vary_value = self.vary.join(", ");
124
132
  if let Ok(value) = HeaderValue::from_str(&vary_value) {
@@ -130,6 +138,7 @@ impl MiddlewareLayer for CacheControl {
130
138
  for (name, value) in &self.additional_headers {
131
139
  if let Ok(header_value) = HeaderValue::from_str(value) {
132
140
  if let Ok(header_name) = name.parse::<HeaderName>() {
141
+ debug!(target: "middleware::cache_control", "Setting custom header {} to {:?}", header_name, header_value);
133
142
  resp.headers_mut().insert(header_name, header_value);
134
143
  }
135
144
  }