itsi 0.1.6 → 0.1.8

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 (239) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +49 -0
  3. data/Rakefile +20 -0
  4. data/crates/itsi_error/src/from.rs +26 -29
  5. data/crates/itsi_error/src/lib.rs +1 -1
  6. data/crates/itsi_server/Cargo.lock +2956 -0
  7. data/crates/itsi_server/Cargo.toml +2 -1
  8. data/crates/itsi_server/src/env.rs +43 -0
  9. data/crates/itsi_server/src/lib.rs +1 -0
  10. data/crates/itsi_server/src/request/itsi_request.rs +7 -7
  11. data/crates/itsi_server/src/server/bind.rs +4 -3
  12. data/crates/itsi_server/src/server/itsi_server.rs +1 -8
  13. data/crates/itsi_server/src/server/listener.rs +98 -107
  14. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +22 -12
  15. data/crates/itsi_server/src/server/tls/locked_dir_cache.rs +3 -3
  16. data/crates/itsi_server/src/server/tls.rs +83 -44
  17. data/gems/scheduler/ext/itsi_error/src/from.rs +26 -29
  18. data/gems/scheduler/ext/itsi_error/src/lib.rs +1 -1
  19. data/gems/scheduler/ext/itsi_server/Cargo.lock +2956 -0
  20. data/gems/scheduler/ext/itsi_server/Cargo.toml +2 -1
  21. data/gems/scheduler/ext/itsi_server/src/env.rs +43 -0
  22. data/gems/scheduler/ext/itsi_server/src/lib.rs +1 -0
  23. data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +7 -7
  24. data/gems/scheduler/ext/itsi_server/src/server/bind.rs +4 -3
  25. data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +1 -8
  26. data/gems/scheduler/ext/itsi_server/src/server/listener.rs +98 -107
  27. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +22 -12
  28. data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +3 -3
  29. data/gems/scheduler/ext/itsi_server/src/server/tls.rs +83 -44
  30. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  31. data/gems/server/Cargo.lock +2917 -0
  32. data/gems/server/Cargo.toml +7 -0
  33. data/gems/server/ext/itsi_error/src/from.rs +26 -29
  34. data/gems/server/ext/itsi_error/src/lib.rs +1 -1
  35. data/gems/server/ext/itsi_server/Cargo.lock +2956 -0
  36. data/gems/server/ext/itsi_server/Cargo.toml +2 -1
  37. data/gems/server/ext/itsi_server/src/env.rs +43 -0
  38. data/gems/server/ext/itsi_server/src/lib.rs +1 -0
  39. data/gems/server/ext/itsi_server/src/request/itsi_request.rs +7 -7
  40. data/gems/server/ext/itsi_server/src/server/bind.rs +4 -3
  41. data/gems/server/ext/itsi_server/src/server/itsi_server.rs +1 -8
  42. data/gems/server/ext/itsi_server/src/server/listener.rs +98 -107
  43. data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +22 -12
  44. data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +3 -3
  45. data/gems/server/ext/itsi_server/src/server/tls.rs +83 -44
  46. data/gems/server/lib/itsi/index.html.erb +91 -0
  47. data/gems/server/lib/itsi/server/scheduler_mode.rb +1 -1
  48. data/gems/server/lib/itsi/server/version.rb +1 -1
  49. data/gems/server/lib/itsi/server.rb +22 -2
  50. data/lib/itsi/version.rb +1 -1
  51. data/sandbox/deploy/main.tf +237 -0
  52. data/sandbox/deploy/outputs.tf +4 -0
  53. data/sandbox/deploy/vars.tf +11 -0
  54. data/sandbox/falcon_benchmark/Gemfile +10 -0
  55. data/sandbox/falcon_benchmark/Gemfile.lock +140 -0
  56. data/sandbox/falcon_benchmark/config.ru +54 -0
  57. data/sandbox/itsi_sandbox_async/Gemfile +10 -0
  58. data/sandbox/itsi_sandbox_async/Gemfile.lock +69 -0
  59. data/sandbox/itsi_sandbox_async/config.ru +10 -0
  60. data/sandbox/itsi_sandbox_hanami/.env +2 -0
  61. data/sandbox/itsi_sandbox_hanami/.gitignore +6 -0
  62. data/sandbox/itsi_sandbox_hanami/.rspec +1 -0
  63. data/sandbox/itsi_sandbox_hanami/Gemfile +49 -0
  64. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +440 -0
  65. data/sandbox/itsi_sandbox_hanami/Guardfile +9 -0
  66. data/sandbox/itsi_sandbox_hanami/Procfile.dev +2 -0
  67. data/sandbox/itsi_sandbox_hanami/README.md +1 -0
  68. data/sandbox/itsi_sandbox_hanami/Rakefile +3 -0
  69. data/sandbox/itsi_sandbox_hanami/app/action.rb +12 -0
  70. data/sandbox/itsi_sandbox_hanami/app/actions/.keep +0 -0
  71. data/sandbox/itsi_sandbox_hanami/app/assets/css/app.css +5 -0
  72. data/sandbox/itsi_sandbox_hanami/app/assets/images/favicon.ico +0 -0
  73. data/sandbox/itsi_sandbox_hanami/app/assets/js/app.js +1 -0
  74. data/sandbox/itsi_sandbox_hanami/app/db/relation.rb +10 -0
  75. data/sandbox/itsi_sandbox_hanami/app/db/repo.rb +10 -0
  76. data/sandbox/itsi_sandbox_hanami/app/db/struct.rb +10 -0
  77. data/sandbox/itsi_sandbox_hanami/app/operation.rb +9 -0
  78. data/sandbox/itsi_sandbox_hanami/app/relations/.keep +0 -0
  79. data/sandbox/itsi_sandbox_hanami/app/repos/.keep +0 -0
  80. data/sandbox/itsi_sandbox_hanami/app/structs/.keep +0 -0
  81. data/sandbox/itsi_sandbox_hanami/app/templates/layouts/app.html.erb +14 -0
  82. data/sandbox/itsi_sandbox_hanami/app/view.rb +9 -0
  83. data/sandbox/itsi_sandbox_hanami/app/views/helpers.rb +10 -0
  84. data/sandbox/itsi_sandbox_hanami/bin/dev +8 -0
  85. data/sandbox/itsi_sandbox_hanami/config/app.rb +8 -0
  86. data/sandbox/itsi_sandbox_hanami/config/assets.js +16 -0
  87. data/sandbox/itsi_sandbox_hanami/config/db/migrate/.keep +0 -0
  88. data/sandbox/itsi_sandbox_hanami/config/db/seeds.rb +15 -0
  89. data/sandbox/itsi_sandbox_hanami/config/puma.rb +47 -0
  90. data/sandbox/itsi_sandbox_hanami/config/routes.rb +7 -0
  91. data/sandbox/itsi_sandbox_hanami/config/settings.rb +9 -0
  92. data/sandbox/itsi_sandbox_hanami/config.ru +5 -0
  93. data/sandbox/itsi_sandbox_hanami/db/.keep +0 -0
  94. data/sandbox/itsi_sandbox_hanami/lib/itsi_hanami/types.rb +11 -0
  95. data/sandbox/itsi_sandbox_hanami/lib/tasks/.keep +0 -0
  96. data/sandbox/itsi_sandbox_hanami/package-lock.json +946 -0
  97. data/sandbox/itsi_sandbox_hanami/package.json +8 -0
  98. data/sandbox/itsi_sandbox_hanami/spec/requests/root_spec.rb +11 -0
  99. data/sandbox/itsi_sandbox_hanami/spec/spec_helper.rb +9 -0
  100. data/sandbox/itsi_sandbox_hanami/spec/support/db/cleaning.rb +42 -0
  101. data/sandbox/itsi_sandbox_hanami/spec/support/db.rb +10 -0
  102. data/sandbox/itsi_sandbox_hanami/spec/support/features.rb +5 -0
  103. data/sandbox/itsi_sandbox_hanami/spec/support/operations.rb +8 -0
  104. data/sandbox/itsi_sandbox_hanami/spec/support/requests.rb +13 -0
  105. data/sandbox/itsi_sandbox_hanami/spec/support/rspec.rb +61 -0
  106. data/sandbox/itsi_sandbox_rack/Gemfile +17 -0
  107. data/sandbox/itsi_sandbox_rack/Gemfile.lock +153 -0
  108. data/sandbox/itsi_sandbox_rack/config.ru +18 -0
  109. data/sandbox/itsi_sandbox_rack_lint/Gemfile +7 -0
  110. data/sandbox/itsi_sandbox_rack_lint/Gemfile.lock +27 -0
  111. data/sandbox/itsi_sandbox_rack_lint/config.ru +3 -0
  112. data/sandbox/itsi_sandbox_rails/.dockerignore +51 -0
  113. data/sandbox/itsi_sandbox_rails/.gitattributes +9 -0
  114. data/sandbox/itsi_sandbox_rails/.github/dependabot.yml +12 -0
  115. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +90 -0
  116. data/sandbox/itsi_sandbox_rails/.gitignore +34 -0
  117. data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +3 -0
  118. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +3 -0
  119. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +14 -0
  120. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +3 -0
  121. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +3 -0
  122. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +51 -0
  123. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +47 -0
  124. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +109 -0
  125. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +3 -0
  126. data/sandbox/itsi_sandbox_rails/.kamal/secrets +17 -0
  127. data/sandbox/itsi_sandbox_rails/.rubocop.yml +8 -0
  128. data/sandbox/itsi_sandbox_rails/.ruby-version +1 -0
  129. data/sandbox/itsi_sandbox_rails/Dockerfile +72 -0
  130. data/sandbox/itsi_sandbox_rails/Gemfile +72 -0
  131. data/sandbox/itsi_sandbox_rails/Gemfile.lock +480 -0
  132. data/sandbox/itsi_sandbox_rails/README.md +24 -0
  133. data/sandbox/itsi_sandbox_rails/Rakefile +6 -0
  134. data/sandbox/itsi_sandbox_rails/app/assets/images/.keep +0 -0
  135. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +10 -0
  136. data/sandbox/itsi_sandbox_rails/app/controllers/application_controller.rb +4 -0
  137. data/sandbox/itsi_sandbox_rails/app/controllers/concerns/.keep +0 -0
  138. data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +51 -0
  139. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +41 -0
  140. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +32 -0
  141. data/sandbox/itsi_sandbox_rails/app/helpers/application_helper.rb +2 -0
  142. data/sandbox/itsi_sandbox_rails/app/javascript/application.js +3 -0
  143. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/application.js +9 -0
  144. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/hello_controller.js +7 -0
  145. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/index.js +4 -0
  146. data/sandbox/itsi_sandbox_rails/app/jobs/application_job.rb +7 -0
  147. data/sandbox/itsi_sandbox_rails/app/mailers/application_mailer.rb +4 -0
  148. data/sandbox/itsi_sandbox_rails/app/models/application_record.rb +3 -0
  149. data/sandbox/itsi_sandbox_rails/app/models/concerns/.keep +0 -0
  150. data/sandbox/itsi_sandbox_rails/app/models/post.rb +2 -0
  151. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +28 -0
  152. data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.html.erb +13 -0
  153. data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.text.erb +1 -0
  154. data/sandbox/itsi_sandbox_rails/app/views/pwa/manifest.json.erb +22 -0
  155. data/sandbox/itsi_sandbox_rails/app/views/pwa/service-worker.js +26 -0
  156. data/sandbox/itsi_sandbox_rails/bin/brakeman +7 -0
  157. data/sandbox/itsi_sandbox_rails/bin/bundle +109 -0
  158. data/sandbox/itsi_sandbox_rails/bin/dev +2 -0
  159. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +14 -0
  160. data/sandbox/itsi_sandbox_rails/bin/importmap +4 -0
  161. data/sandbox/itsi_sandbox_rails/bin/jobs +6 -0
  162. data/sandbox/itsi_sandbox_rails/bin/kamal +27 -0
  163. data/sandbox/itsi_sandbox_rails/bin/rails +4 -0
  164. data/sandbox/itsi_sandbox_rails/bin/rake +4 -0
  165. data/sandbox/itsi_sandbox_rails/bin/rubocop +8 -0
  166. data/sandbox/itsi_sandbox_rails/bin/setup +34 -0
  167. data/sandbox/itsi_sandbox_rails/bin/thrust +5 -0
  168. data/sandbox/itsi_sandbox_rails/config/application.rb +61 -0
  169. data/sandbox/itsi_sandbox_rails/config/boot.rb +4 -0
  170. data/sandbox/itsi_sandbox_rails/config/cable.yml +17 -0
  171. data/sandbox/itsi_sandbox_rails/config/cache.yml +16 -0
  172. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -0
  173. data/sandbox/itsi_sandbox_rails/config/database.yml +40 -0
  174. data/sandbox/itsi_sandbox_rails/config/deploy.yml +116 -0
  175. data/sandbox/itsi_sandbox_rails/config/environment.rb +5 -0
  176. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +72 -0
  177. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +90 -0
  178. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +53 -0
  179. data/sandbox/itsi_sandbox_rails/config/importmap.rb +7 -0
  180. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +7 -0
  181. data/sandbox/itsi_sandbox_rails/config/initializers/content_security_policy.rb +25 -0
  182. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +8 -0
  183. data/sandbox/itsi_sandbox_rails/config/initializers/inflections.rb +16 -0
  184. data/sandbox/itsi_sandbox_rails/config/locales/en.yml +31 -0
  185. data/sandbox/itsi_sandbox_rails/config/puma.rb +41 -0
  186. data/sandbox/itsi_sandbox_rails/config/queue.yml +18 -0
  187. data/sandbox/itsi_sandbox_rails/config/recurring.yml +10 -0
  188. data/sandbox/itsi_sandbox_rails/config/routes.rb +21 -0
  189. data/sandbox/itsi_sandbox_rails/config/storage.yml +34 -0
  190. data/sandbox/itsi_sandbox_rails/config.ru +7 -0
  191. data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +11 -0
  192. data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +14 -0
  193. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +10 -0
  194. data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +129 -0
  195. data/sandbox/itsi_sandbox_rails/db/schema.rb +23 -0
  196. data/sandbox/itsi_sandbox_rails/db/seeds.rb +9 -0
  197. data/sandbox/itsi_sandbox_rails/lib/tasks/.keep +0 -0
  198. data/sandbox/itsi_sandbox_rails/log/.keep +0 -0
  199. data/sandbox/itsi_sandbox_rails/public/400.html +114 -0
  200. data/sandbox/itsi_sandbox_rails/public/404.html +114 -0
  201. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +114 -0
  202. data/sandbox/itsi_sandbox_rails/public/422.html +114 -0
  203. data/sandbox/itsi_sandbox_rails/public/500.html +114 -0
  204. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  205. data/sandbox/itsi_sandbox_rails/public/icon.svg +3 -0
  206. data/sandbox/itsi_sandbox_rails/public/robots.txt +1 -0
  207. data/sandbox/itsi_sandbox_rails/script/.keep +0 -0
  208. data/sandbox/itsi_sandbox_rails/storage/.keep +0 -0
  209. data/sandbox/itsi_sandbox_rails/test/application_system_test_case.rb +5 -0
  210. data/sandbox/itsi_sandbox_rails/test/controllers/.keep +0 -0
  211. data/sandbox/itsi_sandbox_rails/test/fixtures/files/.keep +0 -0
  212. data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +9 -0
  213. data/sandbox/itsi_sandbox_rails/test/helpers/.keep +0 -0
  214. data/sandbox/itsi_sandbox_rails/test/integration/.keep +0 -0
  215. data/sandbox/itsi_sandbox_rails/test/mailers/.keep +0 -0
  216. data/sandbox/itsi_sandbox_rails/test/models/.keep +0 -0
  217. data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +7 -0
  218. data/sandbox/itsi_sandbox_rails/test/system/.keep +0 -0
  219. data/sandbox/itsi_sandbox_rails/test/test_helper.rb +15 -0
  220. data/sandbox/itsi_sandbox_rails/tmp/.keep +0 -0
  221. data/sandbox/itsi_sandbox_rails/tmp/pids/.keep +0 -0
  222. data/sandbox/itsi_sandbox_rails/tmp/storage/.keep +0 -0
  223. data/sandbox/itsi_sandbox_rails/vendor/.keep +0 -0
  224. data/sandbox/itsi_sandbox_rails/vendor/javascript/.keep +0 -0
  225. data/sandbox/itsi_sandbox_roda/Gemfile +5 -0
  226. data/sandbox/itsi_sandbox_roda/Gemfile.lock +44 -0
  227. data/sandbox/itsi_sandbox_roda/config.ru +39 -0
  228. data/sandbox/itsi_sinatra/Gemfile +9 -0
  229. data/sandbox/itsi_sinatra/Gemfile.lock +81 -0
  230. data/sandbox/itsi_sinatra/app.rb +9 -0
  231. data/sandbox/pebble/docker-compose.yml +11 -0
  232. data/tasks.txt +10 -4
  233. metadata +196 -12
  234. data/crates/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  235. data/crates/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
  236. data/gems/scheduler/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  237. data/gems/scheduler/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
  238. data/gems/server/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  239. data/gems/server/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
