@hoanghainh/komagu 1.8.0 → 2.0.1

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 (210) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/assess/lsa/CHANGELOG.md +6 -0
  4. package/assess/lsa/VERSION +1 -1
  5. package/assess/lsa/adapters/build_adapters.py +16 -8
  6. package/assess/lsa/adapters/codex/README.md +1 -1
  7. package/assess/lsa/adapters/generic/README.md +1 -1
  8. package/assess/lsa/examples/eval-run-4/ground-truth.json +823 -0
  9. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/ai-run-stats.json +58 -0
  10. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/coverage.json +85 -0
  11. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/findings/priv-privilege-001.json +822 -0
  12. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/findings/priv-privilege-002.json +393 -0
  13. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/findings.json +4477 -0
  14. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/mass-assignment.candidates.json +232 -0
  15. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-001.json +425 -0
  16. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-002.json +333 -0
  17. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-003.json +400 -0
  18. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-004.json +403 -0
  19. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-005.json +398 -0
  20. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-006.json +63 -0
  21. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/score.json +120 -0
  22. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/ai-run-stats.json +55 -0
  23. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/coverage.json +50 -0
  24. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/findings/priv-privilege-001.json +613 -0
  25. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/findings/priv-privilege-002.json +287 -0
  26. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/findings.json +4870 -0
  27. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/mass-assignment.candidates.json +232 -0
  28. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-001.json +425 -0
  29. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-002.json +333 -0
  30. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-003.json +400 -0
  31. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-004.json +403 -0
  32. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-005.json +398 -0
  33. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-006.json +63 -0
  34. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/score.json +107 -0
  35. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/ai-run-stats.json +58 -0
  36. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/coverage.json +92 -0
  37. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/findings/priv-privilege-001.json +645 -0
  38. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/findings/priv-privilege-002.json +222 -0
  39. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/findings.json +4859 -0
  40. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/mass-assignment.candidates.json +232 -0
  41. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-001.json +425 -0
  42. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-002.json +333 -0
  43. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-003.json +400 -0
  44. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-004.json +403 -0
  45. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-005.json +398 -0
  46. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-006.json +63 -0
  47. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/score.json +121 -0
  48. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/coverage.json +111 -0
  49. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/findings/priv-privilege-001.json +6 -0
  50. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/findings/priv-privilege-002.json +344 -0
  51. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/findings.json +3544 -0
  52. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/mass-assignment.candidates.json +232 -0
  53. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-001.json +425 -0
  54. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-002.json +333 -0
  55. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-003.json +400 -0
  56. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-004.json +403 -0
  57. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-005.json +398 -0
  58. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-006.json +63 -0
  59. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/score.json +123 -0
  60. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/ai-run-stats.json +50 -0
  61. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/coverage.json +42 -0
  62. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings/priv-privilege-001.json +540 -0
  63. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings/priv-privilege-002.json +238 -0
  64. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings.json +4383 -0
  65. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings.sarif +8729 -0
  66. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/mass-assignment.candidates.json +232 -0
  67. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/report.ja.md +1911 -0
  68. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/report.md +1911 -0
  69. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-001.json +425 -0
  70. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-002.json +333 -0
  71. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-003.json +400 -0
  72. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-004.json +403 -0
  73. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-005.json +398 -0
  74. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-006.json +63 -0
  75. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/score.json +101 -0
  76. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/stack-profile.json +226 -0
  77. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/ai-run-stats.json +54 -0
  78. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/coverage.json +66 -0
  79. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/findings/priv-privilege-001.json +440 -0
  80. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/findings/priv-privilege-002.json +229 -0
  81. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/findings.json +3424 -0
  82. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/mass-assignment.candidates.json +232 -0
  83. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-001.json +425 -0
  84. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-002.json +333 -0
  85. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-003.json +400 -0
  86. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-004.json +403 -0
  87. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-005.json +398 -0
  88. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-006.json +63 -0
  89. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/score.json +120 -0
  90. package/assess/lsa/examples/eval-run-5/gptoss-a/ai-run-stats.json +88 -0
  91. package/assess/lsa/examples/eval-run-5/gptoss-a/coverage.json +36 -0
  92. package/assess/lsa/examples/eval-run-5/gptoss-a/findings/priv-privilege-001.json +530 -0
  93. package/assess/lsa/examples/eval-run-5/gptoss-a/findings/priv-privilege-002.json +248 -0
  94. package/assess/lsa/examples/eval-run-5/gptoss-a/findings.json +4766 -0
  95. package/assess/lsa/examples/eval-run-5/gptoss-a/findings.sarif +9326 -0
  96. package/assess/lsa/examples/eval-run-5/gptoss-a/mass-assignment.candidates.json +232 -0
  97. package/assess/lsa/examples/eval-run-5/gptoss-a/report.ja.md +2011 -0
  98. package/assess/lsa/examples/eval-run-5/gptoss-a/report.md +2011 -0
  99. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-001.json +425 -0
  100. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-002.json +333 -0
  101. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-003.json +400 -0
  102. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-004.json +403 -0
  103. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-005.json +398 -0
  104. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-006.json +63 -0
  105. package/assess/lsa/examples/eval-run-5/gptoss-a/score.json +80 -0
  106. package/assess/lsa/examples/eval-run-5/gptoss-a/stack-profile.json +226 -0
  107. package/assess/lsa/examples/eval-run-5/gptoss-b/ai-run-stats.json +83 -0
  108. package/assess/lsa/examples/eval-run-5/gptoss-b/coverage.json +44 -0
  109. package/assess/lsa/examples/eval-run-5/gptoss-b/findings/priv-privilege-001.json +579 -0
  110. package/assess/lsa/examples/eval-run-5/gptoss-b/findings/priv-privilege-002.json +268 -0
  111. package/assess/lsa/examples/eval-run-5/gptoss-b/findings.json +3913 -0
  112. package/assess/lsa/examples/eval-run-5/gptoss-b/mass-assignment.candidates.json +232 -0
  113. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-001.json +425 -0
  114. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-002.json +333 -0
  115. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-003.json +400 -0
  116. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-004.json +403 -0
  117. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-005.json +398 -0
  118. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-006.json +63 -0
  119. package/assess/lsa/examples/eval-run-5/gptoss-b/score.json +94 -0
  120. package/assess/lsa/examples/eval-run-5/ground-truth.json +823 -0
  121. package/assess/lsa/knowledge/severity-and-cwe.md +1 -1
  122. package/assess/lsa/prompts/35-privilege-auditor.md +3 -1
  123. package/assess/lsa/scripts/baseline.py +5 -2
  124. package/assess/lsa/scripts/findings_to_sarif.py +24 -1
  125. package/assess/lsa/tests/EVAL-RESULTS.md +156 -0
  126. package/assess/lsa/tests/score_findings.py +58 -0
  127. package/assess/lsa/tests/test_adapters.py +21 -2
  128. package/assess/lsa/tests/test_baseline.py +8 -0
  129. package/assess/lsa/tests/test_contract_groundwork.py +7 -7
  130. package/assess/lsa/tests/test_eval_run_4.py +73 -0
  131. package/assess/lsa/tests/test_eval_run_5.py +73 -0
  132. package/assess/lsa/tests/test_privilege_tier2.py +30 -0
  133. package/operate/ai/anchoring.py +130 -0
  134. package/operate/ai/client.py +13 -0
  135. package/operate/ai/context.py +105 -0
  136. package/operate/ai/runner.py +197 -69
  137. package/operate/cli/__init__.py +1 -1
  138. package/operate/cli/commands/scan.py +3 -8
  139. package/operate/cli/commands/test.py +1 -1
  140. package/operate/cli/env.py +4 -20
  141. package/operate/cross_user_tester/persona_matrix.py +5 -1
  142. package/operate/devsecops/pipeline.py +5 -5
  143. package/operate/exploit/generator.py +5 -1
  144. package/operate/lsa_sarif/lsa_to_sarif.py +24 -2
  145. package/operate/lsa_sarif/sarif_findings.py +96 -0
  146. package/operate/remediator/runner.py +1 -5
  147. package/operate/remediator/strategies.py +1 -1
  148. package/operate/tests/test_ai_anchoring.py +184 -0
  149. package/operate/tests/test_cli_baseline.py +1 -9
  150. package/operate/tests/test_cli_env.py +8 -29
  151. package/operate/tests/test_cross_user_pipeline.py +2 -2
  152. package/operate/tests/test_exploit_and_virtual_patch.py +3 -3
  153. package/operate/tests/test_headless_ai.py +148 -1
  154. package/operate/tests/test_npm_package.py +2 -16
  155. package/operate/tests/test_sarif_from_scan.py +156 -0
  156. package/package.json +2 -4
  157. package/remediate/authz/README.md +1 -1
  158. package/remediate/authz/dotnet/src/Komagu.Security.Authorization/DefaultKomaguAuthorizationService.cs +1 -1
  159. package/remediate/authz/dotnet/src/Komagu.Security.Authorization/SecurityAuditEvent.cs +2 -2
  160. package/remediate/authz/golang/authz.go +1 -1
  161. package/remediate/authz/nodejs/src/service.js +1 -1
  162. package/remediate/authz/nodejs/tests/test-authz.js +1 -1
  163. package/remediate/authz/patcher.py +3 -4
  164. package/remediate/authz/python/komagu_authz/models.py +2 -2
  165. package/remediate/authz/python/tests/test_fastapi_adapter.py +1 -1
  166. package/remediate/authz/python/tests/test_fastapi_d5_crosstest.py +1 -1
  167. package/remediate/authz/python/tests/test_python_authz.py +3 -3
  168. package/remediate/authz/spring/src/main/kotlin/io/komagu/security/authorization/DefaultKomaguSecurityManager.kt +1 -1
  169. package/remediate/authz/spring/src/main/kotlin/io/komagu/security/authorization/SecurityAuditEvent.kt +1 -2
  170. package/remediate/authz/tests/test_bola_patcher.py +1 -1
  171. package/remediate/edge/coraza/rules/coraza-crs-custom.conf +3 -4
  172. package/remediate/edge/coraza/virtual_patcher.py +4 -6
  173. package/remediate/edge/docker-compose.yml +1 -1
  174. package/remediate/ekyc/server/jpki_verifier.py +2 -8
  175. package/remediate/ekyc/server/tokenization.py +2 -8
  176. package/remediate/identity/README.md +5 -5
  177. package/remediate/identity/dotnet/src/Komagu.Security.Identity/KomaguOidcOptions.cs +2 -2
  178. package/remediate/identity/dotnet/tests/Komagu.Security.Identity.Tests/TestTokenGenerator.cs +1 -1
  179. package/remediate/identity/dotnet/tests/Komagu.Security.Identity.Tests/TokenValidationTests.cs +1 -1
  180. package/remediate/identity/python/komagu_identity/oidc_validator.py +2 -8
  181. package/remediate/identity/python/tests/test_oidc_validator.py +1 -1
  182. package/remediate/identity/spring/src/main/kotlin/io/komagu/security/identity/KomaguOidcProperties.kt +2 -2
  183. package/remediate/identity/spring/src/test/kotlin/io/komagu/security/identity/KomaguIdentityAutoConfigurationTest.kt +2 -2
  184. package/remediate/identity/spring/src/test/kotlin/io/komagu/security/identity/TestJwtFactory.kt +1 -1
  185. package/remediate/identity/spring/src/test/kotlin/io/komagu/security/identity/TokenValidationIntegrationTest.kt +1 -1
  186. package/remediate/identity/test-env/realm-komagu.json +1 -1
  187. package/remediate/legacy_shims/coldfusion/KomaguSecurityShim.cfc +5 -5
  188. package/remediate/query/README.md +1 -1
  189. package/remediate/query/dotnet/src/Komagu.Security.Query.Analyzers/DiagnosticIds.cs +1 -1
  190. package/remediate/query/dotnet/src/Komagu.Security.Query.Analyzers/Komagu.Security.Query.Analyzers.csproj +1 -1
  191. package/remediate/query/spring/src/main/kotlin/io/komagu/security/query/detekt/KomaguRuleSetProvider.kt +1 -1
  192. package/remediate/resilience/dr/dr_manager.py +2 -8
  193. package/remediate/resilience/dr/runbook.md +2 -2
  194. package/remediate/resilience/terraform/variables.tf +1 -1
  195. package/remediate/tenancy/audit/audit_trail.py +2 -8
  196. package/remediate/tenancy/crypto/byok_manager.py +2 -8
  197. package/remediate/tenancy/middleware/tenant_context.py +2 -8
  198. package/remediate/tenancy/sql/rls_isolation.sql +11 -11
  199. package/remediate/tenancy/sql/schema_per_tenant.sql +7 -7
  200. package/remediate/tenancy/test_sql_postgres.py +1 -1
  201. package/remediate/tenancy/tests/test_tenancy.py +4 -4
  202. package/bin/komainu +0 -16
  203. package/bin/komainu-legacy.js +0 -16
  204. package/remediate/ekyc/tests/test_legacy_env.py +0 -33
  205. package/remediate/identity/python/tests/test_legacy_env.py +0 -33
  206. package/remediate/identity/spring/src/main/kotlin/io/komagu/security/identity/LegacyKomainuPropertiesPostProcessor.kt +0 -60
  207. package/remediate/identity/spring/src/main/resources/META-INF/spring.factories +0 -2
  208. package/remediate/identity/spring/src/test/kotlin/io/komagu/security/identity/LegacyKomainuPropertiesPostProcessorTest.kt +0 -86
  209. package/remediate/resilience/tests/test_legacy_env.py +0 -33
  210. package/remediate/tenancy/tests/test_legacy_env.py +0 -49
