fix: 对齐 authz 认证链路
This commit is contained in:
+14
-2
@@ -19,11 +19,16 @@ docker compose up -d
|
||||
# 3. 查看状态
|
||||
docker compose ps
|
||||
|
||||
# 4. 停止
|
||||
# 4. 通过网关访问
|
||||
curl http://127.0.0.1:18080/healthz
|
||||
|
||||
# 5. 停止
|
||||
docker compose down
|
||||
```
|
||||
|
||||
构建脚本会扫描 `app/` 下所有 `api`、`rpc`、`mq` 入口,通过 `docker buildx bake` 并行构建所有服务镜像,生成 `juwan/<service>-<type>:dev`。
|
||||
构建脚本会扫描 `app/` 下所有 `api`、`rpc`、`mq`、`adapter` 入口,通过 `docker buildx bake` 并行构建所有服务镜像,生成 `juwan/<service>-<type>:dev`。
|
||||
|
||||
端到端接口测试走网关 `http://127.0.0.1:18080`,`18801-18809` 是各服务的直连端口,不经过认证链路。
|
||||
|
||||
如需只启动部分服务:
|
||||
|
||||
@@ -38,6 +43,7 @@ docker compose up -d postgres redis snowflake player-rpc player-api
|
||||
| PostgreSQL | 15432 |
|
||||
| Redis | 16379 |
|
||||
| Kafka | 19092 |
|
||||
| Envoy Gateway | 18080 |
|
||||
| users-api | 18801 |
|
||||
| player-api | 18802 |
|
||||
| game-api | 18803 |
|
||||
@@ -52,6 +58,12 @@ docker compose up -d postgres redis snowflake player-rpc player-api
|
||||
|
||||
编辑 `.env` 修改数据库密码、Kafka 地址等。默认值可直接用于本地开发。
|
||||
|
||||
## 认证
|
||||
|
||||
登录和注册通过 `users-api` 下发 `JToken` Cookie。`envoy-gateway` 负责 JWT 校验并注入认证头,`authz-adapter` 做会话态二次校验,后端服务只消费 `x-auth-user-id` 等头。
|
||||
|
||||
写接口需要先 `GET /healthz` 领取 `XSRF-TOKEN` 和 `XSRF-GUARD`,再在请求头带上 `xsrf-token`。
|
||||
|
||||
## 数据库初始化
|
||||
|
||||
首次启动时 PostgreSQL 会自动执行 `desc/sql/` 下的建表语句。如需重新初始化,删除 volume 后重启:
|
||||
|
||||
+29
-3
@@ -38,22 +38,48 @@ COPY {service_dir}/etc /app/etc
|
||||
CMD ["./main", "-f", "etc/{config_name}"]
|
||||
"""
|
||||
|
||||
dockerfile_no_config_tpl = """\
|
||||
# syntax=docker/dockerfile:1.7
|
||||
FROM golang:1.25-alpine AS builder
|
||||
RUN apk add --no-cache tzdata
|
||||
WORKDIR /build
|
||||
COPY go.mod go.sum ./
|
||||
RUN --mount=type=cache,target=/go/pkg/mod go mod download
|
||||
COPY . .
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -ldflags="-s -w" -o /app/main ./{service_dir}
|
||||
|
||||
FROM alpine:latest
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
|
||||
ENV TZ=Asia/Shanghai
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/main /app/main
|
||||
CMD ["./main"]
|
||||
"""
|
||||
|
||||
targets = {}
|
||||
for service_dir in sorted(glob.glob("app/*/*")):
|
||||
service_type = os.path.basename(service_dir)
|
||||
if service_type not in ("api", "rpc", "mq"):
|
||||
if service_type not in ("api", "rpc", "mq", "adapter"):
|
||||
continue
|
||||
go_files = glob.glob(os.path.join(service_dir, "*.go"))
|
||||
has_main = any("package main" in open(f).read() for f in go_files) if go_files else False
|
||||
if not has_main:
|
||||
continue
|
||||
yamls = glob.glob(os.path.join(service_dir, "etc", "*.yaml"))
|
||||
config_name = os.path.basename(yamls[0]) if yamls else "config.yaml"
|
||||
service_name = os.path.basename(os.path.dirname(service_dir))
|
||||
target_name = f"{service_name}-{service_type}"
|
||||
|
||||
if yamls:
|
||||
config_name = os.path.basename(yamls[0])
|
||||
dockerfile = dockerfile_tpl.format(service_dir=service_dir, config_name=config_name)
|
||||
else:
|
||||
dockerfile = dockerfile_no_config_tpl.format(service_dir=service_dir)
|
||||
|
||||
targets[target_name] = {
|
||||
"dockerfile-inline": dockerfile_tpl.format(service_dir=service_dir, config_name=config_name),
|
||||
"dockerfile-inline": dockerfile,
|
||||
"tags": [f"{prefix}/{target_name}:{tag}"],
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,53 @@ services:
|
||||
container_name: juwan-snowflake
|
||||
restart: unless-stopped
|
||||
|
||||
authz-adapter:
|
||||
image: juwan/authz-adapter:dev
|
||||
container_name: juwan-authz-adapter
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LISTEN_ON: 0.0.0.0:9002
|
||||
USER_RPC_TARGET: user-rpc:8080
|
||||
depends_on:
|
||||
user-rpc:
|
||||
condition: service_started
|
||||
|
||||
envoy-gateway:
|
||||
image: envoyproxy/envoy:v1.31-latest
|
||||
container_name: juwan-envoy-gateway
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- /usr/local/bin/envoy
|
||||
- -c
|
||||
- /etc/envoy/envoy.yaml
|
||||
- --log-level
|
||||
- info
|
||||
ports:
|
||||
- "18080:8080"
|
||||
volumes:
|
||||
- ./envoy.yaml:/etc/envoy/envoy.yaml:ro
|
||||
depends_on:
|
||||
authz-adapter:
|
||||
condition: service_started
|
||||
users-api:
|
||||
condition: service_started
|
||||
player-api:
|
||||
condition: service_started
|
||||
game-api:
|
||||
condition: service_started
|
||||
shop-api:
|
||||
condition: service_started
|
||||
order-api:
|
||||
condition: service_started
|
||||
wallet-api:
|
||||
condition: service_started
|
||||
community-api:
|
||||
condition: service_started
|
||||
objectstory-api:
|
||||
condition: service_started
|
||||
email-api:
|
||||
condition: service_started
|
||||
|
||||
# ==================== RPC 层 ====================
|
||||
user-rpc:
|
||||
image: juwan/users-rpc:dev
|
||||
|
||||
@@ -0,0 +1,705 @@
|
||||
static_resources:
|
||||
listeners:
|
||||
- name: ingress_http
|
||||
address:
|
||||
socket_address:
|
||||
address: 0.0.0.0
|
||||
port_value: 8080
|
||||
filter_chains:
|
||||
- filters:
|
||||
- name: envoy.filters.network.http_connection_manager
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
|
||||
stat_prefix: ingress_http
|
||||
codec_type: AUTO
|
||||
generate_request_id: true
|
||||
use_remote_address: true
|
||||
route_config:
|
||||
name: local_route
|
||||
virtual_hosts:
|
||||
- name: juwan_services
|
||||
domains: ["*"]
|
||||
routes:
|
||||
- match:
|
||||
path: /healthz
|
||||
direct_response:
|
||||
status: 200
|
||||
body:
|
||||
inline_string: ok
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/auth/login
|
||||
route:
|
||||
cluster: user_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/auth/register
|
||||
route:
|
||||
cluster: user_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/auth/forgot-password
|
||||
route:
|
||||
cluster: user_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/auth/reset-password
|
||||
route:
|
||||
cluster: user_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/auth/forgot-password/send
|
||||
route:
|
||||
cluster: email_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/email/verification-code/send
|
||||
route:
|
||||
cluster: email_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/games
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: game_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/players
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: player_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/services
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: player_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/shops
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: shop_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/shops/[0-9]+$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: shop_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/users/[0-9]+$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: user_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/users/[0-9]+/posts$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: community_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/users/[0-9]+/shop$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: shop_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/posts
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: community_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
path: /api/v1/files
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
route:
|
||||
cluster: objectstory_api_cluster
|
||||
timeout: 30s
|
||||
typed_per_filter_config:
|
||||
envoy.filters.http.ext_authz:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
|
||||
disabled: true
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/auth
|
||||
route:
|
||||
cluster: user_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/users
|
||||
route:
|
||||
cluster: user_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/email
|
||||
route:
|
||||
cluster: email_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/games
|
||||
route:
|
||||
cluster: game_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/players
|
||||
route:
|
||||
cluster: player_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/services
|
||||
route:
|
||||
cluster: player_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/shops
|
||||
route:
|
||||
cluster: shop_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/orders
|
||||
route:
|
||||
cluster: order_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/wallet
|
||||
route:
|
||||
cluster: wallet_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/posts
|
||||
route:
|
||||
cluster: community_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/comments
|
||||
route:
|
||||
cluster: community_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
path: /api/v1/upload
|
||||
route:
|
||||
cluster: objectstory_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /api/v1/files
|
||||
route:
|
||||
cluster: objectstory_api_cluster
|
||||
timeout: 30s
|
||||
|
||||
- match:
|
||||
prefix: /
|
||||
direct_response:
|
||||
status: 404
|
||||
body:
|
||||
inline_string: gateway route not found
|
||||
|
||||
http_filters:
|
||||
- name: envoy.filters.http.lua
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
|
||||
inline_code: |
|
||||
local TOKEN_HEADER = "xsrf-token"
|
||||
local TOKEN_COOKIE = "XSRF-TOKEN"
|
||||
local GUARD_COOKIE = "XSRF-GUARD"
|
||||
|
||||
local seeded = false
|
||||
|
||||
local function seed_random()
|
||||
if seeded then
|
||||
return
|
||||
end
|
||||
seeded = true
|
||||
math.randomseed(os.time())
|
||||
end
|
||||
|
||||
local function split_cookie(header)
|
||||
local out = {}
|
||||
if not header then
|
||||
return out
|
||||
end
|
||||
for pair in string.gmatch(header, "([^;]+)") do
|
||||
local key, value = string.match(pair, "^%s*([^=]+)=?(.*)$")
|
||||
if key ~= nil and value ~= nil then
|
||||
out[string.lower(key)] = value
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local function is_safe_method(method)
|
||||
return method == "GET" or method == "HEAD" or method == "OPTIONS"
|
||||
end
|
||||
|
||||
local function build_token(request_id)
|
||||
seed_random()
|
||||
local rnd = tostring(math.random(100000, 999999))
|
||||
local rid = request_id or "rid"
|
||||
return tostring(os.time()) .. "-" .. rid .. "-" .. rnd
|
||||
end
|
||||
|
||||
function envoy_on_request(request_handle)
|
||||
local headers = request_handle:headers()
|
||||
local method = headers:get(":method")
|
||||
|
||||
local cookie_header = headers:get("cookie")
|
||||
local cookies = split_cookie(cookie_header)
|
||||
local token_cookie = cookies[string.lower(TOKEN_COOKIE)]
|
||||
local guard_cookie = cookies[string.lower(GUARD_COOKIE)]
|
||||
|
||||
request_handle:streamInfo():dynamicMetadata():set("csrf", "need_set_token_cookie", token_cookie == nil or token_cookie == "")
|
||||
request_handle:streamInfo():dynamicMetadata():set("csrf", "need_set_guard_cookie", guard_cookie == nil or guard_cookie == "")
|
||||
|
||||
if token_cookie == nil or token_cookie == "" then
|
||||
token_cookie = build_token(headers:get("x-request-id"))
|
||||
request_handle:streamInfo():dynamicMetadata():set("csrf", "token_value", token_cookie)
|
||||
else
|
||||
request_handle:streamInfo():dynamicMetadata():set("csrf", "token_value", token_cookie)
|
||||
end
|
||||
|
||||
if guard_cookie == nil or guard_cookie == "" then
|
||||
guard_cookie = build_token(headers:get("x-request-id"))
|
||||
request_handle:streamInfo():dynamicMetadata():set("csrf", "guard_value", guard_cookie)
|
||||
else
|
||||
request_handle:streamInfo():dynamicMetadata():set("csrf", "guard_value", guard_cookie)
|
||||
end
|
||||
|
||||
if is_safe_method(method) then
|
||||
return
|
||||
end
|
||||
|
||||
local token_header = headers:get(TOKEN_HEADER)
|
||||
|
||||
if token_header == nil or token_header == "" then
|
||||
request_handle:respond(
|
||||
{[":status"] = "403", ["content-type"] = "application/json"},
|
||||
'{"code":403,"message":"missing XSRF-TOKEN header"}'
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
if token_cookie == nil or token_cookie == "" or guard_cookie == nil or guard_cookie == "" then
|
||||
request_handle:respond(
|
||||
{[":status"] = "403", ["content-type"] = "application/json"},
|
||||
'{"code":403,"message":"missing csrf cookies"}'
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
if token_header ~= token_cookie then
|
||||
request_handle:respond(
|
||||
{[":status"] = "403", ["content-type"] = "application/json"},
|
||||
'{"code":403,"message":"xsrf token mismatch"}'
|
||||
)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function envoy_on_response(response_handle)
|
||||
local metadata = response_handle:streamInfo():dynamicMetadata():get("csrf")
|
||||
if metadata == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local token_value = metadata["token_value"]
|
||||
local guard_value = metadata["guard_value"]
|
||||
|
||||
if metadata["need_set_token_cookie"] == true and token_value ~= nil and token_value ~= "" then
|
||||
response_handle:headers():add(
|
||||
"set-cookie",
|
||||
TOKEN_COOKIE .. "=" .. token_value .. "; Path=/; Max-Age=7200; SameSite=Strict"
|
||||
)
|
||||
end
|
||||
|
||||
if metadata["need_set_guard_cookie"] == true and guard_value ~= nil and guard_value ~= "" then
|
||||
response_handle:headers():add(
|
||||
"set-cookie",
|
||||
GUARD_COOKIE .. "=" .. guard_value .. "; Path=/; Max-Age=7200; SameSite=Strict; HttpOnly"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
- name: envoy.filters.http.jwt_authn
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
|
||||
providers:
|
||||
juwan_user_jwt:
|
||||
issuer: juwan-user-rpc
|
||||
from_cookies:
|
||||
- JToken
|
||||
local_jwks:
|
||||
inline_string: '{"keys":[{"kty":"oct","k":"TUdVeU1XRTNaRGhqTVRRNVpEZzFNV1ZpT1dVME1HTTNPVEUyTldWa1lUQmxPVEU1WldSa1pEVTFZall6T0dKak9XUmlOek0wTlRjNE5ESXlNamxrWlE","alg":"HS256","use":"sig","kid":"juwan-hs256-1"}]}'
|
||||
forward: false
|
||||
claim_to_headers:
|
||||
- header_name: x-auth-user-id
|
||||
claim_name: UserId
|
||||
- header_name: x-auth-is-admin
|
||||
claim_name: IsAdmin
|
||||
rules:
|
||||
- match:
|
||||
path: /healthz
|
||||
- match:
|
||||
prefix: /api/v1
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: OPTIONS
|
||||
- match:
|
||||
path: /api/v1/auth/login
|
||||
- match:
|
||||
path: /api/v1/auth/register
|
||||
- match:
|
||||
path: /api/v1/auth/forgot-password
|
||||
- match:
|
||||
path: /api/v1/auth/reset-password
|
||||
- match:
|
||||
path: /api/v1/auth/forgot-password/send
|
||||
- match:
|
||||
path: /api/v1/email/verification-code/send
|
||||
- match:
|
||||
prefix: /api/v1/games
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
prefix: /api/v1/players
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
prefix: /api/v1/services
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
path: /api/v1/shops
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/shops/[0-9]+$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/users/[0-9]+$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/users/[0-9]+/posts$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
safe_regex:
|
||||
google_re2: {}
|
||||
regex: "^/api/v1/users/[0-9]+/shop$"
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
prefix: /api/v1/posts
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
path: /api/v1/files
|
||||
headers:
|
||||
- name: ":method"
|
||||
exact_match: GET
|
||||
- match:
|
||||
prefix: /api/v1
|
||||
requires:
|
||||
provider_name: juwan_user_jwt
|
||||
|
||||
- name: envoy.filters.http.ext_authz
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
|
||||
transport_api_version: V3
|
||||
failure_mode_allow: false
|
||||
with_request_body:
|
||||
max_request_bytes: 8192
|
||||
allow_partial_message: true
|
||||
grpc_service:
|
||||
envoy_grpc:
|
||||
cluster_name: authz_adapter_cluster
|
||||
timeout: 0.5s
|
||||
|
||||
- name: envoy.filters.http.router
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
|
||||
|
||||
clusters:
|
||||
- name: user_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: user_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: users-api
|
||||
port_value: 8888
|
||||
|
||||
- name: email_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: email_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: email-api
|
||||
port_value: 8888
|
||||
|
||||
- name: player_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: player_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: player-api
|
||||
port_value: 8888
|
||||
|
||||
- name: game_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: game_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: game-api
|
||||
port_value: 8888
|
||||
|
||||
- name: shop_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: shop_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: shop-api
|
||||
port_value: 8888
|
||||
|
||||
- name: order_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: order_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: order-api
|
||||
port_value: 8888
|
||||
|
||||
- name: wallet_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: wallet_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: wallet-api
|
||||
port_value: 8888
|
||||
|
||||
- name: community_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: community_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: community-api
|
||||
port_value: 8888
|
||||
|
||||
- name: objectstory_api_cluster
|
||||
connect_timeout: 2s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
load_assignment:
|
||||
cluster_name: objectstory_api_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: objectstory-api
|
||||
port_value: 8888
|
||||
|
||||
- name: authz_adapter_cluster
|
||||
connect_timeout: 0.5s
|
||||
type: STRICT_DNS
|
||||
lb_policy: ROUND_ROBIN
|
||||
http2_protocol_options: {}
|
||||
load_assignment:
|
||||
cluster_name: authz_adapter_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: authz-adapter
|
||||
port_value: 9002
|
||||
|
||||
admin:
|
||||
access_log_path: /tmp/admin.log
|
||||
address:
|
||||
socket_address:
|
||||
address: 0.0.0.0
|
||||
port_value: 9901
|
||||
@@ -391,7 +391,7 @@ data:
|
||||
from_cookies:
|
||||
- "JToken"
|
||||
local_jwks:
|
||||
inline_string: '{"keys":[{"kty":"oct","k":"MGUyMWE3ZDhjMTQ5ZDg1MWViOWU0MGM3OTE2NWVkYTBlOTE5ZWRkZDU1YjYzOGJjOWRiNzM0NTc4NDIyMjlkZQ","alg":"HS256","use":"sig","kid":"juwan-hs256-1"}]}'
|
||||
inline_string: '{"keys":[{"kty":"oct","k":"TUdVeU1XRTNaRGhqTVRRNVpEZzFNV1ZpT1dVME1HTTNPVEUyTldWa1lUQmxPVEU1WldSa1pEVTFZall6T0dKak9XUmlOek0wTlRjNE5ESXlNamxrWlE","alg":"HS256","use":"sig","kid":"juwan-hs256-1"}]}'
|
||||
forward: false
|
||||
claim_to_headers:
|
||||
- header_name: "x-auth-user-id"
|
||||
|
||||
Reference in New Issue
Block a user