diff --git a/Caddyfile b/Caddyfile index c9ede64..ad8cc65 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,79 +1,73 @@ { email dead@cxap.space - dns cloudflare {$CF_API_TOKEN} + acme_dns cloudflare {$CF_API_TOKEN} order authenticate before respond - order authorize before respond + order authorize before reverse_proxy servers { trusted_proxies static private_ranges } - certificates { - automate auth.realy.nothing.help - automate *.realy.nothing.help - } -} + security { + local identity store localdb { + realm local + path /data/users.json + } -security { - # Локальное хранилище пользователей - local identity store localdb { - realm local - path /data/users.json - } + authentication portal authportal { + crypto default token lifetime {$AUTH_TOKEN_LIFETIME:43200} + enable identity store localdb - # Портал аутентификации (используем в site-блоке ниже) - authentication portal authportal { - # криптополитика и тайминги - crypto default token lifetime {$AUTH_TOKEN_LIFETIME:-12h} - enable identity store localdb + cookie domain realy.nothing.help + cookie lifetime {$AUTH_COOKIE_LIFETIME:43200} + cookie samesite lax - # единый cookie для всех поддоменов realy.nothing.help - cookie domain realy.nothing.help - cookie lifetime {$AUTH_COOKIE_LIFETIME:-12h} - cookie idle_timeout {$AUTH_IDLE_TIMEOUT:-30m} - cookie samesite lax + ui { + links { + "Portainer" "https://port.realy.nothing.help" icon "las la-tachometer-alt" + "WhoAmI" "/whoami" icon "las la-user" + } + } - ui { - title "Account" - # можно добавить ярлыки на часто используемые сервисы - links { - "Portainer" "https://port.realy.nothing.help" - "WhoAmI" "/whoami" + transform user { + match origin local + action add role admin + # require mfa } } - # Всем локальным пользователям — роль admin + требование MFA - transform user { - match origin local - action add role admin - # require mfa - } - # И базовая роль "user" всем аутентифицированным - transform user { - action add role user + authorization policy apikey_or_admin { + set auth url https://auth.realy.nothing.help + allow roles admin + with api key auth portal authportal realm local + + acl rule { + comment "Accept" + match role admin + allow stop log info + } + acl rule { + comment "Deny" + match any + deny log warn + } } } +} - # Политика для API: либо admin-роль, либо API-ключи портала - authorization policy apikey_or_admin { +(auth_forward) { + authorize with apikey_or_admin { set auth url https://auth.realy.nothing.help - allow roles admin - with api key auth portal authportal realm local - - # Явные ACL с логами - acl rule { comment "Accept" match role admin allow stop log info } - acl rule { comment "Deny" match any deny log warn } + inject headers with claims } } auth.realy.nothing.help { - # сам портал на отдельном хосте route { authenticate with authportal } - # Базовые security-заголовки header { Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" X-Content-Type-Options "nosniff" @@ -82,16 +76,6 @@ auth.realy.nothing.help { } } -# Обычная «пользовательская» защита: просто требует валидную сессию, -# редиректит на портал, прокидывает клеймы в заголовки. -(auth_forward) { - authorize { - set auth url https://auth.realy.nothing.help - inject headers with claims - } -} - -# Защита API: только admin или по API-ключу (policy объявлена выше) -(authorize_apikey_or_admin) { - authorize with apikey_or_admin -} +*.realy.nothing.help { + respond / "ok" +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 183dfcd..b0a06fd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: ports: - "80:80" - "443:443" - - "443:443/udp" # HTTP/3 + - "443:443/udp" environment: - CADDY_INGRESS_NETWORKS=proxy - CF_API_TOKEN=${CF_API_TOKEN} @@ -16,7 +16,7 @@ services: - /var/run/docker.sock:/var/run/docker.sock:ro - caddy_data:/data - ./Caddyfile:/etc/caddy/Caddyfile:ro - - ./users.json:/data/users.json:ro + - ./users.json:/data/users.json networks: [proxy] command: ["caddy","docker-proxy","--caddyfile-path=/etc/caddy/Caddyfile","--docker-sockets","unix:///var/run/docker.sock"] @@ -25,16 +25,14 @@ services: container_name: portainer restart: always expose: - - "9000" # HTTP UI внутрь докера - - "8000" # Edge (если нужен: лучше через NetBird; иначе публикуйте отдельно с FW) + - "9000" + - "8000" volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer_data:/data networks: [proxy] labels: caddy: port.realy.nothing.help - caddy.handle_path: /api/* - caddy.handle_path.0_reverse_proxy: "{{upstreams 9000}}" caddy.encode: zstd gzip caddy.import: auth_forward caddy.reverse_proxy: "{{upstreams 9000}}" diff --git a/users.json b/users.json index ff25a6d..4a5f16a 100644 --- a/users.json +++ b/users.json @@ -1,11 +1,58 @@ { + "version": "1.1.2", + "policy": { + "password": { + "keep_versions": 10, + "min_length": 8, + "max_length": 128, + "require_uppercase": false, + "require_lowercase": false, + "require_number": false, + "require_non_alpha_numeric": false, + "block_reuse": false, + "block_password_change": false + }, + "user": { + "min_length": 3, + "max_length": 50, + "allow_non_alpha_numeric": false, + "allow_uppercase": false + } + }, + "revision": 2, + "last_modified": "2021-10-25T13:04:58.482997492-04:00", "users": [ { + "id": "39555452-454e-4c85-829b-8195a8dd8c81", "username": "deadcxap", - "email": "dead@cxap.space", - "password": "$2b$12$s5SZcTu0THrdIHmdqTIuS.Hb89nokYfwF5xSDPSJPZsKoYnFkv61i", + "email_address": { + "address": "dead@cxap.space", + "domain": "cxap.space" + }, + "email_addresses": [ + { + "address": "dead@cxap.space", + "domain": "cxap.space" + } + ], + "passwords": [ + { + "purpose": "generic", + "algorithm": "bcrypt", + "hash": "$2b$12$s5SZcTu0THrdIHmdqTIuS.Hb89nokYfwF5xSDPSJPZsKoYnFkv61i", + "cost": 10, + "expired_at": "0001-01-01T00:00:00Z", + "created_at": "2021-10-25T17:04:58.4251263Z", + "disabled_at": "0001-01-01T00:00:00Z" + } + ], + "created": "2021-10-25T17:04:58.42512588Z", + "last_modified": "2021-10-25T17:04:58.42512594Z", "roles": [ - "admin" + { + "name": "admin", + "organization": "authp" + } ] } ]