1
0
forked from baron/baron-sso

README update

This commit is contained in:
Lectom C Han
2026-01-28 17:30:23 +09:00
parent 3e95650024
commit 39594f8e21
11 changed files with 1127 additions and 445 deletions

View File

@@ -0,0 +1,22 @@
CREATE DATABASE IF NOT EXISTS ory;
CREATE TABLE IF NOT EXISTS ory.oathkeeper_access_logs (
timestamp DateTime64(3) DEFAULT now64(3),
request_id String DEFAULT '',
method String DEFAULT '',
path String DEFAULT '',
status UInt16 DEFAULT 0,
latency_ms UInt32 DEFAULT 0,
rp String DEFAULT '',
action String DEFAULT '',
target String DEFAULT '',
subject String DEFAULT '',
client_ip String DEFAULT '',
user_agent String DEFAULT '',
decision String DEFAULT '',
trace_id String DEFAULT '',
span_id String DEFAULT '',
raw String DEFAULT ''
) ENGINE = MergeTree()
ORDER BY (timestamp, request_id)
TTL timestamp + INTERVAL 30 DAY;

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env sh
set -eu
APP_ENV_VALUE="${APP_ENV:-}"
case "$APP_ENV_VALUE" in
production|prod)
RULES_FILE="/etc/config/oathkeeper/rules.prod.json"
;;
stage|staging)
RULES_FILE="/etc/config/oathkeeper/rules.stage.json"
;;
*)
RULES_FILE="/etc/config/oathkeeper/rules.json"
;;
esac
export RULES_FILE
echo "[oathkeeper] APP_ENV=$APP_ENV_VALUE rules=$RULES_FILE"
exec /bin/sh -c "oathkeeper serve proxy -c /etc/config/oathkeeper/oathkeeper.yml 2>&1 | tee /var/log/oathkeeper/access.log"

View File

@@ -4,13 +4,17 @@ serve:
api:
port: 4456
log:
level: info
format: json
errors:
fallback:
- json
access_rules:
repositories:
- file:///etc/config/oathkeeper/rules.json
- file://${RULES_FILE:-/etc/config/oathkeeper/rules.json}
authenticators:
noop:

View File

@@ -0,0 +1,112 @@
[
{
"id": "public-health",
"description": "공개 헬스체크 (TODO: 도메인 제한)",
"match": {
"url": "http://<.*>/health",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트",
"match": {
"url": "http://<.*>/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "http://<.*>/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "http://<.*>/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "kratos-public",
"description": "Kratos Public API를 /kratos로 노출",
"match": {
"url": "http://<.*>/kratos/<.*>",
"methods": ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
},
"upstream": {
"url": "http://kratos:4433",
"strip_path": "/kratos"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "hydra-public",
"description": "Hydra Public API를 /hydra로 노출",
"match": {
"url": "http://<.*>/hydra/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path": "/hydra"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
}
]

View File

@@ -1 +1,92 @@
[]
[
{
"id": "public-health",
"description": "공개 헬스체크",
"match": {
"url": "http://<.*>/health",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "public-preflight",
"description": "CORS preflight",
"match": {
"url": "http://<.*>/api/v1/<.*>",
"methods": ["OPTIONS"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트",
"match": {
"url": "http://<.*>/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "http://<.*>/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "http://<.*>/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
}
]

View File

@@ -0,0 +1,92 @@
[
{
"id": "public-health",
"description": "공개 헬스체크 (PROD 도메인)",
"match": {
"url": "https://auth.brsw.kr/health",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "public-preflight",
"description": "CORS preflight (PROD 도메인)",
"match": {
"url": "https://auth.brsw.kr/api/v1/<.*>",
"methods": ["OPTIONS"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트 (PROD 도메인)",
"match": {
"url": "https://auth.brsw.kr/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "https://auth.brsw.kr/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "https://auth.brsw.kr/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
}
]

View File

@@ -0,0 +1,92 @@
[
{
"id": "public-health",
"description": "공개 헬스체크 (STAGE 도메인)",
"match": {
"url": "https://sso.hmac.kr/health",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "public-preflight",
"description": "CORS preflight (STAGE 도메인)",
"match": {
"url": "https://sso.hmac.kr/api/v1/<.*>",
"methods": ["OPTIONS"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트 (STAGE 도메인)",
"match": {
"url": "https://sso.hmac.kr/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "noop" }
],
"authorizer": { "handler": "allow" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "https://sso.hmac.kr/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
},
{
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "https://sso.hmac.kr/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
"url": "http://baron_backend:3000"
},
"authenticators": [
{ "handler": "cookie_session" }
],
"authorizer": { "handler": "remote_json" },
"mutators": [
{ "handler": "noop" }
]
}
]

View File

@@ -0,0 +1,52 @@
[sources.oathkeeper_file]
type = "file"
include = ["/var/log/oathkeeper/access.log"]
read_from = "beginning"
[transforms.oathkeeper_parse]
type = "remap"
inputs = ["oathkeeper_file"]
source = '''
.raw = .message
parsed = parse_json(.message) ?? {}
.timestamp = to_timestamp(.timestamp) ?? now()
.request_id = parsed.request_id ?? parsed.req_id ?? ""
request_method = get(parsed, ["request", "method"]) ?? ""
request_path = get(parsed, ["request", "path"]) ?? ""
request_url = get(parsed, ["request", "url"]) ?? ""
.method = parsed.method ?? parsed.http_method ?? request_method ?? ""
.path = parsed.path ?? parsed.http_path ?? request_path ?? request_url ?? ""
response_status = get(parsed, ["response", "status"]) ?? 0
.status = to_int(parsed.status ?? parsed.status_code ?? response_status ?? 0) ?? 0
.latency_ms = to_int(parsed.latency_ms ?? parsed.duration_ms ?? parsed.took ?? 0) ?? 0
identity_id = get(parsed, ["identity", "id"]) ?? ""
.subject = parsed.subject ?? identity_id ?? ""
.client_ip = parsed.client_ip ?? parsed.remote_ip ?? parsed.ip ?? ""
headers = get(parsed, ["headers"]) ?? {}
.user_agent = parsed.user_agent
if is_null(.user_agent) { .user_agent = get(headers, ["User-Agent"]) }
if is_null(.user_agent) { .user_agent = "" }
.decision = parsed.decision
if is_null(.decision) { .decision = parsed.result }
if is_null(.decision) { .decision = "" }
.trace_id = parsed.trace_id
if is_null(.trace_id) { .trace_id = "" }
.span_id = parsed.span_id
if is_null(.span_id) { .span_id = "" }
.rp = ""
.action = ""
.target = ""
'''
[sinks.clickhouse]
type = "clickhouse"
inputs = ["oathkeeper_parse"]
endpoint = "http://ory_clickhouse:8123"
database = "ory"
table = "oathkeeper_access_logs"
compression = "gzip"