Enabling UI

The control-plane UI lives in feature-ui.

Build with it:

./gradlew shadowJar -Pkeeper.features=ui

Open:

GET /ui/

Disable the UI at startup:

java \
  -Dkeeper.ui.enabled=false \
  -jar build/libs/tkeeper-2.0.0.jar

Authentication

The UI uses the same external auth mode as the API.

With dev auth, the browser sends:

X-DEV-TOKEN

With JWT auth, the browser sends:

X-JWT-TOKEN

If auth.jwt.oidc is configured, the UI reads OIDC settings from:

GET /v1/keeper/control/auth/config

Content Security Policy

The UI feature adds security headers under /ui.

Default CSP:

keeper.csp {
  default-src = ["'self'"]
  base-uri = ["'self'"]
  object-src = ["'none'"]
  frame-ancestors = ["'none'"]
  script-src = ["'self'"]
  style-src = ["'self'"]
  img-src = ["'self'", "data:"]
  font-src = ["'self'", "data:"]
  connect-src = ["'self'"]
  form-action = ["'self'"]
}

Report-only mode:

keeper.csp {
  report-only = true
}

Extra origins:

keeper.csp {
  connect-extra = [
    "https://issuer.example"
  ]

  form-action-extra = [
    "https://issuer.example"
  ]

  img-extra = [
    "https://assets.example"
  ]
}

OIDC origins are added to connect-src automatically when:

keeper.csp {
  oidc-auto-connect = true
}

Set it to false when connect-src is managed manually.

Headers

The UI also sends:

Referrer-Policy: no-referrer
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Permissions-Policy: geolocation=(), microphone=(), camera=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin

When public TLS is enabled:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Frequent Problems

/ui/ returns 404

Rebuild with feature-ui.

OIDC login cannot reach the issuer

Check keeper.csp.connect-extra or keep keeper.csp.oidc-auto-connect = true.