@@ -2,7 +2,9 @@ use base64::{engine::general_purpose, Engine as _};
2
2
  use itsi_error::Result;
3
3
  use itsi_tracing::info;
4
4
  use locked_dir_cache::LockedDirCache;
5
- use rcgen::{CertificateParams, DnType, KeyPair, SanType};
5
+ use rcgen::{
6
+ generate_simple_self_signed, CertificateParams, CertifiedKey, DnType, KeyPair, SanType,
7
+ };
6
8
  use rustls::{
7
9
  pki_types::{CertificateDer, PrivateKeyDer},
8
10
  ClientConfig, RootCertStore,
@@ -10,16 +12,19 @@ use rustls::{
10
12
  use rustls_pemfile::{certs, pkcs8_private_keys};
11
13
  use std::{
12
14
  collections::HashMap,
13
- env, fs,
15
+ fs,
14
16
  io::{BufReader, Error},
15
17
  sync::Arc,
16
18
  };
17
19
  use tokio::sync::Mutex;
18
20
  use tokio_rustls::{rustls::ServerConfig, TlsAcceptor};
19
21
  use tokio_rustls_acme::{AcmeAcceptor, AcmeConfig, AcmeState};
22
+
23
+ use crate::env::{
24
+ ITSI_ACME_CACHE_DIR, ITSI_ACME_CA_PEM_PATH, ITSI_ACME_CONTACT_EMAIL, ITSI_ACME_DIRECTORY_URL,
25
+ ITSI_LOCAL_CA_DIR,
26
+ };
20
27
  mod locked_dir_cache;
21
- const ITS_CA_CERT: &str = include_str!("./itsi_ca/itsi_ca.crt");
22
- const ITS_CA_KEY: &str = include_str!("./itsi_ca/itsi_ca.key");
23
28
 
24
29
  #[derive(Clone)]
25
30
  pub enum ItsiTlsAcceptor {
@@ -31,11 +36,12 @@ pub enum ItsiTlsAcceptor {
31
36
  ),
32
37
  }
33
38
 
34
- // Generates a TLS configuration based on either :
35
- // * Input "cert" and "key" options (either paths or Base64-encoded strings) or
36
- // * Performs automatic certificate generation/retrieval. Generated certs use an internal self-signed Isti CA.
37
- // If a non-local host or optional domain parameter is provided,
38
- // an automated certificate will attempt to be fetched using let's encrypt.
39
+ /// Generates a TLS configuration based on either :
40
+ /// * Input "cert" and "key" options (either paths or Base64-encoded strings) or
41
+ /// * Performs automatic certificate generation/retrieval. Generated certs use an internal self-signed Isti CA.
42
+ ///
43
+ /// If a non-local host or optional domain parameter is provided,
44
+ /// an automated certificate will attempt to be fetched using let's encrypt.
39
45
  pub fn configure_tls(
40
46
  host: &str,
41
47
  query_params: &HashMap<String, String>,
@@ -44,17 +50,27 @@ pub fn configure_tls(
44
50
  .get("domains")
45
51
  .map(|v| v.split(',').map(String::from).collect::<Vec<_>>());
46
52
 
47
- if query_params.get("cert").is_none() || query_params.get("key").is_none() {
53
+ if query_params.get("cert").is_some_and(|c| c == "auto") {
48
54
  if let Some(domains) = domains {
49
- let directory_url = env::var("ACME_DIRECTORY_URL")
50
- .unwrap_or_else(|_| "https://acme-v02.api.letsencrypt.org/directory".to_string());
55
+ let directory_url = &*ITSI_ACME_DIRECTORY_URL;
51
56
  info!(
52
57
  domains = format!("{:?}", domains),
53
58
  directory_url, "Requesting acme cert"
54
59
  );
55
60
 
56
- let mut root_cert_store = RootCertStore::empty();
57
- if let Ok(ca_pem_path) = env::var("ITSI_ACME_CA_PEM_PATH") {
61
+ let acme_config = AcmeConfig::new(domains)
62
+ .contact([format!("mailto:{}", (*ITSI_ACME_CONTACT_EMAIL).as_ref().map_err(|_| {
63
+ itsi_error::ItsiError::ArgumentError(
64
+ "ITSI_ACME_CONTACT_EMAIL must be set before you can auto-generate production certificates"
65
+ .to_string(),
66
+ )
67
+ })?)])
68
+ .cache(LockedDirCache::new(&*ITSI_ACME_CACHE_DIR))
69
+ .directory(directory_url);
70
+
71
+ let acme_state = if let Ok(ca_pem_path) = &*ITSI_ACME_CA_PEM_PATH {
72
+ let mut root_cert_store = RootCertStore::empty();
73
+
58
74
  let ca_pem = fs::read(ca_pem_path).expect("failed to read CA pem file");
59
75
  let mut ca_reader = BufReader::new(&ca_pem[..]);
60
76
  let der_certs: Vec<CertificateDer> = certs(&mut ca_reader)
@@ -66,31 +82,23 @@ pub fn configure_tls(
66
82
  ))
67
83
  })?;
68
84
  root_cert_store.add_parsable_certificates(der_certs);
69
- }
70
85
 
71
- let client_config = ClientConfig::builder()
72
- .with_root_certificates(root_cert_store)
73
- .with_no_client_auth();
74
-
75
- let contact_email = env::var("ITSI_ACME_CONTACT_EMAIL").map_err(|_| {
76
- itsi_error::ItsiError::ArgumentError(
77
- "ITSI_ACME_CONTACT_EMAIL must be set before you can auto-generate production certificates"
78
- .to_string(),
79
- )
80
- })?;
81
-
82
- let cache_dir = env::var("ITSI_ACME_CACHE_DIR")
83
- .unwrap_or_else(|_| "./.rustls_acme_cache".to_string());
84
-
85
- let acme_state = AcmeConfig::new(domains)
86
- .contact([format!("mailto:{}", contact_email)])
87
- .cache(LockedDirCache::new(cache_dir))
88
- .directory(directory_url)
89
- .client_tls_config(Arc::new(client_config))
90
- .state();
91
- let rustls_config = ServerConfig::builder()
86
+ let client_config = ClientConfig::builder()
87
+ .with_root_certificates(root_cert_store)
88
+ .with_no_client_auth();
89
+ acme_config
90
+ .client_tls_config(Arc::new(client_config))
91
+ .state()
92
+ } else {
93
+ acme_config.state()
94
+ };
95
+
96
+ let mut rustls_config = ServerConfig::builder()
92
97
  .with_no_client_auth()
93
98
  .with_cert_resolver(acme_state.resolver());
99
+
100
+ rustls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
101
+
94
102
  let acceptor = acme_state.acceptor();
95
103
  return Ok(ItsiTlsAcceptor::Automatic(
96
104
  acceptor,
@@ -107,7 +115,7 @@ pub fn configure_tls(
107
115
  let key = load_private_key(key_path);
108
116
  (certs, key)
109
117
  } else {
110
- generate_ca_signed_cert(vec![host.to_owned()])?
118
+ generate_ca_signed_cert(domains.unwrap_or(vec![host.to_owned()]))?
111
119
  };
112
120
 
113
121
  let mut config = ServerConfig::builder()
@@ -178,10 +186,19 @@ pub fn load_private_key(path: &str) -> PrivateKeyDer<'static> {
178
186
  pub fn generate_ca_signed_cert(
179
187
  domains: Vec<String>,
180
188
  ) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
181
- info!("Generating New Itsi CA - Self signed Certificate. Use `itsi ca export` to export the CA certificate for import into your local trust store.");
189
+ info!(
190
+ domains = format!("{}", domains.join(", ")),
191
+ "Self signed cert",
192
+ );
193
+ info!(
194
+ "Add {} to your system's trusted cert store to resolve certificate errors.",
195
+ format!("{}/itsi_dev_ca.crt", ITSI_LOCAL_CA_DIR.to_str().unwrap())
196
+ );
197
+ info!("Dev CA path can be overridden by setting env var: `ITSI_LOCAL_CA_DIR`.");
198
+ let (ca_key_pem, ca_cert_pem) = get_or_create_local_dev_ca()?;
182
199
 
183
- let ca_kp = KeyPair::from_pem(ITS_CA_KEY).expect("Failed to load embedded CA key");
184
- let ca_cert = CertificateParams::from_ca_cert_pem(ITS_CA_CERT)
200
+ let ca_kp = KeyPair::from_pem(&ca_key_pem).expect("Failed to load CA key");
201
+ let ca_cert = CertificateParams::from_ca_cert_pem(&ca_cert_pem)
185
202
  .expect("Failed to parse embedded CA certificate")
186
203
  .self_signed(&ca_kp)
187
204
  .expect("Failed to self-sign embedded CA cert");
@@ -189,10 +206,6 @@ pub fn generate_ca_signed_cert(
189
206
  let ee_key = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256).unwrap();
190
207
  let mut ee_params = CertificateParams::default();
191
208
 
192
- info!(
193
- "Generated certificate will be valid for domains {:?}",
194
- domains
195
- );
196
209
  use std::net::IpAddr;
197
210
 
198
211
  ee_params.subject_alt_names = domains
@@ -221,3 +234,29 @@ pub fn generate_ca_signed_cert(
221
234
  PrivateKeyDer::try_from(ee_key.serialize_der()).unwrap(),
222
235
  ))
223
236
  }
237
+
238
+ fn get_or_create_local_dev_ca() -> Result<(String, String)> {
239
+ let ca_dir = &*ITSI_LOCAL_CA_DIR;
240
+ fs::create_dir_all(ca_dir)?;
241
+
242
+ let key_path = ca_dir.join("itsi_dev_ca.key");
243
+ let cert_path = ca_dir.join("itsi_dev_ca.crt");
244
+
245
+ if key_path.exists() && cert_path.exists() {
246
+ // Already have a local CA
247
+ let key_pem = fs::read_to_string(&key_path)?;
248
+ let cert_pem = fs::read_to_string(&cert_path)?;
249
+
250
+ Ok((key_pem, cert_pem))
251
+ } else {
252
+ let subject_alt_names = vec!["dev.itsi.fyi".to_string(), "localhost".to_string()];
253
+
254
+ let CertifiedKey { cert, key_pair } =
255
+ generate_simple_self_signed(subject_alt_names).unwrap();
256
+
257
+ fs::write(&key_path, key_pair.serialize_pem())?;
258
+ fs::write(&cert_path, cert.pem())?;
259
+
260
+ Ok((key_pair.serialize_pem(), cert.pem()))
261
+ }
262
+ }
@@ -1,5 +1,12 @@
1
+ use magnus::{
2
+ Error,
3
+ error::ErrorType,
4
+ exception::{self, arg_error, exception},
5
+ };
6
+ use nix::errno::Errno;
7
+
1
8
  use crate::ItsiError;
2
- use std::ffi::NulError;
9
+ use std::{ffi::NulError, io};
3
10
 
4
11
  pub static CLIENT_CONNECTION_CLOSED: &str = "Client disconnected";
5
12
 
@@ -9,14 +16,14 @@ impl From<httparse::Error> for ItsiError {
9
16
  }
10
17
  }
11
18
 
12
- impl From<nix::errno::Errno> for ItsiError {
13
- fn from(err: nix::errno::Errno) -> Self {
19
+ impl From<Errno> for ItsiError {
20
+ fn from(err: Errno) -> Self {
14
21
  ItsiError::ArgumentError(err.to_string())
15
22
  }
16
23
  }
17
24
 
18
- impl From<std::io::Error> for ItsiError {
19
- fn from(err: std::io::Error) -> Self {
25
+ impl From<io::Error> for ItsiError {
26
+ fn from(err: io::Error) -> Self {
20
27
  ItsiError::ArgumentError(err.to_string())
21
28
  }
22
29
  }
@@ -33,39 +40,29 @@ impl From<NulError> for ItsiError {
33
40
  }
34
41
  }
35
42
 
36
- impl From<magnus::Error> for ItsiError {
37
- fn from(err: magnus::Error) -> Self {
43
+ impl From<Error> for ItsiError {
44
+ fn from(err: Error) -> Self {
38
45
  match err.error_type() {
39
- magnus::error::ErrorType::Jump(tag) => ItsiError::Jump(tag.to_string()),
40
- magnus::error::ErrorType::Error(_exception_class, cow) => {
41
- ItsiError::ArgumentError(cow.to_string())
42
- }
43
- magnus::error::ErrorType::Exception(exception) => {
44
- ItsiError::ArgumentError(exception.to_string())
45
- }
46
+ ErrorType::Jump(tag) => ItsiError::Jump(tag.to_string()),
47
+ ErrorType::Error(_exception_class, cow) => ItsiError::ArgumentError(cow.to_string()),
48
+ ErrorType::Exception(exception) => ItsiError::ArgumentError(exception.to_string()),
46
49
  }
47
50
  }
48
51
  }
49
52
 
50
- impl From<ItsiError> for magnus::Error {
53
+ impl From<ItsiError> for Error {
51
54
  fn from(err: ItsiError) -> Self {
52
55
  match err {
53
- ItsiError::InvalidInput(msg) => magnus::Error::new(magnus::exception::arg_error(), msg),
54
- ItsiError::InternalServerError(msg) => {
55
- magnus::Error::new(magnus::exception::exception(), msg)
56
- }
57
- ItsiError::UnsupportedProtocol(msg) => {
58
- magnus::Error::new(magnus::exception::arg_error(), msg)
59
- }
60
- ItsiError::ArgumentError(msg) => {
61
- magnus::Error::new(magnus::exception::arg_error(), msg)
62
- }
63
- ItsiError::Jump(msg) => magnus::Error::new(magnus::exception::local_jump_error(), msg),
64
- ItsiError::Break() => magnus::Error::new(magnus::exception::interrupt(), "Break"),
56
+ ItsiError::InvalidInput(msg) => Error::new(arg_error(), msg),
57
+ ItsiError::InternalServerError(msg) => Error::new(exception(), msg),
58
+ ItsiError::UnsupportedProtocol(msg) => Error::new(arg_error(), msg),
59
+ ItsiError::ArgumentError(msg) => Error::new(arg_error(), msg),
60
+ ItsiError::Jump(msg) => Error::new(exception::local_jump_error(), msg),
61
+ ItsiError::Break() => Error::new(exception::interrupt(), "Break"),
65
62
  ItsiError::ClientConnectionClosed => {
66
- magnus::Error::new(magnus::exception::eof_error(), CLIENT_CONNECTION_CLOSED)
63
+ Error::new(exception::eof_error(), CLIENT_CONNECTION_CLOSED)
67
64
  }
68
- ItsiError::Pass() => magnus::Error::new(magnus::exception::interrupt(), "Pass"),
65
+ ItsiError::Pass() => Error::new(exception::interrupt(), "Pass"),
69
66
  }
70
67
  }
71
68
  }
@@ -3,7 +3,7 @@ use thiserror::Error;
3
3
 
4
4
  pub type Result<T> = std::result::Result<T, ItsiError>;
5
5
 
6
- #[derive(Error, Debug)]
6
+ #[derive(Error, Debug, Clone)]
7
7
  pub enum ItsiError {
8
8
  #[error("Invalid input {0}")]
9
9
  InvalidInput(String),