Files
kevinveenbirkenbachandClaude Opus 5.5 b0856dcf7b fix(web-app-snipe-it): bridge the SSO header past v8.8.1's HTTP_ refusal
Snipe-IT v8.8.1 refuses any `login_remote_user_header_name` matching
`/^HTTP_/i`, so the configured `HTTP_X_FORWARDED_PREFERRED_USERNAME`
stopped minting sessions behind oauth2-proxy.

Apache in the image now copies `X-Forwarded-Preferred-Username` into
the server variable `INFINITO_SSO_USER`, and only when the request also
carries `X-Infinito-Sso-Proxy` equal to the new per-inventory
`sso_proxy_secret`; an empty secret keeps the bridge closed. openresty
sends that header on every proxied request, so a client reaching the
container directly cannot log in by forging the identity header. A
deploy-time check asserts both directions (forged 200, with secret 302).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 22:10:23 +02:00

154 lines
5.1 KiB
Django/Jinja

{% include 'roles/sys-svc-container/templates/env.j2' %}
{# nocheck: comments-valid (upstream Snipe-IT .env.example; its section banners are intentional). #}
APP_ENV={{ ENVIRONMENT | lower }}
APP_DEBUG={{MODE_DEBUG | string | lower }}
APP_KEY={{ lookup('config', application_id, 'secrets.credentials.app_key')}}
APP_URL={{ SNIPE_IT_URL | regex_replace('/$', '') }}
APP_TIMEZONE={{ HOST_TIMEZONE | dotenv_quote }}
APP_LOCALE={{ HOST_LL_CC }}
MAX_RESULTS=500
{% if lookup('objstore', application_id, 'enabled') | bool %}
PRIVATE_FILESYSTEM_DISK=s3_private
PUBLIC_FILESYSTEM_DISK=s3_public
{% else %}
PRIVATE_FILESYSTEM_DISK=local
PUBLIC_FILESYSTEM_DISK=local_public
{% endif %}
DB_CONNECTION=mysql
DB_HOST={{ lookup('database', application_id, 'host') }}
DB_PORT={{ lookup('database', application_id, 'port') }}
DB_DATABASE={{ lookup('database', application_id, 'name') }}
DB_USERNAME={{ lookup('database', application_id, 'username') }}
DB_PASSWORD={{ lookup('database', application_id, 'password') | dotenv_quote }}
{% if lookup('database', application_id, 'local') %}
MYSQL_ROOT_PASSWORD={{ lookup('database', application_id, 'password') | dotenv_quote }}
DB_PREFIX=null
DB_DUMP_PATH=/usr/bin
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
{% endif %}
DB_SSL=false
DB_SSL_IS_PAAS=false
DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
DB_SSL_VERIFY_SERVER=null
CACHE_DRIVER=redis
SESSION_DRIVER=redis
REDIS_HOST={{ lookup('engine', 'redis', application_id, 'host') }}
REDIS_PORT={{ lookup('engine', 'redis', application_id, 'port') }}
REDIS_PASSWORD={{ lookup('engine', 'redis', application_id, 'password') | dotenv_quote }}
{% set email = lookup('email', application_id) %}
{% if email.enabled | bool %}
MAIL_MAILER=smtp
MAIL_HOST={{ email.host }}
MAIL_PORT={{ email.port }}
MAIL_USERNAME={{ email.username }}
MAIL_PASSWORD={{ email.password | dotenv_quote }}
MAIL_TLS_VERIFY_PEER={{ email.tls | capitalize }}
MAIL_FROM_ADDR={{ email['from'] }}
MAIL_FROM_NAME={{ (service_provider.company.titel ~ ' - Snipe-IT') | dotenv_quote }}
MAIL_REPLYTO_ADDR={{ email['from'] }}
MAIL_REPLYTO_NAME={{ (service_provider.company.titel ~ ' - Snipe-IT') | dotenv_quote }}
MAIL_AUTO_EMBED_METHOD=attachment
{% endif %}
ALLOW_BACKUP_DELETE=false
ALLOW_DATA_PURGE=false
IMAGE_LIB=gd
MAIL_BACKUP_NOTIFICATION_DRIVER=null
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
BACKUP_ENV=true
SESSION_LIFETIME=12000
EXPIRE_ON_CLOSE=false
ENCRYPT=false
COOKIE_NAME=snipeit_session
COOKIE_DOMAIN=null
SECURE_COOKIES={{ SNIPE_IT_TLS_ENABLED | string | lower }}
API_TOKEN_EXPIRATION_YEARS=40
APP_TRUSTED_PROXIES=**
INFINITO_SSO_PROXY_SECRET={{ SNIPE_IT_SSO_PROXY_SECRET }}
ALLOW_IFRAMING=false
REFERRER_POLICY=same-origin
ENABLE_CSP=false
CORS_ALLOWED_ORIGINS=null
ENABLE_HSTS={{ SNIPE_IT_TLS_ENABLED | string | lower }}
QUEUE_DRIVER=sync
CACHE_PREFIX=snipeit
REDIS_HOST={{ lookup('engine', 'redis', application_id, 'host') }}
REDIS_PASSWORD={{ lookup('engine', 'redis', application_id, 'password') | dotenv_quote }}
REDIS_PORT={{ lookup('engine', 'redis', application_id, 'port') }}
MEMCACHED_HOST=null
MEMCACHED_PORT=null
{% if lookup('objstore', application_id, 'enabled') | bool %}
PUBLIC_AWS_ACCESS_KEY_ID={{ lookup('objstore', application_id, 'access_key') }}
PUBLIC_AWS_SECRET_ACCESS_KEY={{ lookup('objstore', application_id, 'secret_key') }}
PUBLIC_AWS_DEFAULT_REGION={{ lookup('objstore', application_id, 'region') }}
PUBLIC_AWS_BUCKET={{ lookup('objstore', application_id, 'bucket') }}
PUBLIC_AWS_URL={{ lookup('objstore', application_id, 'public_url') }}
PUBLIC_AWS_ENDPOINT={{ lookup('objstore', application_id, 'url') }}
PUBLIC_AWS_PATH_STYLE=true
PUBLIC_AWS_BUCKET_ROOT=public
{% else %}
PUBLIC_AWS_SECRET_ACCESS_KEY=null
PUBLIC_AWS_ACCESS_KEY_ID=null
PUBLIC_AWS_DEFAULT_REGION=null
PUBLIC_AWS_BUCKET=null
PUBLIC_AWS_URL=null
PUBLIC_AWS_ENDPOINT=null
PUBLIC_AWS_PATH_STYLE=null
PUBLIC_AWS_BUCKET_ROOT=null
{% endif %}
{% if lookup('objstore', application_id, 'enabled') | bool %}
PRIVATE_AWS_ACCESS_KEY_ID={{ lookup('objstore', application_id, 'access_key') }}
PRIVATE_AWS_SECRET_ACCESS_KEY={{ lookup('objstore', application_id, 'secret_key') }}
PRIVATE_AWS_DEFAULT_REGION={{ lookup('objstore', application_id, 'region') }}
PRIVATE_AWS_BUCKET={{ lookup('objstore', application_id, 'bucket') }}
PRIVATE_AWS_URL={{ lookup('objstore', application_id, 'url') }}
PRIVATE_AWS_ENDPOINT={{ lookup('objstore', application_id, 'url') }}
PRIVATE_AWS_PATH_STYLE=true
PRIVATE_AWS_BUCKET_ROOT=private
{% else %}
PRIVATE_AWS_ACCESS_KEY_ID=null
PRIVATE_AWS_SECRET_ACCESS_KEY=null
PRIVATE_AWS_DEFAULT_REGION=null
PRIVATE_AWS_BUCKET=null
PRIVATE_AWS_URL=null
PRIVATE_AWS_ENDPOINT=null
PRIVATE_AWS_PATH_STYLE=null
PRIVATE_AWS_BUCKET_ROOT=null
{% endif %}
AWS_ACCESS_KEY_ID=null
AWS_SECRET_ACCESS_KEY=null
AWS_DEFAULT_REGION=null
LOGIN_MAX_ATTEMPTS=5
LOGIN_LOCKOUT_DURATION=60
RESET_PASSWORD_LINK_EXPIRES=900
LOG_CHANNEL=stderr
LOG_MAX_DAYS=10
APP_LOCKED=false
APP_CIPHER=AES-256-CBC
APP_FORCE_TLS={{ lookup('tls', application_id, 'enabled') | string | lower }}
GOOGLE_MAPS_API=
LDAP_MEM_LIM={{ lookup('service_memory_mb', application_id, SNIPE_IT_SERVICE, 0.25) }}M
LDAP_TIME_LIM=600