@@ -27,7 +27,7 @@ class TokenValidationIntegrationTest {
27
27
 
28
28
  companion object {
29
29
  const val EXPECTED_ISSUER = "https://auth.komagu.test/realms/komagu"
30
- const val EXPECTED_AUDIENCE = "komainu-api"
30
+ const val EXPECTED_AUDIENCE = "komagu-api"
31
31
  val jwtFactory = TestJwtFactory()
32
32
  }
33
33
 
@@ -37,7 +37,7 @@
37
37
  ]
38
38
  },
39
39
  {
40
- "clientId": "komainu-api",
40
+ "clientId": "komagu-api",
41
41
  "name": "Komagu Resource Server API",
42
42
  "enabled": true,
43
43
  "bearerOnly": true,
@@ -18,12 +18,12 @@
18
18
  <cfargument name="idValue" type="any" required="true">
19
19
 
20
20
  <cfif isNull(arguments.idValue)>
21
- <cfthrow type="Komainu.InvalidId" message="Identifier cannot be null.">
21
+ <cfthrow type="Komagu.InvalidId" message="Identifier cannot be null.">
22
22
  </cfif>
23
23
 
24
24
  <cfset var s = trim(toString(arguments.idValue))>
25
25
  <cfif len(s) EQ 0 OR NOT reFind("^[1-9][0-9]{0,18}$", s)>
26
- <cfthrow type="Komainu.InvalidId" message="Identifier must be a positive canonical decimal integer.">
26
+ <cfthrow type="Komagu.InvalidId" message="Identifier must be a positive canonical decimal integer.">
27
27
  </cfif>
28
28
 
29
29
  <cfreturn s>
@@ -59,10 +59,10 @@
59
59
  <cfargument name="allowList" type="array" required="true">
60
60
 
61
61
  <cfif NOT arrayFind(arguments.allowList, arguments.identifier)>
62
- <cfthrow type="Komainu.DisallowedIdentifier" message="Disallowed SQL identifier.">
62
+ <cfthrow type="Komagu.DisallowedIdentifier" message="Disallowed SQL identifier.">
63
63
  </cfif>
64
64
  <cfif NOT reFind("^[a-zA-Z_][a-zA-Z0-9_]*$", arguments.identifier)>
65
- <cfthrow type="Komainu.InvalidIdentifier" message="Invalid SQL identifier format.">
65
+ <cfthrow type="Komagu.InvalidIdentifier" message="Invalid SQL identifier format.">
66
66
  </cfif>
67
67
  <cfreturn arguments.identifier>
68
68
  </cffunction>
@@ -99,7 +99,7 @@
99
99
  </cfquery>
100
100
 
101
101
  <cfif qOwnership.recordCount EQ 0>
102
- <cfthrow type="Komainu.AccessDenied" message="Record not found or not owned.">
102
+ <cfthrow type="Komagu.AccessDenied" message="Record not found or not owned.">
103
103
  </cfif>
104
104
 
105
105
  <cfreturn normResId>
@@ -42,7 +42,7 @@ val safeClause = allowList.buildSortClause(userInputColumn, "DESC")
42
42
 
43
43
  The `Komagu.Security.Query.Analyzers` package inspects syntax trees during build time and inside the IDE to flag any string concatenation or string interpolation passed into raw SQL query methods:
44
44
 
45
- - **Diagnostic ID:** `KOMAINU001`
45
+ - **Diagnostic ID:** `KOMAGU001`
46
46
  - **Severity:** `Warning` / `Error`
47
47
  - **Target APIs:** `FromSqlRaw`, `ExecuteSqlRaw`, `ExecuteSqlRawAsync`, `SqlQueryRaw`, `Query`, `Execute`.
48
48
 
@@ -3,5 +3,5 @@ namespace Komagu.Security.Query.Analyzers;
3
3
  public static class DiagnosticIds
4
4
  {
5
5
  // Kept after the rename so existing #pragma / .editorconfig suppressions still apply (#290).
6
- public const string SqlInjectionDiagnosticId = "KOMAINU001";
6
+ public const string SqlInjectionDiagnosticId = "KOMAGU001";
7
7
  }
@@ -10,7 +10,7 @@
10
10
  <Version>1.0.0-preview.1</Version>
11
11
  <Authors>Komagu Contributors</Authors>
12
12
  <Company>Komagu Security</Company>
13
- <Description>Roslyn analyzer rule KOMAINU001 detecting SQL injection from string-built queries in C#.</Description>
13
+ <Description>Roslyn analyzer rule KOMAGU001 detecting SQL injection from string-built queries in C#.</Description>
14
14
  <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
15
15
  <IsRoslynComponent>true</IsRoslynComponent>
16
16
  <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
@@ -9,7 +9,7 @@ import io.gitlab.arturbosch.detekt.api.RuleSetProvider
9
9
  */
10
10
  class KomaguRuleSetProvider : RuleSetProvider {
11
11
  // Kept after the rename so existing detekt.yml sections and @Suppress ids still apply (#290).
12
- override val ruleSetId: String = "komainu-security"
12
+ override val ruleSetId: String = "komagu-security"
13
13
 
14
14
  override fun instance(config: Config): RuleSet {
15
15
  return RuleSet(
@@ -15,18 +15,12 @@ import json
15
15
  import os
16
16
  import sys
17
17
  import time
18
- import warnings
19
18
  from typing import Any, Dict, List, Optional, Tuple
20
19
 
21
20
 
22
21
  def _env(name: str, default: Optional[str] = None) -> Optional[str]:
23
- """Read KOMAGU_<name>, falling back to the deprecated KOMAINU_<name> (#290)."""
24
- value = os.environ.get("KOMAGU_" + name)
25
- if value is None:
26
- value = os.environ.get("KOMAINU_" + name)
27
- if value is not None:
28
- warnings.warn(f"KOMAINU_{name} is deprecated, set KOMAGU_{name} instead", DeprecationWarning, stacklevel=2)
29
- return default if value is None else value
22
+ """Read KOMAGU_<name>."""
23
+ return os.environ.get("KOMAGU_" + name, default)
30
24
 
31
25
 
32
26
 
@@ -34,7 +34,7 @@ A Disaster Recovery failover is declared by the Incident Commander / Principal A
34
34
  ### Phase 2: Secondary Cluster Activation (大阪スタンバイ環境起動)
35
35
  1. Scale Osaka ECS tasks from 0 (warm standby) to production capacity:
36
36
  ```bash
37
- aws ecs update-service --cluster komainu-production-standby-dr-cluster \
37
+ aws ecs update-service --cluster komagu-production-standby-dr-cluster \
38
38
  --service api-gateway --desired-count 4 --region ap-northeast-3
39
39
  ```
40
40
  2. Rehydrate relational state from S3 Object Lock Compliance WORM bucket:
@@ -43,7 +43,7 @@ A Disaster Recovery failover is declared by the Incident Commander / Principal A
43
43
  ```
44
44
 
45
45
  ### Phase 3: Route53 Traffic Cutover (DNS切替)
46
- 1. Update DNS failover record to point to Osaka ALB (`osaka-dr-alb.komainu.internal`).
46
+ 1. Update DNS failover record to point to Osaka ALB (`osaka-dr-alb.komagu.internal`).
47
47
  2. Verify smoke test health check returns HTTP 200 on all core endpoints.
48
48
 
49
49
  ---
@@ -15,7 +15,7 @@ variable "secondary_region" {
15
15
  variable "project_name" {
16
16
  description = "Project and workload prefix"
17
17
  type = string
18
- default = "komainu"
18
+ default = "komagu"
19
19
  }
20
20
 
21
21
  variable "environment" {
@@ -17,18 +17,12 @@ import os
17
17
  import secrets
18
18
  import sys
19
19
  import threading
20
- import warnings
21
20
  from typing import Any, Dict, List, Optional, Tuple
22
21
 
23
22
 
24
23
  def _env(name: str, default: Optional[str] = None) -> Optional[str]:
25
- """Read KOMAGU_<name>, falling back to the deprecated KOMAINU_<name> (#290)."""
26
- value = os.environ.get("KOMAGU_" + name)
27
- if value is None:
28
- value = os.environ.get("KOMAINU_" + name)
29
- if value is not None:
30
- warnings.warn(f"KOMAINU_{name} is deprecated, set KOMAGU_{name} instead", DeprecationWarning, stacklevel=2)
31
- return default if value is None else value
24
+ """Read KOMAGU_<name>."""
25
+ return os.environ.get("KOMAGU_" + name, default)
32
26
 
33
27
 
34
28
 
@@ -15,18 +15,12 @@ import json
15
15
  import os
16
16
  import secrets
17
17
  import sys
18
- import warnings
19
18
  from typing import Any, Dict, Optional, Tuple
20
19
 
21
20
 
22
21
  def _env(name: str, default: Optional[str] = None) -> Optional[str]:
23
- """Read KOMAGU_<name>, falling back to the deprecated KOMAINU_<name> (#290)."""
24
- value = os.environ.get("KOMAGU_" + name)
25
- if value is None:
26
- value = os.environ.get("KOMAINU_" + name)
27
- if value is not None:
28
- warnings.warn(f"KOMAINU_{name} is deprecated, set KOMAGU_{name} instead", DeprecationWarning, stacklevel=2)
29
- return default if value is None else value
22
+ """Read KOMAGU_<name>."""
23
+ return os.environ.get("KOMAGU_" + name, default)
30
24
 
31
25
 
32
26
  try:
@@ -12,18 +12,12 @@ from contextlib import contextmanager
12
12
  import hmac
13
13
  import os
14
14
  import re
15
- import warnings
16
15
  from typing import Any, Dict, Iterator, Optional
17
16
 
18
17
 
19
18
  def _env(name: str, default: Optional[str] = None) -> Optional[str]:
20
- """Read KOMAGU_<name>, falling back to the deprecated KOMAINU_<name> (#290)."""
21
- value = os.environ.get("KOMAGU_" + name)
22
- if value is None:
23
- value = os.environ.get("KOMAINU_" + name)
24
- if value is not None:
25
- warnings.warn(f"KOMAINU_{name} is deprecated, set KOMAGU_{name} instead", DeprecationWarning, stacklevel=2)
26
- return default if value is None else value
19
+ """Read KOMAGU_<name>."""
20
+ return os.environ.get("KOMAGU_" + name, default)
27
21
 
28
22
 
29
23
  # Context variable holding the active tenant_id for the current execution thread/coroutine
@@ -8,16 +8,16 @@
8
8
  -- In autocommit connection pools, session state expires immediately after set_current_tenant().
9
9
  -- 2. ROLE RESTRICTION: FORCE ROW LEVEL SECURITY enforces policies on table owners
10
10
  -- and standard users, but NEVER applies to PostgreSQL superusers or roles with BYPASSRLS.
11
- -- Applications MUST connect using a non-owner, non-BYPASSRLS application role (komainu_app).
11
+ -- Applications MUST connect using a non-owner, non-BYPASSRLS application role (komagu_app).
12
12
 
13
13
  -- 0. Provision Dedicated Non-Owner Application Role (without hard-coded password)
14
14
  -- NOTE: In production environments requiring LOGIN connections, configure passwords
15
- -- exclusively via deployment orchestration or vault parameters (ALTER ROLE komainu_app WITH LOGIN PASSWORD ...),
15
+ -- exclusively via deployment orchestration or vault parameters (ALTER ROLE komagu_app WITH LOGIN PASSWORD ...),
16
16
  -- NEVER hard-code credentials in committed migration scripts.
17
17
  DO $$
18
18
  BEGIN
19
- IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'komainu_app') THEN
20
- CREATE ROLE komainu_app WITH NOSUPERUSER NOBYPASSRLS NOCREATEDB NOCREATEROLE NOLOGIN;
19
+ IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'komagu_app') THEN
20
+ CREATE ROLE komagu_app WITH NOSUPERUSER NOBYPASSRLS NOCREATEDB NOCREATEROLE NOLOGIN;
21
21
  END IF;
22
22
  END;
23
23
  $$;
@@ -55,7 +55,7 @@ ALTER TABLE orders FORCE ROW LEVEL SECURITY;
55
55
  DROP POLICY IF EXISTS tenant_org_isolation_policy ON tenant_organizations;
56
56
  CREATE POLICY tenant_org_isolation_policy ON tenant_organizations
57
57
  FOR ALL
58
- TO komainu_app
58
+ TO komagu_app
59
59
  USING (
60
60
  id = NULLIF(current_setting('app.current_tenant_id', true), '')
61
61
  )
@@ -67,7 +67,7 @@ CREATE POLICY tenant_org_isolation_policy ON tenant_organizations
67
67
  DROP POLICY IF EXISTS tenant_isolation_policy ON orders;
68
68
  CREATE POLICY tenant_isolation_policy ON orders
69
69
  FOR ALL
70
- TO komainu_app
70
+ TO komagu_app
71
71
  USING (
72
72
  tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')
73
73
  )
@@ -126,11 +126,11 @@ CREATE TRIGGER trg_orders_tenant_injection
126
126
 
127
127
  -- 6. Grant Least-Privilege Access to Application Role & Revoke Public Execution
128
128
  REVOKE ALL ON FUNCTION trg_inject_current_tenant() FROM PUBLIC;
129
- GRANT USAGE ON SCHEMA public TO komainu_app;
130
- GRANT SELECT, INSERT, UPDATE, DELETE ON tenant_organizations TO komainu_app;
131
- GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO komainu_app;
129
+ GRANT USAGE ON SCHEMA public TO komagu_app;
130
+ GRANT SELECT, INSERT, UPDATE, DELETE ON tenant_organizations TO komagu_app;
131
+ GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO komagu_app;
132
132
 
133
133
  REVOKE ALL ON FUNCTION set_current_tenant(VARCHAR) FROM PUBLIC;
134
134
  REVOKE ALL ON FUNCTION reset_current_tenant() FROM PUBLIC;
135
- GRANT EXECUTE ON FUNCTION set_current_tenant(VARCHAR) TO komainu_app;
136
- GRANT EXECUTE ON FUNCTION reset_current_tenant() TO komainu_app;
135
+ GRANT EXECUTE ON FUNCTION set_current_tenant(VARCHAR) TO komagu_app;
136
+ GRANT EXECUTE ON FUNCTION reset_current_tenant() TO komagu_app;
@@ -59,10 +59,10 @@ BEGIN
59
59
 
60
60
 
61
61
  -- Grant least-privilege tenant access to application role
62
- IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'komainu_app') THEN
63
- EXECUTE format('GRANT USAGE ON SCHEMA %I TO komainu_app', v_schema_name);
64
- EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA %I TO komainu_app', v_schema_name);
65
- EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO komainu_app', v_schema_name);
62
+ IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'komagu_app') THEN
63
+ EXECUTE format('GRANT USAGE ON SCHEMA %I TO komagu_app', v_schema_name);
64
+ EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA %I TO komagu_app', v_schema_name);
65
+ EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO komagu_app', v_schema_name);
66
66
  END IF;
67
67
 
68
68
  END;
@@ -101,11 +101,11 @@ $$ LANGUAGE plpgsql;
101
101
  REVOKE ALL ON FUNCTION create_tenant_schema(VARCHAR) FROM PUBLIC;
102
102
  REVOKE ALL ON FUNCTION switch_tenant_schema(VARCHAR) FROM PUBLIC;
103
103
  REVOKE ALL ON TABLE public.tenant_registry FROM PUBLIC;
104
- -- Note: No SELECT grant on tenant_registry for komainu_app. Namespace‑only isolation is enforced; cross‑tenant queries must use tenant‑specific schemas.
104
+ -- Note: No SELECT grant on tenant_registry for komagu_app. Namespace‑only isolation is enforced; cross‑tenant queries must use tenant‑specific schemas.
105
105
  DO $$
106
106
  BEGIN
107
- IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'komainu_app') THEN
108
- GRANT EXECUTE ON FUNCTION switch_tenant_schema(VARCHAR) TO komainu_app;
107
+ IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'komagu_app') THEN
108
+ GRANT EXECUTE ON FUNCTION switch_tenant_schema(VARCHAR) TO komagu_app;
109
109
  END IF;
110
110
  END $$;
111
111
 
@@ -16,7 +16,7 @@ import psycopg2
16
16
  from psycopg2 import sql
17
17
 
18
18
  # Paths to the SQL scripts relative to the repository root.
19
- REPO_ROOT = Path("/Users/hoanghainh/Projects/komainu")
19
+ REPO_ROOT = Path(__file__).resolve().parents[2]
20
20
  SCHEMA_SQL = REPO_ROOT / "remediate" / "tenancy" / "sql" / "schema_per_tenant.sql"
21
21
  RLS_SQL = REPO_ROOT / "remediate" / "tenancy" / "sql" / "rls_isolation.sql"
22
22
 
@@ -206,8 +206,8 @@ class TestTenantIsolationAndBYOK(unittest.TestCase):
206
206
  self.assertIn("REVOKE ALL ON ALL TABLES IN SCHEMA %I FROM PUBLIC", sql_content)
207
207
  self.assertIn("REVOKE ALL ON FUNCTION create_tenant_schema(VARCHAR) FROM PUBLIC", sql_content)
208
208
  self.assertIn("REVOKE ALL ON FUNCTION switch_tenant_schema(VARCHAR) FROM PUBLIC", sql_content)
209
- self.assertIn("GRANT USAGE ON SCHEMA %I TO komainu_app", sql_content)
210
- self.assertIn("GRANT EXECUTE ON FUNCTION switch_tenant_schema(VARCHAR) TO komainu_app", sql_content)
209
+ self.assertIn("GRANT USAGE ON SCHEMA %I TO komagu_app", sql_content)
210
+ self.assertIn("GRANT EXECUTE ON FUNCTION switch_tenant_schema(VARCHAR) TO komagu_app", sql_content)
211
211
 
212
212
  def test_11_rls_sql_app_role_and_tenant_organizations_security(self) -> None:
213
213
  """Verifies RLS template defines non-owner app role, protects tenant_organizations, and pins search_path."""
@@ -215,7 +215,7 @@ class TestTenantIsolationAndBYOK(unittest.TestCase):
215
215
  with open(rls_file, "r", encoding="utf-8") as f:
216
216
  sql_content = f.read()
217
217
 
218
- self.assertIn("CREATE ROLE komainu_app WITH NOSUPERUSER NOBYPASSRLS", sql_content)
218
+ self.assertIn("CREATE ROLE komagu_app WITH NOSUPERUSER NOBYPASSRLS", sql_content)
219
219
  self.assertIn("NOLOGIN", sql_content)
220
220
  self.assertNotIn("replace_with_secure_app_password", sql_content)
221
221
  self.assertIn("ALTER TABLE tenant_organizations ENABLE ROW LEVEL SECURITY", sql_content)
@@ -225,7 +225,7 @@ class TestTenantIsolationAndBYOK(unittest.TestCase):
225
225
  self.assertIn("TRANSACTION REQUIREMENT", sql_content)
226
226
  self.assertIn("BEGIN ... COMMIT", sql_content)
227
227
  self.assertIn("REVOKE ALL ON FUNCTION set_current_tenant(VARCHAR) FROM PUBLIC", sql_content)
228
- self.assertIn("GRANT EXECUTE ON FUNCTION set_current_tenant(VARCHAR) TO komainu_app", sql_content)
228
+ self.assertIn("GRANT EXECUTE ON FUNCTION set_current_tenant(VARCHAR) TO komagu_app", sql_content)
229
229
 
230
230
  def test_12_rls_cross_tenant_isolation_logic_simulation(self) -> None:
231
231
  """Simulates RLS policy evaluation: verifying cross-tenant records cannot be read."""
package/bin/komainu DELETED
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Deprecated `bin/komainu` entrypoint: use `bin/komagu` (#290)."""
3
-
4
- from __future__ import annotations
5
-
6
- import sys
7
- from pathlib import Path
8
-
9
- REPO_ROOT = Path(__file__).resolve().parent.parent
10
- sys.path.insert(0, str(REPO_ROOT))
11
-
12
- from operate.cli.main import main # noqa: E402
13
-
14
- if __name__ == "__main__":
15
- print("[DEPRECATED] bin/komainu was renamed to bin/komagu.", file=sys.stderr)
16
- sys.exit(main())
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Deprecated `komainu` / `komainu-guard` npm bin aliases.
4
- *
5
- * Prints a rename notice to stderr, then runs the Komagu launcher unchanged.
6
- * Remove in the next major release (#290).
7
- */
8
-
9
- 'use strict';
10
-
11
- console.error(
12
- '\x1b[33m[DEPRECATED]\x1b[0m `komainu` / `komainu-guard` were renamed to `komagu`. ' +
13
- 'Install @hoanghainh/komagu and run `komagu` instead.'
14
- );
15
-
16
- require('./komagu.js');
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env python3
2
- """KOMAGU_* environment variables with the deprecated KOMAINU_* fallback (#290)."""
3
-
4
- from __future__ import annotations
5
-
6
- import os
7
- import unittest
8
- import warnings
9
- from unittest.mock import patch
10
-
11
- from remediate.ekyc.server import tokenization, jpki_verifier
12
-
13
- MODULES = (tokenization, jpki_verifier)
14
-
15
-
16
- class TestLegacyEnvFallback(unittest.TestCase):
17
- def test_new_name_wins_without_warning(self) -> None:
18
- env = {"KOMAGU_EKYC_HMAC_KEY": "new", "KOMAINU_EKYC_HMAC_KEY": "old"}
19
- for mod in MODULES:
20
- with self.subTest(module=mod.__name__), patch.dict(os.environ, env), warnings.catch_warnings(record=True) as caught:
21
- warnings.simplefilter("always")
22
- self.assertEqual(mod._env("EKYC_HMAC_KEY"), "new")
23
- self.assertEqual(caught, [])
24
-
25
- def test_legacy_name_is_read_with_deprecation_warning(self) -> None:
26
- for mod in MODULES:
27
- with self.subTest(module=mod.__name__), patch.dict(os.environ, {"KOMAINU_EKYC_HMAC_KEY": "old"}, clear=True):
28
- with self.assertWarnsRegex(DeprecationWarning, "KOMAINU_EKYC_HMAC_KEY is deprecated"):
29
- self.assertEqual(mod._env("EKYC_HMAC_KEY"), "old")
30
-
31
-
32
- if __name__ == "__main__":
33
- unittest.main()
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env python3
2
- """KOMAGU_* environment variables with the deprecated KOMAINU_* fallback (#290)."""
3
-
4
- from __future__ import annotations
5
-
6
- import os
7
- import unittest
8
- import warnings
9
- from unittest.mock import patch
10
-
11
- from remediate.identity.python.komagu_identity import oidc_validator
12
-
13
- MODULES = (oidc_validator,)
14
-
15
-
16
- class TestLegacyEnvFallback(unittest.TestCase):
17
- def test_new_name_wins_without_warning(self) -> None:
18
- env = {"KOMAGU_ALLOW_DEV_TOKENS": "new", "KOMAINU_ALLOW_DEV_TOKENS": "old"}
19
- for mod in MODULES:
20
- with self.subTest(module=mod.__name__), patch.dict(os.environ, env), warnings.catch_warnings(record=True) as caught:
21
- warnings.simplefilter("always")
22
- self.assertEqual(mod._env("ALLOW_DEV_TOKENS"), "new")
23
- self.assertEqual(caught, [])
24
-
25
- def test_legacy_name_is_read_with_deprecation_warning(self) -> None:
26
- for mod in MODULES:
27
- with self.subTest(module=mod.__name__), patch.dict(os.environ, {"KOMAINU_ALLOW_DEV_TOKENS": "old"}, clear=True):
28
- with self.assertWarnsRegex(DeprecationWarning, "KOMAINU_ALLOW_DEV_TOKENS is deprecated"):
29
- self.assertEqual(mod._env("ALLOW_DEV_TOKENS"), "old")
30
-
31
-
32
- if __name__ == "__main__":
33
- unittest.main()
@@ -1,60 +0,0 @@
1
- package io.komagu.security.identity
2
-
3
- import org.springframework.boot.SpringApplication
4
- import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor
5
- import org.springframework.boot.env.EnvironmentPostProcessor
6
- import org.springframework.boot.logging.DeferredLogFactory
7
- import org.springframework.core.Ordered
8
- import org.springframework.core.env.ConfigurableEnvironment
9
- import org.springframework.core.env.EnumerablePropertySource
10
- import org.springframework.core.env.MapPropertySource
11
-
12
- /**
13
- * Maps deprecated pre-rename `komainu.security.*` properties (and `KOMAINU_SECURITY_*` env vars)
14
- * onto `komagu.security.*` (#290). The mapped values are added last, so any `komagu.security.*`
15
- * value set explicitly still wins. Remove in the next major release.
16
- */
17
- class LegacyKomainuPropertiesPostProcessor(logFactory: DeferredLogFactory) : EnvironmentPostProcessor, Ordered {
18
-
19
- private val log = logFactory.getLog(javaClass)
20
-
21
- override fun postProcessEnvironment(environment: ConfigurableEnvironment, application: SpringApplication?) {
22
- val mapped = linkedMapOf<String, Any>()
23
- // Property sources iterate highest precedence first, so the first legacy value seen wins.
24
- environment.propertySources
25
- .filterIsInstance<EnumerablePropertySource<*>>()
26
- .filter { it.name != SOURCE_NAME }
27
- .forEach { collectLegacy(it, mapped) }
28
- if (mapped.isEmpty()) return
29
- log.warn(
30
- "komainu.security.* properties are deprecated, rename them to komagu.security.* " +
31
- "(mapped: ${mapped.keys.joinToString()})"
32
- )
33
- environment.propertySources.addLast(MapPropertySource(SOURCE_NAME, mapped))
34
- }
35
-
36
- private fun collectLegacy(source: EnumerablePropertySource<*>, mapped: MutableMap<String, Any>) {
37
- for (name in source.propertyNames) {
38
- val current = currentName(name)
39
- if (current != null && current !in mapped) {
40
- source.getProperty(name)?.let { mapped[current] = it }
41
- }
42
- }
43
- }
44
-
45
- override fun getOrder(): Int = ConfigDataEnvironmentPostProcessor.ORDER + 1
46
-
47
- companion object {
48
- const val SOURCE_NAME = "legacyKomainuProperties"
49
- private const val LEGACY_PREFIX = "komainu.security."
50
- private const val LEGACY_ENV_PREFIX = "KOMAINU_SECURITY_"
51
- private const val PREFIX = "komagu.security."
52
-
53
- fun currentName(name: String): String? = when {
54
- name.startsWith(LEGACY_PREFIX) -> PREFIX + name.removePrefix(LEGACY_PREFIX)
55
- name.startsWith(LEGACY_ENV_PREFIX) ->
56
- PREFIX + name.removePrefix(LEGACY_ENV_PREFIX).lowercase().replace('_', '.')
57
- else -> null
58
- }
59
- }
60
- }
@@ -1,2 +0,0 @@
1
- org.springframework.boot.env.EnvironmentPostProcessor=\
2
- io.komagu.security.identity.LegacyKomainuPropertiesPostProcessor
@@ -1,86 +0,0 @@
1
- package io.komagu.security.identity
2
-
3
- import org.junit.jupiter.api.Assertions.assertEquals
4
- import org.junit.jupiter.api.Assertions.assertNull
5
- import org.junit.jupiter.api.Assertions.assertTrue
6
- import org.junit.jupiter.api.Test
7
- import org.springframework.boot.context.properties.bind.Binder
8
- import org.springframework.boot.logging.DeferredLogFactory
9
- import org.springframework.core.env.MapPropertySource
10
- import org.springframework.core.env.PropertySource
11
- import org.springframework.core.env.StandardEnvironment
12
- import org.springframework.core.env.SystemEnvironmentPropertySource
13
-
14
- class LegacyKomainuPropertiesPostProcessorTest {
15
-
16
- private val processor = LegacyKomainuPropertiesPostProcessor(DeferredLogFactory { it.get() })
17
-
18
- private fun bind(env: StandardEnvironment): KomaguOidcProperties =
19
- Binder.get(env).bind("komagu.security.oidc", KomaguOidcProperties::class.java).orElseGet { KomaguOidcProperties() }
20
-
21
- private fun envWith(vararg sources: PropertySource<*>): StandardEnvironment {
22
- val env = StandardEnvironment()
23
- env.propertySources.toList().forEach { env.propertySources.remove(it.name) }
24
- sources.forEach { env.propertySources.addLast(it) }
25
- return env
26
- }
27
-
28
- @Test
29
- fun `legacy properties bind to the komagu prefix`() {
30
- val env = envWith(
31
- MapPropertySource(
32
- "app",
33
- mapOf(
34
- "komainu.security.oidc.issuer" to "https://auth.example.com",
35
- "komainu.security.oidc.jwk-set-uri" to "https://auth.example.com/certs",
36
- "komainu.security.oidc.clock-skew-seconds" to "30"
37
- )
38
- )
39
- )
40
- processor.postProcessEnvironment(env, null)
41
-
42
- val props = bind(env)
43
- assertEquals("https://auth.example.com", props.issuer)
44
- assertEquals("https://auth.example.com/certs", props.jwkSetUri)
45
- assertEquals(30L, props.clockSkewSeconds)
46
- }
47
-
48
- @Test
49
- fun `explicit komagu properties win over legacy ones`() {
50
- val env = envWith(
51
- MapPropertySource("low", mapOf("komagu.security.oidc.audience" to "new-api")),
52
- MapPropertySource("high", mapOf("komainu.security.oidc.audience" to "old-api"))
53
- )
54
- processor.postProcessEnvironment(env, null)
55
-
56
- assertEquals("new-api", bind(env).audience)
57
- }
58
-
59
- @Test
60
- fun `legacy environment variables are mapped`() {
61
- val env = envWith(
62
- SystemEnvironmentPropertySource(
63
- "systemEnvironment",
64
- mapOf<String, Any>("KOMAINU_SECURITY_OIDC_ALLOWINSECUREHTTPJWKS" to "true")
65
- )
66
- )
67
- processor.postProcessEnvironment(env, null)
68
-
69
- assertEquals(true, bind(env).allowInsecureHttpJwks)
70
- }
71
-
72
- @Test
73
- fun `nothing is added without legacy properties`() {
74
- val env = envWith(MapPropertySource("app", mapOf("komagu.security.oidc.audience" to "x")))
75
- processor.postProcessEnvironment(env, null)
76
-
77
- assertNull(env.propertySources.get(LegacyKomainuPropertiesPostProcessor.SOURCE_NAME))
78
- }
79
-
80
- @Test
81
- fun `post processor is registered in spring factories`() {
82
- val factories = javaClass.classLoader.getResource("META-INF/spring.factories")!!.readText()
83
- assertTrue("org.springframework.boot.env.EnvironmentPostProcessor" in factories)
84
- assertTrue(LegacyKomainuPropertiesPostProcessor::class.java.name in factories)
85
- }
86
- }
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env python3
2
- """KOMAGU_* environment variables with the deprecated KOMAINU_* fallback (#290)."""
3
-
4
- from __future__ import annotations
5
-
6
- import os
7
- import unittest
8
- import warnings
9
- from unittest.mock import patch
10
-
11
- from remediate.resilience.dr import dr_manager
12
-
13
- MODULES = (dr_manager,)
14
-
15
-
16
- class TestLegacyEnvFallback(unittest.TestCase):
17
- def test_new_name_wins_without_warning(self) -> None:
18
- env = {"KOMAGU_DR_METADATA_PATH": "new", "KOMAINU_DR_METADATA_PATH": "old"}
19
- for mod in MODULES:
20
- with self.subTest(module=mod.__name__), patch.dict(os.environ, env), warnings.catch_warnings(record=True) as caught:
21
- warnings.simplefilter("always")
22
- self.assertEqual(mod._env("DR_METADATA_PATH"), "new")
23
- self.assertEqual(caught, [])
24
-
25
- def test_legacy_name_is_read_with_deprecation_warning(self) -> None:
26
- for mod in MODULES:
27
- with self.subTest(module=mod.__name__), patch.dict(os.environ, {"KOMAINU_DR_METADATA_PATH": "old"}, clear=True):
28
- with self.assertWarnsRegex(DeprecationWarning, "KOMAINU_DR_METADATA_PATH is deprecated"):
29
- self.assertEqual(mod._env("DR_METADATA_PATH"), "old")
30
-
31
-
32
- if __name__ == "__main__":
33
- unittest.main()