Harden admin deployment and local acceptance
Enforce mTLS and least-privilege runtime boundaries while adding repeatable MySQL 8.4 and Docker smoke checks that require no production secrets.
This commit is contained in:
@@ -10,7 +10,7 @@ import java.nio.file.Path
|
||||
class DeploymentConsistencyTest : FunSpec({
|
||||
val root = Path.of(System.getProperty("user.dir"))
|
||||
|
||||
test("OpenAPI documents every mounted public route") {
|
||||
test("OpenAPI documents every mounted API route") {
|
||||
val openApi = root.read("docs/openapi.yaml")
|
||||
val documentedPaths = Regex("""(?m)^ (/[^:]+):\s*$""")
|
||||
.findAll(openApi)
|
||||
@@ -20,6 +20,25 @@ class DeploymentConsistencyTest : FunSpec({
|
||||
documentedPaths shouldBe EXPECTED_PUBLIC_PATHS
|
||||
}
|
||||
|
||||
test("OpenAPI defines admin pagination and response contracts") {
|
||||
val openApi = root.read("docs/openapi.yaml")
|
||||
val sessionSchema = openApi
|
||||
.substringAfter(" AdminSessionState:")
|
||||
.substringBefore(" AdminLoginResponse:")
|
||||
|
||||
sessionSchema shouldNotContain "csrfToken"
|
||||
openApi shouldContain "schema: { \$ref: \"#/components/schemas/AdminOverview\" }"
|
||||
openApi shouldContain "schema: { \$ref: \"#/components/schemas/AdminReferralOverview\" }"
|
||||
openApi shouldContain "schema: { \$ref: \"#/components/schemas/AdminUserPage\" }"
|
||||
openApi shouldContain "schema: { \$ref: \"#/components/schemas/AdminUserDetail\" }"
|
||||
openApi shouldContain "schema: { \$ref: \"#/components/schemas/AdminLedgerPage\" }"
|
||||
openApi shouldContain "schema: { \$ref: \"#/components/schemas/AdminAuditPage\" }"
|
||||
openApi shouldContain "pendingBindings"
|
||||
openApi shouldContain "ineligibleBindings"
|
||||
openApi shouldContain "chargedCredits"
|
||||
openApi shouldContain "referralCode"
|
||||
}
|
||||
|
||||
test("production Compose reuses private MySQL and hardens the application container") {
|
||||
val compose = root.read("compose.yaml")
|
||||
|
||||
@@ -37,12 +56,35 @@ class DeploymentConsistencyTest : FunSpec({
|
||||
compose shouldNotContain "0.0.0.0:"
|
||||
}
|
||||
|
||||
test("admin bootstrap is one-time and runtime database grants stay explicit") {
|
||||
val compose = root.read("compose.yaml")
|
||||
val privileges = root.read("docs/mysql-minimum-privileges.sql")
|
||||
|
||||
compose shouldContain "ADMIN_BOOTSTRAP_ENABLED: \${ADMIN_BOOTSTRAP_ENABLED:-false}"
|
||||
privileges shouldContain "GRANT SELECT ON osg_account.admin_operators"
|
||||
privileges shouldContain "GRANT INSERT, UPDATE ON osg_account.admin_operators"
|
||||
privileges shouldContain "GRANT SELECT ON osg_account.admin_sessions"
|
||||
privileges shouldContain "GRANT INSERT, UPDATE, DELETE ON osg_account.admin_sessions"
|
||||
privileges shouldContain "GRANT SELECT ON osg_account.gateway_grant_scopes"
|
||||
privileges shouldContain "GRANT INSERT ON osg_account.gateway_grant_scopes"
|
||||
privileges shouldContain "GRANT SELECT ON osg_account.gateway_refresh_tokens"
|
||||
privileges shouldContain "GRANT INSERT, UPDATE ON osg_account.gateway_refresh_tokens"
|
||||
privileges shouldContain "GRANT INSERT ON osg_account.admin_audit_log"
|
||||
privileges shouldContain "GRANT INSERT ON osg_account.admin_credit_grants"
|
||||
privileges shouldNotContain "UPDATE ON osg_account.admin_audit_log"
|
||||
privileges shouldNotContain "DELETE ON osg_account.admin_credit_grants"
|
||||
}
|
||||
|
||||
test("container image remains non-root and read-only compatible") {
|
||||
val dockerfile = root.read("Dockerfile")
|
||||
val build = root.read("build.gradle.kts")
|
||||
|
||||
dockerfile shouldContain "USER 10001:10001"
|
||||
dockerfile shouldContain "ENV HOME=/tmp"
|
||||
dockerfile shouldContain "http://127.0.0.1:8080/health/ready"
|
||||
dockerfile shouldNotContain "ENTRYPOINT [\"sh\""
|
||||
dockerfile shouldNotContain "jansi.tmpdir"
|
||||
build shouldContain "exclude(group = \"org.fusesource.jansi\", module = \"jansi\")"
|
||||
}
|
||||
|
||||
test("OpenResty proxies HTTP WebSocket invitations and both AASA paths safely") {
|
||||
@@ -55,6 +97,7 @@ class DeploymentConsistencyTest : FunSpec({
|
||||
openResty shouldContain "location ^~ /i/"
|
||||
Regex("""location \^~ /i/ \{\s+access_log off;""").containsMatchIn(openResty) shouldBe true
|
||||
openResty shouldNotContain "alias /www/wwwroot/osglab.com/apple-app-site-association"
|
||||
openResty shouldNotContain "unsafe-inline"
|
||||
}
|
||||
|
||||
test("CI definition is singular and leaves MySQL lifecycle to Testcontainers") {
|
||||
@@ -112,6 +155,23 @@ private val EXPECTED_PUBLIC_PATHS = setOf(
|
||||
"/v1/gateway/asr",
|
||||
"/v1/gateway/asr/sessions",
|
||||
"/v1/gateway/asr/sessions/{sessionId}/stream",
|
||||
"/v1/admin/auth/session",
|
||||
"/v1/admin/auth/login",
|
||||
"/v1/admin/auth/logout",
|
||||
"/v1/admin/overview",
|
||||
"/v1/admin/referrals",
|
||||
"/v1/admin/users",
|
||||
"/v1/admin/users/{userId}",
|
||||
"/v1/admin/users/{userId}/ledger",
|
||||
"/v1/admin/credits/grants",
|
||||
"/v1/admin/operators/summary",
|
||||
"/v1/admin/operators",
|
||||
"/v1/admin/operators/{operatorId}/enable",
|
||||
"/v1/admin/operators/{operatorId}/disable",
|
||||
"/v1/admin/operators/{operatorId}/unlock",
|
||||
"/v1/admin/operators/{operatorId}/credentials/reset",
|
||||
"/v1/admin/operators/{operatorId}/sessions/revoke",
|
||||
"/v1/admin/audit",
|
||||
"/.well-known/apple-app-site-association",
|
||||
"/apple-app-site-association",
|
||||
"/i/{code}",
|
||||
|
||||
Reference in New Issue
Block a user