Merge remote-tracking branch 'origin/master' into feat-settings-ui
# Conflicts: # internal/model/webauthn.gopull/4372/head
commit
9b66bb4fe2
|
@ -795,6 +795,34 @@
|
||||||
"contributions": [
|
"contributions": [
|
||||||
"doc"
|
"doc"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "LongerHV",
|
||||||
|
"name": "Michał Mieszczak",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/46924944?v=4",
|
||||||
|
"profile": "https://github.com/LongerHV",
|
||||||
|
"contributions": [
|
||||||
|
"ideas",
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "paul-ohl",
|
||||||
|
"name": "Paul Ohl",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/37795294?v=4",
|
||||||
|
"profile": "https://github.com/paul-ohl",
|
||||||
|
"contributions": [
|
||||||
|
"doc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "smkent",
|
||||||
|
"name": "Stephen Kent",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/2831985?v=4",
|
||||||
|
"profile": "https://github.com/smkent",
|
||||||
|
"contributions": [
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7
|
"contributorsPerLine": 7
|
||||||
|
|
|
@ -16,10 +16,12 @@ coverage:
|
||||||
default: false
|
default: false
|
||||||
backend:
|
backend:
|
||||||
base: auto
|
base: auto
|
||||||
|
threshold: 0.15%
|
||||||
flags:
|
flags:
|
||||||
- backend
|
- backend
|
||||||
frontend:
|
frontend:
|
||||||
base: auto
|
base: auto
|
||||||
|
threshold: 0.15%
|
||||||
flags:
|
flags:
|
||||||
- frontend
|
- frontend
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
description: Report a bug
|
||||||
|
labels:
|
||||||
|
- type/bug/unconfirmed
|
||||||
|
- status/needs-triage
|
||||||
|
- priority/4/normal
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report. If you are unsure if this is actually a bug we generally recommend creating a [Question and Answer Discussion](https://github.com/authelia/authelia/discussions/new?category=q-a) first.
|
||||||
|
|
||||||
|
Please review the following requirements before submitting this issue type:
|
||||||
|
|
||||||
|
1. Please ensure you do not report security vulnerabilities via this method. See our [Security Policy](https://www.authelia.com/security-policy).
|
||||||
|
2. Please try to give as much information as possible for us to be able to reproduce the issue and provide a quick fix.
|
||||||
|
3. Please ensure an issue does not already exist for this potential bug.
|
||||||
|
4. Please only provide specific versions. Latest is not a version.
|
||||||
|
5. Please read the [Troubleshooting Sanitization](https://www.authelia.com/r/sanitize) reference guide if you plan on removing or adjusting any values for the logs or configuration files.
|
||||||
|
6. Please consider including a [HTTP Archive File](https://www.authelia.com/r/har) if you're having redirection issues.
|
||||||
|
- type: dropdown
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
description: What version(s) of Authelia can you reproduce this bug on?
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
- v4.37.2
|
||||||
|
- v4.37.1
|
||||||
|
- v4.37.0
|
||||||
|
- v4.36.9
|
||||||
|
- v4.36.8
|
||||||
|
- v4.36.7
|
||||||
|
- v4.36.6
|
||||||
|
- v4.36.5
|
||||||
|
- v4.36.4
|
||||||
|
- v4.36.3
|
||||||
|
- v4.36.2
|
||||||
|
- v4.36.1
|
||||||
|
- v4.36.0
|
||||||
|
- v4.35.6
|
||||||
|
- v4.35.5
|
||||||
|
- v4.35.4
|
||||||
|
- v4.35.3
|
||||||
|
- v4.35.2
|
||||||
|
- v4.35.1
|
||||||
|
- v4.35.0
|
||||||
|
- v4.34.6
|
||||||
|
- v4.34.5
|
||||||
|
- v4.34.4
|
||||||
|
- v4.34.3
|
||||||
|
- v4.34.2
|
||||||
|
- v4.34.1
|
||||||
|
- v4.34.0
|
||||||
|
- v4.33.2
|
||||||
|
- v4.33.1
|
||||||
|
- v4.33.0
|
||||||
|
- v4.32.2
|
||||||
|
- v4.32.1
|
||||||
|
- v4.32.0
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: deployment
|
||||||
|
attributes:
|
||||||
|
label: Deployment Method
|
||||||
|
description: How are you deploying Authelia?
|
||||||
|
options:
|
||||||
|
- Docker
|
||||||
|
- Kubernetes
|
||||||
|
- Bare-metal
|
||||||
|
- Other
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: proxy
|
||||||
|
attributes:
|
||||||
|
label: Reverse Proxy
|
||||||
|
description: What reverse proxy are you using?
|
||||||
|
options:
|
||||||
|
- Caddy
|
||||||
|
- Traefik
|
||||||
|
- Envoy
|
||||||
|
- Istio
|
||||||
|
- NGINX
|
||||||
|
- SWAG
|
||||||
|
- NGINX Proxy Manager
|
||||||
|
- HAProxy
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: proxy-version
|
||||||
|
attributes:
|
||||||
|
label: Reverse Proxy Version
|
||||||
|
description: What is the version of your reverse proxy?
|
||||||
|
placeholder: x.x.x
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Describe the bug
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Reproduction
|
||||||
|
description: Describe how we can reproduce this issue
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expectations
|
||||||
|
attributes:
|
||||||
|
label: Expectations
|
||||||
|
description: Describe the desired or expected results
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Logs
|
||||||
|
description: Provide the logs (the template will automatically put this content in a code block)
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: configuration
|
||||||
|
attributes:
|
||||||
|
label: Configuration
|
||||||
|
description: Provide the Authelia configuration file (the template will automatically put this content in a code block)
|
||||||
|
render: yaml
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: documentation
|
||||||
|
attributes:
|
||||||
|
label: Documentation
|
||||||
|
description: Provide any relevant specification or other documentation if applicable
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
...
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug Report
|
|
||||||
about: Use this template to report bugs other than security vulnerabilities
|
|
||||||
labels: Possible Bug
|
|
||||||
---
|
|
||||||
## Bug Report
|
|
||||||
<!--
|
|
||||||
1. IMPORTANT: Do not report security vulnerabilities via GitHub issues. Please click 'choose a different type' and see
|
|
||||||
the dedicated report a security vulnerability link.
|
|
||||||
2. Remember to customize the title above.
|
|
||||||
3. Replace the below sections (not this section) starting with <!- - and ending with - -> with relevant information,
|
|
||||||
making sure to remove the <!- - and - ->.
|
|
||||||
4. Sections that start with _N/A_ are optional, but if you populate them with values please remove the _N/A_.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Describe the bug here.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Expected Behaviour
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
<!--
|
|
||||||
Describe the behaviour your expect here.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Reproduction Steps
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
<!--
|
|
||||||
1. Replace this step with your first step. Add additional steps below this.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Additional Information
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
<!--
|
|
||||||
This section is for relevant additional information like; logs, configurations, environment information, etc.
|
|
||||||
-->
|
|
|
@ -1,6 +1,15 @@
|
||||||
---
|
---
|
||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
|
- name: Idea
|
||||||
|
url: https://github.com/authelia/authelia/discussions/new?category=ideas
|
||||||
|
about: Submit an Idea for Voting
|
||||||
|
- name: Question
|
||||||
|
url: https://github.com/authelia/authelia/discussions/new?category=q-a
|
||||||
|
about: Ask a Question
|
||||||
|
- name: Discussion
|
||||||
|
url: https://github.com/authelia/authelia/discussions/new
|
||||||
|
about: Start a Discussion related to Ideas, Polls, Show and Tell, or General Topics
|
||||||
- name: Documentation
|
- name: Documentation
|
||||||
url: https://www.authelia.com/
|
url: https://www.authelia.com/
|
||||||
about: Read the Documentation
|
about: Read the Documentation
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
description: Submit a Feature Request
|
||||||
|
labels:
|
||||||
|
- type/feature
|
||||||
|
- status/needs-design
|
||||||
|
- priority/4/normal
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this feature request. A feature request is created as issue for the purpose of tracking the design and implementation of a feature.
|
||||||
|
|
||||||
|
Please review the following requirements before submitting this issue type:
|
||||||
|
|
||||||
|
1. Ensure there are no other similar feature requests.
|
||||||
|
2. Make sure you've checked the [Documentation](https://www.authelia.com) doesn't clearly document the features existence already.
|
||||||
|
3. Consider creating an [Idea Discussion](https://github.com/authelia/authelia/discussions/new?category=ideas) which can be voted on instead if one doesn't exist.
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Describe the feature
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: use-case
|
||||||
|
attributes:
|
||||||
|
label: Use Case
|
||||||
|
description: Provide a use case
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: details
|
||||||
|
attributes:
|
||||||
|
label: Details
|
||||||
|
description: Describe the feature in detail
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: documentation
|
||||||
|
attributes:
|
||||||
|
label: Documentation
|
||||||
|
description: Provide any relevant specification or other documentation if applicable
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
...
|
|
@ -1,26 +0,0 @@
|
||||||
---
|
|
||||||
name: Feature Request
|
|
||||||
about: Use this template to request features
|
|
||||||
labels: Feature Request
|
|
||||||
---
|
|
||||||
## Feature Request
|
|
||||||
<!--
|
|
||||||
1. IMPORTANT: Do not report security vulnerabilities via GitHub issues. Please click 'choose a different type' and see the dedicated report a security vulnerability link.
|
|
||||||
2. Remember to customize the title above.
|
|
||||||
3. Replace the below sections (not this section) starting with <!- - and ending with - -> with relevant information,
|
|
||||||
making sure to remove the <!- - and - ->.
|
|
||||||
4. Sections that start with _N/A_ are optional, but if you populate them with values please remove the _N/A_.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Describe the feature here.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Use Case
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
<!--
|
|
||||||
Describe the specific use case if it isn't clear or may not be clear from your feature description here.
|
|
||||||
-->
|
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
name: Miscellaneous
|
|
||||||
about: Use this template for everything other than feature requests, security vulnerabilities, or bug reports such as questions
|
|
||||||
---
|
|
||||||
<!--
|
|
||||||
IMPORTANT: Do not report security vulnerabilities via GitHub issues. Please click 'choose a different type' and see the dedicated report a security vulnerability link.
|
|
||||||
-->
|
|
|
@ -1,7 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [[ ! -z "$NO_HOOK" ]]
|
if [ -n "$NO_HOOK" ]; then
|
||||||
then
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -9,4 +8,4 @@ fi
|
||||||
. "$(dirname "$0")/required-apps"
|
. "$(dirname "$0")/required-apps"
|
||||||
|
|
||||||
golangci-lint run -v --fix && \
|
golangci-lint run -v --fix && \
|
||||||
cd web && ${PMGR} lint
|
cd web && "${PMGR}" lint
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
PMGR=pnpm
|
export PMGR=pnpm
|
||||||
|
|
||||||
if [[ ! -x "$(command -v golangci-lint)" ]]; then
|
if [ ! -x "$(command -v golangci-lint)" ]; then
|
||||||
echo "You must install golangci-lint."
|
echo "You must install golangci-lint."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -x "$(command -v pnpm)" ]]; then
|
if [ ! -x "$(command -v pnpm)" ]; then
|
||||||
PMGR=yarn
|
export PMGR=yarn
|
||||||
if [[ ! -x "$(command -v yarn)" ]]; then
|
if [ ! -x "$(command -v yarn)" ]; then
|
||||||
PMGR=npm
|
export PMGR=npm
|
||||||
if [[ ! -x "$(command -v npm)" ]]; then
|
if [ ! -x "$(command -v npm)" ]; then
|
||||||
echo "You must install a node package manager."
|
echo "You must install a node package manager."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
23
.renovaterc
23
.renovaterc
|
@ -2,16 +2,16 @@
|
||||||
"extends": [
|
"extends": [
|
||||||
"config:base",
|
"config:base",
|
||||||
":semanticCommitTypeAll(build)",
|
":semanticCommitTypeAll(build)",
|
||||||
":separatePatchReleases"
|
":separatePatchReleases",
|
||||||
|
"workarounds:doNotUpgradeFromAlpineStableToEdge"
|
||||||
],
|
],
|
||||||
"ignorePaths": [
|
"ignorePaths": [
|
||||||
"docs/**"
|
"docs/**"
|
||||||
],
|
],
|
||||||
"ignorePresets": [
|
"ignorePresets": [
|
||||||
":combinePatchMinorReleases",
|
|
||||||
"helpers:disableTypesNodeMajor",
|
|
||||||
":prHourlyLimit2",
|
":prHourlyLimit2",
|
||||||
":semanticPrefixFixDepsChoreOthers"
|
":semanticPrefixFixDepsChoreOthers",
|
||||||
|
"workarounds:all"
|
||||||
],
|
],
|
||||||
"enabledManagers": [
|
"enabledManagers": [
|
||||||
"bundler",
|
"bundler",
|
||||||
|
@ -24,6 +24,13 @@
|
||||||
"dependencies"
|
"dependencies"
|
||||||
],
|
],
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchUpdateTypes": ["digest", "minor", "patch"],
|
||||||
|
"matchCurrentVersion": "!/^0/",
|
||||||
|
"automerge": true,
|
||||||
|
"automergeType": "pr",
|
||||||
|
"platformAutomerge": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"datasources": [
|
"datasources": [
|
||||||
"docker"
|
"docker"
|
||||||
|
@ -47,14 +54,6 @@
|
||||||
"addLabels": [
|
"addLabels": [
|
||||||
"javascript"
|
"javascript"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"datasources": [
|
|
||||||
"rubygems"
|
|
||||||
],
|
|
||||||
"addLabels": [
|
|
||||||
"ruby"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"postUpdateOptions": [
|
"postUpdateOptions": [
|
||||||
|
|
|
@ -6,7 +6,8 @@ ignore: |
|
||||||
internal/configuration/test_resources/config_bad_quoting.yml
|
internal/configuration/test_resources/config_bad_quoting.yml
|
||||||
web/pnpm-lock.yaml
|
web/pnpm-lock.yaml
|
||||||
web/node_modules/
|
web/node_modules/
|
||||||
|
.github/ISSUE_TEMPLATE/feature-request.yml
|
||||||
|
.github/ISSUE_TEMPLATE/bug-report.yml
|
||||||
rules:
|
rules:
|
||||||
document-end:
|
document-end:
|
||||||
level: warning
|
level: warning
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# ========================================
|
# ========================================
|
||||||
# ===== Build image for the frontend =====
|
# ===== Build image for the frontend =====
|
||||||
# ========================================
|
# ========================================
|
||||||
FROM node:18-alpine AS builder-frontend
|
FROM node:19-alpine AS builder-frontend
|
||||||
|
|
||||||
WORKDIR /node/src/app
|
WORKDIR /node/src/app
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
|
||||||
# =======================================
|
# =======================================
|
||||||
# ===== Build image for the backend =====
|
# ===== Build image for the backend =====
|
||||||
# =======================================
|
# =======================================
|
||||||
FROM golang:1.19.1-alpine AS builder-backend
|
FROM golang:1.19.3-alpine AS builder-backend
|
||||||
|
|
||||||
WORKDIR /go/src/app
|
WORKDIR /go/src/app
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# ========================================
|
# ========================================
|
||||||
# ===== Build image for the frontend =====
|
# ===== Build image for the frontend =====
|
||||||
# ========================================
|
# ========================================
|
||||||
FROM node:18-alpine AS builder-frontend
|
FROM node:19-alpine AS builder-frontend
|
||||||
|
|
||||||
WORKDIR /node/src/app
|
WORKDIR /node/src/app
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ RUN yarn install --frozen-lockfile && yarn build
|
||||||
# =======================================
|
# =======================================
|
||||||
# ===== Build image for the backend =====
|
# ===== Build image for the backend =====
|
||||||
# =======================================
|
# =======================================
|
||||||
FROM golang:1.19.1-alpine AS builder-backend
|
FROM golang:1.19.3-alpine AS builder-backend
|
||||||
|
|
||||||
WORKDIR /go/src/app
|
WORKDIR /go/src/app
|
||||||
|
|
||||||
|
|
268
README.md
268
README.md
|
@ -16,9 +16,8 @@
|
||||||
[![Matrix](https://img.shields.io/matrix/authelia-support:matrix.org?label=matrix&logo=matrix&style=flat-square&color=blue)](https://matrix.to/#/#support:authelia.com)
|
[![Matrix](https://img.shields.io/matrix/authelia-support:matrix.org?label=matrix&logo=matrix&style=flat-square&color=blue)](https://matrix.to/#/#support:authelia.com)
|
||||||
|
|
||||||
**Authelia** is an open-source authentication and authorization server providing two-factor authentication and single
|
**Authelia** is an open-source authentication and authorization server providing two-factor authentication and single
|
||||||
sign-on (SSO) for your applications via a web portal. It acts as a companion for reverse proxies like [nginx],
|
sign-on (SSO) for your applications via a web portal. It acts as a companion for [reverse proxies](#proxy-support) by
|
||||||
[Traefik], [caddy] or [HAProxy] to let them know whether requests should either be allowed or redirected to Authelia's
|
allowing, denying, or redirecting requests.
|
||||||
portal for authentication.
|
|
||||||
|
|
||||||
Documentation is available at [https://www.authelia.com/](https://www.authelia.com/).
|
Documentation is available at [https://www.authelia.com/](https://www.authelia.com/).
|
||||||
|
|
||||||
|
@ -31,9 +30,12 @@ The following is a simple diagram of the architecture:
|
||||||
**Authelia** can be installed as a standalone service from the [AUR](https://aur.archlinux.org/packages/authelia/),
|
**Authelia** can be installed as a standalone service from the [AUR](https://aur.archlinux.org/packages/authelia/),
|
||||||
[APT](https://apt.authelia.com/stable/debian/packages/authelia/),
|
[APT](https://apt.authelia.com/stable/debian/packages/authelia/),
|
||||||
[FreeBSD Ports](https://svnweb.freebsd.org/ports/head/www/authelia/), or using a
|
[FreeBSD Ports](https://svnweb.freebsd.org/ports/head/www/authelia/), or using a
|
||||||
[Static binary](https://github.com/authelia/authelia/releases/latest),
|
[static binary](https://github.com/authelia/authelia/releases/latest),
|
||||||
[.deb package]((https://github.com/authelia/authelia/releases/latest)), [Docker] or [Kubernetes] either manually or via
|
[.deb package]((https://github.com/authelia/authelia/releases/latest)), as a container on [Docker] or [Kubernetes].
|
||||||
the Helm [Chart](https://charts.authelia.com) (beta) leveraging ingress controllers and ingress configurations.
|
|
||||||
|
|
||||||
|
Deployment can be orchestrated via the Helm [Chart](https://charts.authelia.com) (beta) leveraging ingress controllers
|
||||||
|
and ingress configurations.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="./docs/static/images/logos/kubernetes.png" height="100"/>
|
<img src="./docs/static/images/logos/kubernetes.png" height="100"/>
|
||||||
|
@ -70,13 +72,14 @@ This is a list of the key features of Authelia:
|
||||||
* Curated configuration from [LinuxServer](https://www.linuxserver.io/) via their
|
* Curated configuration from [LinuxServer](https://www.linuxserver.io/) via their
|
||||||
[Swag](https://docs.linuxserver.io/general/swag) container as well as a
|
[Swag](https://docs.linuxserver.io/general/swag) container as well as a
|
||||||
[guide](https://blog.linuxserver.io/2020/08/26/setting-up-authelia/).
|
[guide](https://blog.linuxserver.io/2020/08/26/setting-up-authelia/).
|
||||||
* Compatible with [caddy] using the [forward_auth](https://caddyserver.com/docs/caddyfile/directives/forward_auth)
|
* Compatible with [Caddy] using the [forward_auth](https://caddyserver.com/docs/caddyfile/directives/forward_auth)
|
||||||
directive.
|
directive.
|
||||||
* Kubernetes Support:
|
* Kubernetes Support:
|
||||||
* Compatible with the [ingress-nginx](https://github.com/kubernetes/ingress-nginx), the
|
* Compatible with several Kubernetes ingress controllers:
|
||||||
[Traefik Kubernetes CRD](https://doc.traefik.io/traefik/providers/kubernetes-crd/), and the
|
* [ingress-nginx](https://www.authelia.com/integration/kubernetes/nginx-ingress/)
|
||||||
[Traefik Kubernetes Ingress](https://doc.traefik.io/traefik/providers/kubernetes-crd/) Kubernetes ingress
|
* [Traefik Kubernetes CRD](https://www.authelia.com/integration/kubernetes/traefik-ingress/#ingressroute)
|
||||||
controllers out of the box.
|
* [Traefik Kubernetes Ingress](https://www.authelia.com/integration/kubernetes/traefik-ingress/#ingress)
|
||||||
|
* [Istio](https://www.authelia.com/integration/kubernetes/istio/)
|
||||||
* Beta support for installing via Helm using our [Charts](https://charts.authelia.com).
|
* Beta support for installing via Helm using our [Charts](https://charts.authelia.com).
|
||||||
* Beta support for [OpenID Connect](https://www.authelia.com/roadmap/active/openid-connect/).
|
* Beta support for [OpenID Connect](https://www.authelia.com/roadmap/active/openid-connect/).
|
||||||
|
|
||||||
|
@ -86,22 +89,14 @@ If you want to know more about the roadmap, follow [Roadmap](https://www.autheli
|
||||||
|
|
||||||
## Proxy support
|
## Proxy support
|
||||||
|
|
||||||
Authelia works in combination with [nginx], [Traefik], [caddy] or [HAProxy]. It can be deployed on bare metal with
|
Authelia works in combination with [nginx], [Traefik], [Caddy], [Skipper], [Envoy], or [HAProxy].
|
||||||
Docker or on top of [Kubernetes].
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="./docs/static/images/logos/nginx.png" height="50"/>
|
<img src="./docs/static/images/logos/nginx.png" height="50"/>
|
||||||
<img src="./docs/static/images/logos/traefik.png" height="50"/>
|
<img src="./docs/static/images/logos/traefik.png" height="50"/>
|
||||||
<img src="./docs/static/images/logos/caddy.png" height="50"/>
|
<img src="./docs/static/images/logos/caddy.png" height="50"/>
|
||||||
<img src="./docs/static/images/logos/haproxy.png" height="50"/>
|
|
||||||
<img src="./docs/static/images/logos/kubernetes.png" height="50"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
***Help Wanted:*** Assistance would be appreciated in getting Authelia working with
|
|
||||||
[Envoy](https://www.envoyproxy.io/).
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="./docs/static/images/logos/envoy.png" height="50"/>
|
<img src="./docs/static/images/logos/envoy.png" height="50"/>
|
||||||
|
<img src="./docs/static/images/logos/haproxy.png" height="50"/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
@ -200,113 +195,120 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||||
<!-- prettier-ignore-start -->
|
<!-- prettier-ignore-start -->
|
||||||
<!-- markdownlint-disable -->
|
<!-- markdownlint-disable -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tbody>
|
||||||
<td align="center"><a href="https://github.com/clems4ever"><img src="https://avatars.githubusercontent.com/u/3193257?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Clément Michaud</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=clems4ever" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=clems4ever" title="Documentation">📖</a> <a href="#ideas-clems4ever" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-clems4ever" title="Maintenance">🚧</a> <a href="#question-clems4ever" title="Answering Questions">💬</a> <a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3Aclems4ever" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/authelia/authelia/commits?author=clems4ever" title="Tests">⚠️</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/nightah"><img src="https://avatars.githubusercontent.com/u/3339418?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amir Zarrinkafsh</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=nightah" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=nightah" title="Documentation">📖</a> <a href="#ideas-nightah" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-nightah" title="Maintenance">🚧</a> <a href="#question-nightah" title="Answering Questions">💬</a> <a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3Anightah" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/authelia/authelia/commits?author=nightah" title="Tests">⚠️</a></td>
|
<td align="center"><a href="https://github.com/clems4ever"><img src="https://avatars.githubusercontent.com/u/3193257?v=4?s=100" width="100px;" alt="Clément Michaud"/><br /><sub><b>Clément Michaud</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=clems4ever" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=clems4ever" title="Documentation">📖</a> <a href="#ideas-clems4ever" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-clems4ever" title="Maintenance">🚧</a> <a href="#question-clems4ever" title="Answering Questions">💬</a> <a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3Aclems4ever" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/authelia/authelia/commits?author=clems4ever" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="https://github.com/james-d-elliott"><img src="https://avatars.githubusercontent.com/u/3903683?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Elliott</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=james-d-elliott" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=james-d-elliott" title="Documentation">📖</a> <a href="#ideas-james-d-elliott" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-james-d-elliott" title="Maintenance">🚧</a> <a href="#question-james-d-elliott" title="Answering Questions">💬</a> <a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3Ajames-d-elliott" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/authelia/authelia/commits?author=james-d-elliott" title="Tests">⚠️</a></td>
|
<td align="center"><a href="https://github.com/nightah"><img src="https://avatars.githubusercontent.com/u/3339418?v=4?s=100" width="100px;" alt="Amir Zarrinkafsh"/><br /><sub><b>Amir Zarrinkafsh</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=nightah" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=nightah" title="Documentation">📖</a> <a href="#ideas-nightah" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-nightah" title="Maintenance">🚧</a> <a href="#question-nightah" title="Answering Questions">💬</a> <a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3Anightah" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/authelia/authelia/commits?author=nightah" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="https://github.com/n4kre"><img src="https://avatars.githubusercontent.com/u/14371127?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Antoine Favre</b></sub></a><br /><a href="https://github.com/authelia/authelia/issues?q=author%3An4kre" title="Bug reports">🐛</a> <a href="#ideas-n4kre" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center"><a href="https://github.com/james-d-elliott"><img src="https://avatars.githubusercontent.com/u/3903683?v=4?s=100" width="100px;" alt="James Elliott"/><br /><sub><b>James Elliott</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=james-d-elliott" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=james-d-elliott" title="Documentation">📖</a> <a href="#ideas-james-d-elliott" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-james-d-elliott" title="Maintenance">🚧</a> <a href="#question-james-d-elliott" title="Answering Questions">💬</a> <a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3Ajames-d-elliott" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/authelia/authelia/commits?author=james-d-elliott" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="https://github.com/BankaiNoJutsu"><img src="https://avatars.githubusercontent.com/u/2241519?v=4?s=100" width="100px;" alt=""/><br /><sub><b>BankaiNoJutsu</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=BankaiNoJutsu" title="Code">💻</a> <a href="#design-BankaiNoJutsu" title="Design">🎨</a></td>
|
<td align="center"><a href="https://github.com/n4kre"><img src="https://avatars.githubusercontent.com/u/14371127?v=4?s=100" width="100px;" alt="Antoine Favre"/><br /><sub><b>Antoine Favre</b></sub></a><br /><a href="https://github.com/authelia/authelia/issues?q=author%3An4kre" title="Bug reports">🐛</a> <a href="#ideas-n4kre" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
<td align="center"><a href="https://github.com/p-rintz"><img src="https://avatars.githubusercontent.com/u/13933258?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Philipp Rintz</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=p-rintz" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/BankaiNoJutsu"><img src="https://avatars.githubusercontent.com/u/2241519?v=4?s=100" width="100px;" alt="BankaiNoJutsu"/><br /><sub><b>BankaiNoJutsu</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=BankaiNoJutsu" title="Code">💻</a> <a href="#design-BankaiNoJutsu" title="Design">🎨</a></td>
|
||||||
<td align="center"><a href="http://callanbryant.co.uk/"><img src="https://avatars.githubusercontent.com/u/208440?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Callan Bryant</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=naggie" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=naggie" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/p-rintz"><img src="https://avatars.githubusercontent.com/u/13933258?v=4?s=100" width="100px;" alt="Philipp Rintz"/><br /><sub><b>Philipp Rintz</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=p-rintz" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="http://callanbryant.co.uk/"><img src="https://avatars.githubusercontent.com/u/208440?v=4?s=100" width="100px;" alt="Callan Bryant"/><br /><sub><b>Callan Bryant</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=naggie" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=naggie" title="Documentation">📖</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/ViViDboarder"><img src="https://avatars.githubusercontent.com/u/137025?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ian</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ViViDboarder" title="Code">💻</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/FrozenDragoon"><img src="https://avatars.githubusercontent.com/u/5301673?v=4?s=100" width="100px;" alt=""/><br /><sub><b>FrozenDragoon</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=FrozenDragoon" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/ViViDboarder"><img src="https://avatars.githubusercontent.com/u/137025?v=4?s=100" width="100px;" alt="Ian"/><br /><sub><b>Ian</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ViViDboarder" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/vdot0x23"><img src="https://avatars.githubusercontent.com/u/40716069?v=4?s=100" width="100px;" alt=""/><br /><sub><b>vdot0x23</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=vdot0x23" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/FrozenDragoon"><img src="https://avatars.githubusercontent.com/u/5301673?v=4?s=100" width="100px;" alt="FrozenDragoon"/><br /><sub><b>FrozenDragoon</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=FrozenDragoon" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/alexw1982"><img src="https://avatars.githubusercontent.com/u/11628284?v=4?s=100" width="100px;" alt=""/><br /><sub><b>alexw1982</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=alexw1982" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/vdot0x23"><img src="https://avatars.githubusercontent.com/u/40716069?v=4?s=100" width="100px;" alt="vdot0x23"/><br /><sub><b>vdot0x23</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=vdot0x23" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Sohalt"><img src="https://avatars.githubusercontent.com/u/2157287?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sohalt</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Sohalt" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=Sohalt" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/alexw1982"><img src="https://avatars.githubusercontent.com/u/11628284?v=4?s=100" width="100px;" alt="alexw1982"/><br /><sub><b>alexw1982</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=alexw1982" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/Tedyst"><img src="https://avatars.githubusercontent.com/u/13637623?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stoica Tedy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Tedyst" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Sohalt"><img src="https://avatars.githubusercontent.com/u/2157287?v=4?s=100" width="100px;" alt="Sohalt"/><br /><sub><b>Sohalt</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Sohalt" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=Sohalt" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/Chemsmith"><img src="https://avatars.githubusercontent.com/u/9061024?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dylan Smith</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Chemsmith" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Tedyst"><img src="https://avatars.githubusercontent.com/u/13637623?v=4?s=100" width="100px;" alt="Stoica Tedy"/><br /><sub><b>Stoica Tedy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Tedyst" title="Code">💻</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/Chemsmith"><img src="https://avatars.githubusercontent.com/u/9061024?v=4?s=100" width="100px;" alt="Dylan Smith"/><br /><sub><b>Dylan Smith</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Chemsmith" title="Code">💻</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/LukasK13"><img src="https://avatars.githubusercontent.com/u/24586740?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lukas Klass</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=LukasK13" title="Documentation">📖</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://staiger.it/"><img src="https://avatars.githubusercontent.com/u/9325003?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Philipp Staiger</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=lippl" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=lippl" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=lippl" title="Tests">⚠️</a></td>
|
<td align="center"><a href="https://github.com/LukasK13"><img src="https://avatars.githubusercontent.com/u/24586740?v=4?s=100" width="100px;" alt="Lukas Klass"/><br /><sub><b>Lukas Klass</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=LukasK13" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://yaleman.org/"><img src="https://avatars.githubusercontent.com/u/168188?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Hodgkinson</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=yaleman" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://staiger.it/"><img src="https://avatars.githubusercontent.com/u/9325003?v=4?s=100" width="100px;" alt="Philipp Staiger"/><br /><sub><b>Philipp Staiger</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=lippl" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=lippl" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=lippl" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="https://chris.smith.xyz/"><img src="https://avatars.githubusercontent.com/u/1979423?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Smith</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=chris13524" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://yaleman.org/"><img src="https://avatars.githubusercontent.com/u/168188?v=4?s=100" width="100px;" alt="James Hodgkinson"/><br /><sub><b>James Hodgkinson</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=yaleman" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/mqmq0"><img src="https://avatars.githubusercontent.com/u/13240971?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mihály</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=mqmq0" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://chris.smith.xyz/"><img src="https://avatars.githubusercontent.com/u/1979423?v=4?s=100" width="100px;" alt="Chris Smith"/><br /><sub><b>Chris Smith</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=chris13524" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://iret.xyz/"><img src="https://avatars.githubusercontent.com/u/6560655?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Silver Bullet</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=SilverBut" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/mqmq0"><img src="https://avatars.githubusercontent.com/u/13240971?v=4?s=100" width="100px;" alt="Mihály"/><br /><sub><b>Mihály</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=mqmq0" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/skenmy"><img src="https://avatars.githubusercontent.com/u/1454505?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Paul Williams</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=skenmy" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=skenmy" title="Tests">⚠️</a></td>
|
<td align="center"><a href="https://iret.xyz/"><img src="https://avatars.githubusercontent.com/u/6560655?v=4?s=100" width="100px;" alt="Silver Bullet"/><br /><sub><b>Silver Bullet</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=SilverBut" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/skenmy"><img src="https://avatars.githubusercontent.com/u/1454505?v=4?s=100" width="100px;" alt="Paul Williams"/><br /><sub><b>Paul Williams</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=skenmy" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=skenmy" title="Tests">⚠️</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/ntimo"><img src="https://avatars.githubusercontent.com/u/6145026?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Timo</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ntimo" title="Documentation">📖</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/andrewkliskey"><img src="https://avatars.githubusercontent.com/u/44645768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Kliskey</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=andrewkliskey" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/ntimo"><img src="https://avatars.githubusercontent.com/u/6145026?v=4?s=100" width="100px;" alt="Timo"/><br /><sub><b>Timo</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ntimo" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="http://kristofmattei.be/"><img src="https://avatars.githubusercontent.com/u/864376?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kristof Mattei</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Kristof-Mattei" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/andrewkliskey"><img src="https://avatars.githubusercontent.com/u/44645768?v=4?s=100" width="100px;" alt="Andrew Kliskey"/><br /><sub><b>Andrew Kliskey</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=andrewkliskey" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://www.zmiguel.me/"><img src="https://avatars.githubusercontent.com/u/4400540?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ZMiguel Valdiviesso</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=zmiguel" title="Documentation">📖</a></td>
|
<td align="center"><a href="http://kristofmattei.be/"><img src="https://avatars.githubusercontent.com/u/864376?v=4?s=100" width="100px;" alt="Kristof Mattei"/><br /><sub><b>Kristof Mattei</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Kristof-Mattei" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/akusei"><img src="https://avatars.githubusercontent.com/u/12972900?v=4?s=100" width="100px;" alt=""/><br /><sub><b>akusei</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=akusei" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=akusei" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://www.zmiguel.me/"><img src="https://avatars.githubusercontent.com/u/4400540?v=4?s=100" width="100px;" alt="ZMiguel Valdiviesso"/><br /><sub><b>ZMiguel Valdiviesso</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=zmiguel" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/Peaches491"><img src="https://avatars.githubusercontent.com/u/494334?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Miller</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Peaches491" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/akusei"><img src="https://avatars.githubusercontent.com/u/12972900?v=4?s=100" width="100px;" alt="akusei"/><br /><sub><b>akusei</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=akusei" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=akusei" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/dustins"><img src="https://avatars.githubusercontent.com/u/14645?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dustin Sweigart</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dustins" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=dustins" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=dustins" title="Tests">⚠️</a></td>
|
<td align="center"><a href="https://github.com/Peaches491"><img src="https://avatars.githubusercontent.com/u/494334?v=4?s=100" width="100px;" alt="Daniel Miller"/><br /><sub><b>Daniel Miller</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Peaches491" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/dustins"><img src="https://avatars.githubusercontent.com/u/14645?v=4?s=100" width="100px;" alt="Dustin Sweigart"/><br /><sub><b>Dustin Sweigart</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dustins" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=dustins" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=dustins" title="Tests">⚠️</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/rogue780"><img src="https://avatars.githubusercontent.com/u/247716?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shawn Haggard</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=rogue780" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=rogue780" title="Tests">⚠️</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/kevynb"><img src="https://avatars.githubusercontent.com/u/4941215?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevyn Bruyere</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=kevynb" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/rogue780"><img src="https://avatars.githubusercontent.com/u/247716?v=4?s=100" width="100px;" alt="Shawn Haggard"/><br /><sub><b>Shawn Haggard</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=rogue780" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=rogue780" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="https://github.com/ducksecops"><img src="https://avatars.githubusercontent.com/u/25612094?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Sutton</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ducksecops" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/kevynb"><img src="https://avatars.githubusercontent.com/u/4941215?v=4?s=100" width="100px;" alt="Kevyn Bruyere"/><br /><sub><b>Kevyn Bruyere</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=kevynb" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="http://www.xenuser.org/"><img src="https://avatars.githubusercontent.com/u/2216868?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Valentin Höbel</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=xenuser" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/ducksecops"><img src="https://avatars.githubusercontent.com/u/25612094?v=4?s=100" width="100px;" alt="Daniel Sutton"/><br /><sub><b>Daniel Sutton</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ducksecops" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/thehedgefrog"><img src="https://avatars.githubusercontent.com/u/38590447?v=4?s=100" width="100px;" alt=""/><br /><sub><b>thehedgefrog</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=thehedgefrog" title="Documentation">📖</a></td>
|
<td align="center"><a href="http://www.xenuser.org/"><img src="https://avatars.githubusercontent.com/u/2216868?v=4?s=100" width="100px;" alt="Valentin Höbel"/><br /><sub><b>Valentin Höbel</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=xenuser" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/ViRb3"><img src="https://avatars.githubusercontent.com/u/2650170?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Victor</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ViRb3" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/thehedgefrog"><img src="https://avatars.githubusercontent.com/u/38590447?v=4?s=100" width="100px;" alt="thehedgefrog"/><br /><sub><b>thehedgefrog</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=thehedgefrog" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/whiskerch"><img src="https://avatars.githubusercontent.com/u/35109315?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Whisker</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=whiskerch" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/ViRb3"><img src="https://avatars.githubusercontent.com/u/2650170?v=4?s=100" width="100px;" alt="Victor"/><br /><sub><b>Victor</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ViRb3" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/whiskerch"><img src="https://avatars.githubusercontent.com/u/35109315?v=4?s=100" width="100px;" alt="Chris Whisker"/><br /><sub><b>Chris Whisker</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=whiskerch" title="Documentation">📖</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/nasatome"><img src="https://avatars.githubusercontent.com/u/18271791?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nasatome</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=nasatome" title="Documentation">📖</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/bbros-dev"><img src="https://avatars.githubusercontent.com/u/60454087?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Begley Brothers (Development)</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=bbros-dev" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/nasatome"><img src="https://avatars.githubusercontent.com/u/18271791?v=4?s=100" width="100px;" alt="nasatome"/><br /><sub><b>nasatome</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=nasatome" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="http://mikekusold.com/"><img src="https://avatars.githubusercontent.com/u/509966?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike Kusold</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=kusold" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/bbros-dev"><img src="https://avatars.githubusercontent.com/u/60454087?v=4?s=100" width="100px;" alt="Begley Brothers (Development)"/><br /><sub><b>Begley Brothers (Development)</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=bbros-dev" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://dzervas.gr/"><img src="https://avatars.githubusercontent.com/u/1029195?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dimitris Zervas</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dzervas" title="Documentation">📖</a></td>
|
<td align="center"><a href="http://mikekusold.com/"><img src="https://avatars.githubusercontent.com/u/509966?v=4?s=100" width="100px;" alt="Mike Kusold"/><br /><sub><b>Mike Kusold</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=kusold" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://paypal.me/DHoung"><img src="https://avatars.githubusercontent.com/u/52870424?v=4?s=100" width="100px;" alt=""/><br /><sub><b>TheCatLady</b></sub></a><br /><a href="#ideas-TheCatLady" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center"><a href="https://dzervas.gr/"><img src="https://avatars.githubusercontent.com/u/1029195?v=4?s=100" width="100px;" alt="Dimitris Zervas"/><br /><sub><b>Dimitris Zervas</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dzervas" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://lauri.vosandi.com/"><img src="https://avatars.githubusercontent.com/u/194685?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lauri Võsandi</b></sub></a><br /><a href="#ideas-laurivosandi" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center"><a href="http://paypal.me/DHoung"><img src="https://avatars.githubusercontent.com/u/52870424?v=4?s=100" width="100px;" alt="TheCatLady"/><br /><sub><b>TheCatLady</b></sub></a><br /><a href="#ideas-TheCatLady" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
<td align="center"><a href="https://github.com/knnnrd"><img src="https://avatars.githubusercontent.com/u/5852381?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kennard Vermeiren</b></sub></a><br /><a href="#ideas-knnnrd" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center"><a href="https://lauri.vosandi.com/"><img src="https://avatars.githubusercontent.com/u/194685?v=4?s=100" width="100px;" alt="Lauri Võsandi"/><br /><sub><b>Lauri Võsandi</b></sub></a><br /><a href="#ideas-laurivosandi" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/knnnrd"><img src="https://avatars.githubusercontent.com/u/5852381?v=4?s=100" width="100px;" alt="Kennard Vermeiren"/><br /><sub><b>Kennard Vermeiren</b></sub></a><br /><a href="#ideas-knnnrd" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/ThinkChaos"><img src="https://avatars.githubusercontent.com/u/4761135?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ThinkChaos</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ThinkChaos" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=ThinkChaos" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=ThinkChaos" title="Tests">⚠️</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/except"><img src="https://avatars.githubusercontent.com/u/26675576?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hasan</b></sub></a><br /><a href="#security-except" title="Security">🛡️</a></td>
|
<td align="center"><a href="https://github.com/ThinkChaos"><img src="https://avatars.githubusercontent.com/u/4761135?v=4?s=100" width="100px;" alt="ThinkChaos"/><br /><sub><b>ThinkChaos</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ThinkChaos" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=ThinkChaos" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=ThinkChaos" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="http://blog.dchidell.com"><img src="https://avatars.githubusercontent.com/u/26146619?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Chidell</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dchidell" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/except"><img src="https://avatars.githubusercontent.com/u/26675576?v=4?s=100" width="100px;" alt="Hasan"/><br /><sub><b>Hasan</b></sub></a><br /><a href="#security-except" title="Security">🛡️</a></td>
|
||||||
<td align="center"><a href="https://github.com/mardom1"><img src="https://avatars.githubusercontent.com/u/32371724?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Marcel Marquardt</b></sub></a><br /><a href="https://github.com/authelia/authelia/issues?q=author%3Amardom1" title="Bug reports">🐛</a></td>
|
<td align="center"><a href="http://blog.dchidell.com"><img src="https://avatars.githubusercontent.com/u/26146619?v=4?s=100" width="100px;" alt="David Chidell"/><br /><sub><b>David Chidell</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dchidell" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://cdine.org"><img src="https://avatars.githubusercontent.com/u/127512?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ian Gallagher</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=craSH" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/mardom1"><img src="https://avatars.githubusercontent.com/u/32371724?v=4?s=100" width="100px;" alt="Marcel Marquardt"/><br /><sub><b>Marcel Marquardt</b></sub></a><br /><a href="https://github.com/authelia/authelia/issues?q=author%3Amardom1" title="Bug reports">🐛</a></td>
|
||||||
<td align="center"><a href="https://wuhanstudio.cc"><img src="https://avatars.githubusercontent.com/u/15157070?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Wu Han</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=wuhanstudio" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://cdine.org"><img src="https://avatars.githubusercontent.com/u/127512?v=4?s=100" width="100px;" alt="Ian Gallagher"/><br /><sub><b>Ian Gallagher</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=craSH" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/lavih"><img src="https://avatars.githubusercontent.com/u/47455309?v=4?s=100" width="100px;" alt=""/><br /><sub><b>lavih</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=lavih" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://wuhanstudio.cc"><img src="https://avatars.githubusercontent.com/u/15157070?v=4?s=100" width="100px;" alt="Wu Han"/><br /><sub><b>Wu Han</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=wuhanstudio" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/lavih"><img src="https://avatars.githubusercontent.com/u/47455309?v=4?s=100" width="100px;" alt="lavih"/><br /><sub><b>lavih</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=lavih" title="Documentation">📖</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="http://jonbayl"><img src="https://avatars.githubusercontent.com/u/30201351?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jon B. </b></sub></a><br /><a href="#security-jonbayl" title="Security">🛡️</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/AlexGustafsson"><img src="https://avatars.githubusercontent.com/u/14974112?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Gustafsson</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=AlexGustafsson" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=AlexGustafsson" title="Documentation">📖</a></td>
|
<td align="center"><a href="http://jonbayl"><img src="https://avatars.githubusercontent.com/u/30201351?v=4?s=100" width="100px;" alt="Jon B. "/><br /><sub><b>Jon B. </b></sub></a><br /><a href="#security-jonbayl" title="Security">🛡️</a></td>
|
||||||
<td align="center"><a href="https://www.aarsen.me/"><img src="https://avatars.githubusercontent.com/u/7805050?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arsenović Arsen</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ArsenArsen" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=ArsenArsen" title="Tests">⚠️</a> <a href="#security-ArsenArsen" title="Security">🛡️</a></td>
|
<td align="center"><a href="https://github.com/AlexGustafsson"><img src="https://avatars.githubusercontent.com/u/14974112?v=4?s=100" width="100px;" alt="Alex Gustafsson"/><br /><sub><b>Alex Gustafsson</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=AlexGustafsson" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=AlexGustafsson" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/dakriy"><img src="https://avatars.githubusercontent.com/u/13756065?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dakriy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dakriy" title="Code">💻</a></td>
|
<td align="center"><a href="https://www.aarsen.me/"><img src="https://avatars.githubusercontent.com/u/7805050?v=4?s=100" width="100px;" alt="Arsenović Arsen"/><br /><sub><b>Arsenović Arsen</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=ArsenArsen" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=ArsenArsen" title="Tests">⚠️</a> <a href="#security-ArsenArsen" title="Security">🛡️</a></td>
|
||||||
<td align="center"><a href="https://github.com/davama"><img src="https://avatars.githubusercontent.com/u/5359152?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dave</b></sub></a><br /><a href="#userTesting-davama" title="User Testing">📓</a></td>
|
<td align="center"><a href="https://github.com/dakriy"><img src="https://avatars.githubusercontent.com/u/13756065?v=4?s=100" width="100px;" alt="dakriy"/><br /><sub><b>dakriy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=dakriy" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/nreymundo"><img src="https://avatars.githubusercontent.com/u/5833447?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nicolas Reymundo</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=nreymundo" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/davama"><img src="https://avatars.githubusercontent.com/u/5359152?v=4?s=100" width="100px;" alt="Dave"/><br /><sub><b>Dave</b></sub></a><br /><a href="#userTesting-davama" title="User Testing">📓</a></td>
|
||||||
<td align="center"><a href="https://github.com/polandy"><img src="https://avatars.githubusercontent.com/u/3670670?v=4?s=100" width="100px;" alt=""/><br /><sub><b>polandy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=polandy" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/nreymundo"><img src="https://avatars.githubusercontent.com/u/5833447?v=4?s=100" width="100px;" alt="Nicolas Reymundo"/><br /><sub><b>Nicolas Reymundo</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=nreymundo" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/polandy"><img src="https://avatars.githubusercontent.com/u/3670670?v=4?s=100" width="100px;" alt="polandy"/><br /><sub><b>polandy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=polandy" title="Documentation">📖</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/you1996"><img src="https://avatars.githubusercontent.com/u/45292366?v=4?s=100" width="100px;" alt=""/><br /><sub><b>yossbg</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=you1996" title="Code">💻</a> <a href="#design-you1996" title="Design">🎨</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/mpdcampbell"><img src="https://avatars.githubusercontent.com/u/47434940?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Campbell</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=mpdcampbell" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/you1996"><img src="https://avatars.githubusercontent.com/u/45292366?v=4?s=100" width="100px;" alt="yossbg"/><br /><sub><b>yossbg</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=you1996" title="Code">💻</a> <a href="#design-you1996" title="Design">🎨</a></td>
|
||||||
<td align="center"><a href="https://sievenpiper.co"><img src="https://avatars.githubusercontent.com/u/1131882?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Justin Sievenpiper</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=jsievenpiper" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/mpdcampbell"><img src="https://avatars.githubusercontent.com/u/47434940?v=4?s=100" width="100px;" alt="Michael Campbell"/><br /><sub><b>Michael Campbell</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=mpdcampbell" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/kaysond"><img src="https://avatars.githubusercontent.com/u/1147328?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aram Akhavan</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=kaysond" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://sievenpiper.co"><img src="https://avatars.githubusercontent.com/u/1131882?v=4?s=100" width="100px;" alt="Justin Sievenpiper"/><br /><sub><b>Justin Sievenpiper</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=jsievenpiper" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://skhuf.net"><img src="https://avatars.githubusercontent.com/u/286341?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shadow</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=shadow7412" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/kaysond"><img src="https://avatars.githubusercontent.com/u/1147328?v=4?s=100" width="100px;" alt="Aram Akhavan"/><br /><sub><b>Aram Akhavan</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=kaysond" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/tarioch"><img src="https://avatars.githubusercontent.com/u/2998148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Patrick Ruckstuhl</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=tarioch" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://skhuf.net"><img src="https://avatars.githubusercontent.com/u/286341?v=4?s=100" width="100px;" alt="Shadow"/><br /><sub><b>Shadow</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=shadow7412" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/FineWolf"><img src="https://avatars.githubusercontent.com/u/203591?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Moore</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=FineWolf" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=FineWolf" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=FineWolf" title="Tests">⚠️</a></td>
|
<td align="center"><a href="https://github.com/tarioch"><img src="https://avatars.githubusercontent.com/u/2998148?v=4?s=100" width="100px;" alt="Patrick Ruckstuhl"/><br /><sub><b>Patrick Ruckstuhl</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=tarioch" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/FineWolf"><img src="https://avatars.githubusercontent.com/u/203591?v=4?s=100" width="100px;" alt="Andrew Moore"/><br /><sub><b>Andrew Moore</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=FineWolf" title="Code">💻</a> <a href="https://github.com/authelia/authelia/commits?author=FineWolf" title="Documentation">📖</a> <a href="https://github.com/authelia/authelia/commits?author=FineWolf" title="Tests">⚠️</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="http://www.dennisgaida.de"><img src="https://avatars.githubusercontent.com/u/2392217?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dennis Gaida</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=DennisGaida" title="Documentation">📖</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/Alestrix"><img src="https://avatars.githubusercontent.com/u/7452860?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alestrix</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Alestrix" title="Documentation">📖</a></td>
|
<td align="center"><a href="http://www.dennisgaida.de"><img src="https://avatars.githubusercontent.com/u/2392217?v=4?s=100" width="100px;" alt="Dennis Gaida"/><br /><sub><b>Dennis Gaida</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=DennisGaida" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/bgh-github"><img src="https://avatars.githubusercontent.com/u/99472455?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bgh-github</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=bgh-github" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/Alestrix"><img src="https://avatars.githubusercontent.com/u/7452860?v=4?s=100" width="100px;" alt="Alestrix"/><br /><sub><b>Alestrix</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Alestrix" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/mind-ar"><img src="https://avatars.githubusercontent.com/u/10672208?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Manuel Nuñez</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=mind-ar" title="Code">💻</a> <a href="#translation-mind-ar" title="Translation">🌍</a></td>
|
<td align="center"><a href="https://github.com/bgh-github"><img src="https://avatars.githubusercontent.com/u/99472455?v=4?s=100" width="100px;" alt="bgh-github"/><br /><sub><b>bgh-github</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=bgh-github" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/protvis74"><img src="https://avatars.githubusercontent.com/u/50554836?v=4?s=100" width="100px;" alt=""/><br /><sub><b>protvis74</b></sub></a><br /><a href="#translation-protvis74" title="Translation">🌍</a></td>
|
<td align="center"><a href="https://github.com/mind-ar"><img src="https://avatars.githubusercontent.com/u/10672208?v=4?s=100" width="100px;" alt="Manuel Nuñez"/><br /><sub><b>Manuel Nuñez</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=mind-ar" title="Code">💻</a> <a href="#translation-mind-ar" title="Translation">🌍</a></td>
|
||||||
<td align="center"><a href="http://itjamie.com"><img src="https://avatars.githubusercontent.com/u/1613241?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jamie (Bear) Murphy </b></sub></a><br /><a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3AITJamie" title="Reviewed Pull Requests">👀</a></td>
|
<td align="center"><a href="https://github.com/protvis74"><img src="https://avatars.githubusercontent.com/u/50554836?v=4?s=100" width="100px;" alt="protvis74"/><br /><sub><b>protvis74</b></sub></a><br /><a href="#translation-protvis74" title="Translation">🌍</a></td>
|
||||||
<td align="center"><a href="https://github.com/Beanow"><img src="https://avatars.githubusercontent.com/u/497556?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robin van Boven</b></sub></a><br /><a href="#security-Beanow" title="Security">🛡️</a></td>
|
<td align="center"><a href="http://itjamie.com"><img src="https://avatars.githubusercontent.com/u/1613241?v=4?s=100" width="100px;" alt="Jamie (Bear) Murphy "/><br /><sub><b>Jamie (Bear) Murphy </b></sub></a><br /><a href="https://github.com/authelia/authelia/pulls?q=is%3Apr+reviewed-by%3AITJamie" title="Reviewed Pull Requests">👀</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/Beanow"><img src="https://avatars.githubusercontent.com/u/497556?v=4?s=100" width="100px;" alt="Robin van Boven"/><br /><sub><b>Robin van Boven</b></sub></a><br /><a href="#security-Beanow" title="Security">🛡️</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="http://www.cybertrol.com"><img src="https://avatars.githubusercontent.com/u/1178293?v=4?s=100" width="100px;" alt=""/><br /><sub><b>alphabet5</b></sub></a><br /><a href="#ideas-alphabet5" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/rjmidau"><img src="https://avatars.githubusercontent.com/u/8134995?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert Meredith</b></sub></a><br /><a href="#ideas-rjmidau" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center"><a href="http://www.cybertrol.com"><img src="https://avatars.githubusercontent.com/u/1178293?v=4?s=100" width="100px;" alt="alphabet5"/><br /><sub><b>alphabet5</b></sub></a><br /><a href="#ideas-alphabet5" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
<td align="center"><a href="https://github.com/adriang-90"><img src="https://avatars.githubusercontent.com/u/60886162?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adrian Gąsior</b></sub></a><br /><a href="#security-adriang-90" title="Security">🛡️</a></td>
|
<td align="center"><a href="https://github.com/rjmidau"><img src="https://avatars.githubusercontent.com/u/8134995?v=4?s=100" width="100px;" alt="Robert Meredith"/><br /><sub><b>Robert Meredith</b></sub></a><br /><a href="#ideas-rjmidau" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
<td align="center"><a href="http://jamesw.link/me"><img src="https://avatars.githubusercontent.com/u/8067792?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James White</b></sub></a><br /><a href="#question-jamesmacwhite" title="Answering Questions">💬</a></td>
|
<td align="center"><a href="https://github.com/adriang-90"><img src="https://avatars.githubusercontent.com/u/60886162?v=4?s=100" width="100px;" alt="Adrian Gąsior"/><br /><sub><b>Adrian Gąsior</b></sub></a><br /><a href="#security-adriang-90" title="Security">🛡️</a></td>
|
||||||
<td align="center"><a href="https://www.zxlim.xyz"><img src="https://avatars.githubusercontent.com/u/19372079?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zhao Xiang Lim</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=zxlim" title="Documentation">📖</a></td>
|
<td align="center"><a href="http://jamesw.link/me"><img src="https://avatars.githubusercontent.com/u/8067792?v=4?s=100" width="100px;" alt="James White"/><br /><sub><b>James White</b></sub></a><br /><a href="#question-jamesmacwhite" title="Answering Questions">💬</a></td>
|
||||||
<td align="center"><a href="https://github.com/Auzborn123"><img src="https://avatars.githubusercontent.com/u/42992103?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Auzborn123</b></sub></a><br /><a href="#translation-Auzborn123" title="Translation">🌍</a></td>
|
<td align="center"><a href="https://www.zxlim.xyz"><img src="https://avatars.githubusercontent.com/u/19372079?v=4?s=100" width="100px;" alt="Zhao Xiang Lim"/><br /><sub><b>Zhao Xiang Lim</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=zxlim" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/SvanGlan"><img src="https://avatars.githubusercontent.com/u/106152205?v=4?s=100" width="100px;" alt=""/><br /><sub><b>SvanGlan</b></sub></a><br /><a href="#translation-SvanGlan" title="Translation">🌍</a></td>
|
<td align="center"><a href="https://github.com/Auzborn123"><img src="https://avatars.githubusercontent.com/u/42992103?v=4?s=100" width="100px;" alt="Auzborn123"/><br /><sub><b>Auzborn123</b></sub></a><br /><a href="#translation-Auzborn123" title="Translation">🌍</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/SvanGlan"><img src="https://avatars.githubusercontent.com/u/106152205?v=4?s=100" width="100px;" alt="SvanGlan"/><br /><sub><b>SvanGlan</b></sub></a><br /><a href="#translation-SvanGlan" title="Translation">🌍</a></td>
|
||||||
<tr>
|
</tr>
|
||||||
<td align="center"><a href="https://github.com/HannesJo0139"><img src="https://avatars.githubusercontent.com/u/42114183?v=4?s=100" width="100px;" alt=""/><br /><sub><b>HannesJo0139</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=HannesJo0139" title="Documentation">📖</a></td>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/andreas-berg"><img src="https://avatars.githubusercontent.com/u/39428693?v=4?s=100" width="100px;" alt=""/><br /><sub><b>andreas-berg</b></sub></a><br /><a href="https://github.com/authelia/authelia/issues?q=author%3Aandreas-berg" title="Bug reports">🐛</a></td>
|
<td align="center"><a href="https://github.com/HannesJo0139"><img src="https://avatars.githubusercontent.com/u/42114183?v=4?s=100" width="100px;" alt="HannesJo0139"/><br /><sub><b>HannesJo0139</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=HannesJo0139" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="http://radenac.me"><img src="https://avatars.githubusercontent.com/u/47008408?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Clément Radenac</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=clem3109" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/andreas-berg"><img src="https://avatars.githubusercontent.com/u/39428693?v=4?s=100" width="100px;" alt="andreas-berg"/><br /><sub><b>andreas-berg</b></sub></a><br /><a href="https://github.com/authelia/authelia/issues?q=author%3Aandreas-berg" title="Bug reports">🐛</a></td>
|
||||||
<td align="center"><a href="https://github.com/boomam"><img src="https://avatars.githubusercontent.com/u/37086258?v=4?s=100" width="100px;" alt=""/><br /><sub><b>boomam</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=boomam" title="Documentation">📖</a></td>
|
<td align="center"><a href="http://radenac.me"><img src="https://avatars.githubusercontent.com/u/47008408?v=4?s=100" width="100px;" alt="Clément Radenac"/><br /><sub><b>Clément Radenac</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=clem3109" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/Northguy"><img src="https://avatars.githubusercontent.com/u/1189058?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Northguy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Northguy" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/boomam"><img src="https://avatars.githubusercontent.com/u/37086258?v=4?s=100" width="100px;" alt="boomam"/><br /><sub><b>boomam</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=boomam" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/polarathene"><img src="https://avatars.githubusercontent.com/u/5098581?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Brennan Kinney</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=polarathene" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/Northguy"><img src="https://avatars.githubusercontent.com/u/1189058?v=4?s=100" width="100px;" alt="Northguy"/><br /><sub><b>Northguy</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=Northguy" title="Documentation">📖</a></td>
|
||||||
</tr>
|
<td align="center"><a href="https://github.com/polarathene"><img src="https://avatars.githubusercontent.com/u/5098581?v=4?s=100" width="100px;" alt="Brennan Kinney"/><br /><sub><b>Brennan Kinney</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=polarathene" title="Documentation">📖</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/LongerHV"><img src="https://avatars.githubusercontent.com/u/46924944?v=4?s=100" width="100px;" alt="Michał Mieszczak"/><br /><sub><b>Michał Mieszczak</b></sub></a><br /><a href="#ideas-LongerHV" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/authelia/authelia/commits?author=LongerHV" title="Code">💻</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/paul-ohl"><img src="https://avatars.githubusercontent.com/u/37795294?v=4?s=100" width="100px;" alt="Paul Ohl"/><br /><sub><b>Paul Ohl</b></sub></a><br /><a href="https://github.com/authelia/authelia/commits?author=paul-ohl" title="Documentation">📖</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/smkent"><img src="https://avatars.githubusercontent.com/u/2831985?v=4?s=100" width="100px;" alt="Stephen Kent"/><br /><sub><b>Stephen Kent</b></sub></a><br /><a href="#ideas-smkent" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- markdownlint-restore -->
|
<!-- markdownlint-restore -->
|
||||||
|
@ -389,10 +391,12 @@ Companies contributing to Authelia via Open Collective will have a special menti
|
||||||
[Webauthn]: https://www.yubico.com/authentication-standards/webauthn/
|
[Webauthn]: https://www.yubico.com/authentication-standards/webauthn/
|
||||||
[auth_request]: https://nginx.org/en/docs/http/ngx_http_auth_request_module.html
|
[auth_request]: https://nginx.org/en/docs/http/ngx_http_auth_request_module.html
|
||||||
[config.template.yml]: ./config.template.yml
|
[config.template.yml]: ./config.template.yml
|
||||||
[nginx]: https://www.nginx.com/
|
[nginx]: https://www.authelia.com/integration/proxies/nginx/
|
||||||
[Traefik]: https://traefik.io/
|
[Traefik]: https://www.authelia.com/integration/proxies/traefik/
|
||||||
[caddy]: https://caddyserver.com/
|
[Caddy]: https://www.authelia.com/integration/proxies/caddy/
|
||||||
[HAProxy]: https://www.haproxy.org/
|
[Skipper]: https://www.authelia.com/integration/proxies/skipper/
|
||||||
|
[Envoy]: https://www.authelia.com/integration/proxies/envoy/
|
||||||
|
[HAProxy]: https://www.authelia.com/integration/proxies/haproxy/
|
||||||
[Docker]: https://docker.com/
|
[Docker]: https://docker.com/
|
||||||
[Kubernetes]: https://kubernetes.io/
|
[Kubernetes]: https://kubernetes.io/
|
||||||
[security]: https://github.com/authelia/authelia/security/policy
|
[security]: https://github.com/authelia/authelia/security/policy
|
||||||
|
|
|
@ -176,7 +176,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/handlers.firstFactorRequestBody'
|
$ref: '#/components/schemas/handlers.bodyFirstFactorRequest'
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Successful Operation
|
description: Successful Operation
|
||||||
|
@ -446,7 +446,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/handlers.signTOTPRequestBody'
|
$ref: '#/components/schemas/handlers.bodySignTOTPRequest'
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Successful Operation
|
description: Successful Operation
|
||||||
|
@ -579,7 +579,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/handlers.signDuoRequestBody'
|
$ref: '#/components/schemas/handlers.bodySignDuoRequest'
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Successful Operation
|
description: Successful Operation
|
||||||
|
@ -785,7 +785,7 @@ components:
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: push
|
example: push
|
||||||
handlers.firstFactorRequestBody:
|
handlers.bodyFirstFactorRequest:
|
||||||
required:
|
required:
|
||||||
- username
|
- username
|
||||||
- password
|
- password
|
||||||
|
@ -800,6 +800,12 @@ components:
|
||||||
targetURL:
|
targetURL:
|
||||||
type: string
|
type: string
|
||||||
example: https://home.example.com
|
example: https://home.example.com
|
||||||
|
workflow:
|
||||||
|
type: string
|
||||||
|
example: openid_connect
|
||||||
|
workflowID:
|
||||||
|
type: string
|
||||||
|
example: 3ebcfbc5-b0fd-4ee0-9d3c-080ae1e7298c
|
||||||
requestMethod:
|
requestMethod:
|
||||||
type: string
|
type: string
|
||||||
example: GET
|
example: GET
|
||||||
|
@ -852,13 +858,21 @@ components:
|
||||||
password:
|
password:
|
||||||
type: string
|
type: string
|
||||||
example: password
|
example: password
|
||||||
handlers.signDuoRequestBody:
|
handlers.bodySignDuoRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
targetURL:
|
targetURL:
|
||||||
type: string
|
type: string
|
||||||
example: https://secure.example.com
|
example: https://secure.example.com
|
||||||
handlers.signTOTPRequestBody:
|
passcode:
|
||||||
|
type: string
|
||||||
|
workflow:
|
||||||
|
type: string
|
||||||
|
example: openid_connect
|
||||||
|
workflowID:
|
||||||
|
type: string
|
||||||
|
example: 3ebcfbc5-b0fd-4ee0-9d3c-080ae1e7298c
|
||||||
|
handlers.bodySignTOTPRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
token:
|
token:
|
||||||
|
@ -867,6 +881,12 @@ components:
|
||||||
targetURL:
|
targetURL:
|
||||||
type: string
|
type: string
|
||||||
example: https://secure.example.com
|
example: https://secure.example.com
|
||||||
|
workflow:
|
||||||
|
type: string
|
||||||
|
example: openid_connect
|
||||||
|
workflowID:
|
||||||
|
type: string
|
||||||
|
example: 3ebcfbc5-b0fd-4ee0-9d3c-080ae1e7298c
|
||||||
handlers.StateResponse:
|
handlers.StateResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1047,6 +1067,12 @@ components:
|
||||||
userHandle:
|
userHandle:
|
||||||
type: string
|
type: string
|
||||||
format: byte
|
format: byte
|
||||||
|
workflow:
|
||||||
|
type: string
|
||||||
|
example: openid_connect
|
||||||
|
workflowID:
|
||||||
|
type: string
|
||||||
|
example: 3ebcfbc5-b0fd-4ee0-9d3c-080ae1e7298c
|
||||||
webauthn.PublicKeyCredentialCreationOptions:
|
webauthn.PublicKeyCredentialCreationOptions:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newAllCmd() *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "all",
|
|
||||||
Short: "Run all generators with default options",
|
|
||||||
RunE: allRunE,
|
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func allRunE(cmd *cobra.Command, args []string) (err error) {
|
|
||||||
for _, subCmd := range cmd.Parent().Commands() {
|
|
||||||
if subCmd == cmd || subCmd.Use == "completion" || subCmd.Use == "help [command]" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case subCmd.RunE != nil:
|
|
||||||
if err = subCmd.RunE(subCmd, args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case subCmd.Run != nil:
|
|
||||||
subCmd.Run(subCmd, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,34 +1,330 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rsa"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/mail"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newCodeCmd() *cobra.Command {
|
func newCodeCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "code",
|
Use: cmdUseCode,
|
||||||
Short: "Generate code",
|
Short: "Generate code",
|
||||||
RunE: codeRunE,
|
RunE: rootSubCommandsRunE,
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.AddCommand(newCodeKeysCmd())
|
cmd.AddCommand(newCodeKeysCmd(), newCodeServerCmd(), newCodeScriptsCmd())
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func codeRunE(cmd *cobra.Command, args []string) (err error) {
|
func newCodeServerCmd() *cobra.Command {
|
||||||
for _, subCmd := range cmd.Commands() {
|
cmd := &cobra.Command{
|
||||||
switch {
|
Use: cmdUseServer,
|
||||||
case subCmd.RunE != nil:
|
Short: "Generate the Authelia server files",
|
||||||
if err = subCmd.RunE(subCmd, args); err != nil {
|
RunE: codeServerRunE,
|
||||||
return err
|
|
||||||
}
|
DisableAutoGenTag: true,
|
||||||
case subCmd.Run != nil:
|
}
|
||||||
subCmd.Run(subCmd, args)
|
|
||||||
}
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCodeScriptsCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseCodeScripts,
|
||||||
|
Short: "Generate the generated portion of the authelia-scripts command",
|
||||||
|
RunE: codeScriptsRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCodeKeysCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseKeys,
|
||||||
|
Short: "Generate the list of valid configuration keys",
|
||||||
|
RunE: codeKeysRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func codeServerRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
data := TemplateCSP{
|
||||||
|
PlaceholderNONCE: codeCSPNonce,
|
||||||
|
TemplateDefault: buildCSP(codeCSPProductionDefaultSrc, codeCSPValuesCommon, codeCSPValuesProduction),
|
||||||
|
TemplateDevelopment: buildCSP(codeCSPDevelopmentDefaultSrc, codeCSPValuesCommon, codeCSPValuesDevelopment),
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputPath string
|
||||||
|
|
||||||
|
if outputPath, err = getPFlagPath(cmd.Flags(), cmdFlagRoot, cmdFlagFileServerGenerated); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var f *os.File
|
||||||
|
|
||||||
|
if f, err = os.Create(outputPath); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file '%s': %w", outputPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplServer.Execute(f, data); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
|
||||||
|
return fmt.Errorf("failed to write output file '%s': %w", outputPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close output file '%s': %w", outputPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func codeScriptsRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var (
|
||||||
|
root, pathScriptsGen string
|
||||||
|
resp *http.Response
|
||||||
|
)
|
||||||
|
|
||||||
|
data := &tmplScriptsGEnData{}
|
||||||
|
|
||||||
|
if root, err = cmd.Flags().GetString(cmdFlagRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathScriptsGen, err = cmd.Flags().GetString(cmdFlagFileScriptsGen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Package, err = cmd.Flags().GetString(cmdFlagPackageScriptsGen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp, err = http.Get("https://api.github.com/repos/swagger-api/swagger-ui/tags"); err != nil {
|
||||||
|
return fmt.Errorf("failed to get latest version of the Swagger UI: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var (
|
||||||
|
respJSON []GitHubTagsJSON
|
||||||
|
respRaw []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if respRaw, err = io.ReadAll(resp.Body); err != nil {
|
||||||
|
return fmt.Errorf("failed to get latest version of the Swagger UI: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal(respRaw, &respJSON); err != nil {
|
||||||
|
return fmt.Errorf("failed to get latest version of the Swagger UI: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(respJSON) < 1 {
|
||||||
|
return fmt.Errorf("failed to get latest version of the Swagger UI: the api returned zero results")
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(respJSON[0].Name, "v") {
|
||||||
|
data.VersionSwaggerUI = respJSON[0].Name[1:]
|
||||||
|
} else {
|
||||||
|
data.VersionSwaggerUI = respJSON[0].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
fullPathScriptsGen := filepath.Join(root, pathScriptsGen)
|
||||||
|
|
||||||
|
var f *os.File
|
||||||
|
|
||||||
|
if f, err = os.Create(fullPathScriptsGen); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file '%s': %w", fullPathScriptsGen, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplScriptsGen.Execute(f, data); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
|
||||||
|
return fmt.Errorf("failed to write output file '%s': %w", fullPathScriptsGen, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close output file '%s': %w", fullPathScriptsGen, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func codeKeysRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var (
|
||||||
|
pathCodeConfigKeys, root string
|
||||||
|
|
||||||
|
f *os.File
|
||||||
|
)
|
||||||
|
|
||||||
|
data := tmplConfigurationKeysData{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Keys: readTags("", reflect.TypeOf(schema.Configuration{})),
|
||||||
|
}
|
||||||
|
|
||||||
|
if root, err = cmd.Flags().GetString(cmdFlagRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathCodeConfigKeys, err = cmd.Flags().GetString(cmdFlagFileConfigKeys); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Package, err = cmd.Flags().GetString(cmdFlagPackageConfigKeys); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fullPathCodeConfigKeys := filepath.Join(root, pathCodeConfigKeys)
|
||||||
|
|
||||||
|
if f, err = os.Create(fullPathCodeConfigKeys); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file '%s': %w", fullPathCodeConfigKeys, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplCodeConfigurationSchemaKeys.Execute(f, data); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
|
||||||
|
return fmt.Errorf("failed to write output file '%s': %w", fullPathCodeConfigKeys, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close output file '%s': %w", fullPathCodeConfigKeys, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var decodedTypes = []reflect.Type{
|
||||||
|
reflect.TypeOf(mail.Address{}),
|
||||||
|
reflect.TypeOf(regexp.Regexp{}),
|
||||||
|
reflect.TypeOf(url.URL{}),
|
||||||
|
reflect.TypeOf(time.Duration(0)),
|
||||||
|
reflect.TypeOf(schema.Address{}),
|
||||||
|
reflect.TypeOf(rsa.PrivateKey{}),
|
||||||
|
reflect.TypeOf(ecdsa.PrivateKey{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsType(needle reflect.Type, haystack []reflect.Type) (contains bool) {
|
||||||
|
for _, t := range haystack {
|
||||||
|
if needle.Kind() == reflect.Ptr {
|
||||||
|
if needle.Elem() == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if needle == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gocyclo
|
||||||
|
func readTags(prefix string, t reflect.Type) (tags []string) {
|
||||||
|
tags = make([]string, 0)
|
||||||
|
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
|
if t.Kind() == reflect.Slice {
|
||||||
|
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, "", true), t.Elem())...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
|
||||||
|
tag := field.Tag.Get("koanf")
|
||||||
|
|
||||||
|
if tag == "" {
|
||||||
|
tags = append(tags, prefix)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
if !containsType(field.Type, decodedTypes) {
|
||||||
|
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, false), field.Type)...)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
switch field.Type.Elem().Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
if !containsType(field.Type.Elem(), decodedTypes) {
|
||||||
|
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false))
|
||||||
|
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true), field.Type.Elem())...)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true), field.Type.Elem())...)
|
||||||
|
}
|
||||||
|
case reflect.Ptr:
|
||||||
|
switch field.Type.Elem().Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
if !containsType(field.Type.Elem(), decodedTypes) {
|
||||||
|
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, false), field.Type.Elem())...)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
if field.Type.Elem().Elem().Kind() == reflect.Struct {
|
||||||
|
if !containsType(field.Type.Elem(), decodedTypes) {
|
||||||
|
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true), field.Type.Elem())...)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func getKeyNameFromTagAndPrefix(prefix, name string, slice bool) string {
|
||||||
|
nameParts := strings.SplitN(name, ",", 2)
|
||||||
|
|
||||||
|
if prefix == "" {
|
||||||
|
return nameParts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(nameParts) == 2 && nameParts[1] == "squash" {
|
||||||
|
return prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
if slice {
|
||||||
|
if name == "" {
|
||||||
|
return fmt.Sprintf("%s[]", prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s.%s[]", prefix, nameParts[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s.%s", prefix, nameParts[0])
|
||||||
|
}
|
||||||
|
|
|
@ -1,173 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/mail"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newCodeKeysCmd() *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "keys",
|
|
||||||
Short: "Generate the list of valid configuration keys",
|
|
||||||
RunE: codeKeysRunE,
|
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Flags().StringP("file", "f", "./internal/configuration/schema/keys.go", "Sets the path of the keys file")
|
|
||||||
cmd.Flags().String("package", "schema", "Sets the package name of the keys file")
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func codeKeysRunE(cmd *cobra.Command, args []string) (err error) {
|
|
||||||
var (
|
|
||||||
file string
|
|
||||||
|
|
||||||
f *os.File
|
|
||||||
)
|
|
||||||
|
|
||||||
data := keysTemplateStruct{
|
|
||||||
Timestamp: time.Now(),
|
|
||||||
Keys: readTags("", reflect.TypeOf(schema.Configuration{})),
|
|
||||||
}
|
|
||||||
|
|
||||||
if file, err = cmd.Flags().GetString("file"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.Package, err = cmd.Flags().GetString("package"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if f, err = os.Create(file); err != nil {
|
|
||||||
return fmt.Errorf("failed to create file '%s': %w", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
content []byte
|
|
||||||
tmpl *template.Template
|
|
||||||
)
|
|
||||||
|
|
||||||
if content, err = templatesFS.ReadFile("templates/config_keys.go.tmpl"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmpl, err = template.New("keys").Parse(string(content)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmpl.Execute(f, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
type keysTemplateStruct struct {
|
|
||||||
Timestamp time.Time
|
|
||||||
Keys []string
|
|
||||||
Package string
|
|
||||||
}
|
|
||||||
|
|
||||||
var decodedTypes = []reflect.Type{
|
|
||||||
reflect.TypeOf(mail.Address{}),
|
|
||||||
reflect.TypeOf(regexp.Regexp{}),
|
|
||||||
reflect.TypeOf(url.URL{}),
|
|
||||||
reflect.TypeOf(time.Duration(0)),
|
|
||||||
reflect.TypeOf(schema.Address{}),
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsType(needle reflect.Type, haystack []reflect.Type) (contains bool) {
|
|
||||||
for _, t := range haystack {
|
|
||||||
if needle.Kind() == reflect.Ptr {
|
|
||||||
if needle.Elem() == t {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else if needle == t {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func readTags(prefix string, t reflect.Type) (tags []string) {
|
|
||||||
tags = make([]string, 0)
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
field := t.Field(i)
|
|
||||||
|
|
||||||
tag := field.Tag.Get("koanf")
|
|
||||||
|
|
||||||
if tag == "" {
|
|
||||||
tags = append(tags, prefix)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch field.Type.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
if !containsType(field.Type, decodedTypes) {
|
|
||||||
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, false), field.Type)...)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case reflect.Slice:
|
|
||||||
if field.Type.Elem().Kind() == reflect.Struct {
|
|
||||||
if !containsType(field.Type.Elem(), decodedTypes) {
|
|
||||||
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false))
|
|
||||||
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true), field.Type.Elem())...)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Ptr:
|
|
||||||
switch field.Type.Elem().Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
if !containsType(field.Type.Elem(), decodedTypes) {
|
|
||||||
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, false), field.Type.Elem())...)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case reflect.Slice:
|
|
||||||
if field.Type.Elem().Elem().Kind() == reflect.Struct {
|
|
||||||
if !containsType(field.Type.Elem(), decodedTypes) {
|
|
||||||
tags = append(tags, readTags(getKeyNameFromTagAndPrefix(prefix, tag, true), field.Type.Elem())...)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tags = append(tags, getKeyNameFromTagAndPrefix(prefix, tag, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
return tags
|
|
||||||
}
|
|
||||||
|
|
||||||
func getKeyNameFromTagAndPrefix(prefix, name string, slice bool) string {
|
|
||||||
nameParts := strings.SplitN(name, ",", 2)
|
|
||||||
|
|
||||||
if prefix == "" {
|
|
||||||
return nameParts[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(nameParts) == 2 && nameParts[1] == "squash" {
|
|
||||||
return prefix
|
|
||||||
}
|
|
||||||
|
|
||||||
if slice {
|
|
||||||
return fmt.Sprintf("%s.%s[]", prefix, nameParts[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s.%s", prefix, nameParts[0])
|
|
||||||
}
|
|
|
@ -0,0 +1,220 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommitMessageTmpl is a template data structure which is used to generate files with commit message information.
|
||||||
|
type CommitMessageTmpl struct {
|
||||||
|
Scopes ScopesTmpl
|
||||||
|
Types TypesTmpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypesTmpl is a template data structure which is used to generate files with commit message types.
|
||||||
|
type TypesTmpl struct {
|
||||||
|
List []string
|
||||||
|
Details []NameDescriptionTmpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScopesTmpl is a template data structure which is used to generate files with commit message scopes.
|
||||||
|
type ScopesTmpl struct {
|
||||||
|
All []string
|
||||||
|
Packages []string
|
||||||
|
Extra []NameDescriptionTmpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameDescriptionTmpl is a template item which includes a name, description and list of scopes.
|
||||||
|
type NameDescriptionTmpl struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
Scopes []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCommitLintCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseCommitLint,
|
||||||
|
Short: "Generate commit lint files",
|
||||||
|
RunE: commitLintRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
var commitScopesExtra = []NameDescriptionTmpl{
|
||||||
|
{"api", "used for changes that change the openapi specification", nil},
|
||||||
|
{"cmd", "used for changes to the `%s` top level binaries", nil},
|
||||||
|
{"web", "used for changes to the React based frontend", nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
var commitTypes = []NameDescriptionTmpl{
|
||||||
|
{"build", "Changes that affect the build system or external dependencies", []string{"bundler", "deps", "docker", "go", "npm"}},
|
||||||
|
{"ci", "Changes to our CI configuration files and scripts", []string{"autheliabot", "buildkite", "codecov", "golangci-lint", "renovate", "reviewdog"}},
|
||||||
|
{"docs", "Documentation only changes", nil},
|
||||||
|
{"feat", "A new feature", nil},
|
||||||
|
{"fix", "A bug fix", nil},
|
||||||
|
{"i18n", "Updating translations or internationalization settings", nil},
|
||||||
|
{"perf", "A code change that improves performance", nil},
|
||||||
|
{"refactor", "A code change that neither fixes a bug nor adds a feature", nil},
|
||||||
|
{"release", "Releasing a new version of Authelia", nil},
|
||||||
|
{"test", "Adding missing tests or correcting existing tests", nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
var commitTypesExtra = []string{"revert"}
|
||||||
|
|
||||||
|
func getGoPackages(dir string) (pkgs []string, err error) {
|
||||||
|
var (
|
||||||
|
entries []os.DirEntry
|
||||||
|
entriesSub []os.DirEntry
|
||||||
|
)
|
||||||
|
|
||||||
|
if entries, err = os.ReadDir(dir); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to detect go packages in directory '%s': %w", dir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
if !entry.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if entriesSub, err = os.ReadDir(filepath.Join(dir, entry.Name())); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entrySub := range entriesSub {
|
||||||
|
if entrySub.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(entrySub.Name(), ".go") {
|
||||||
|
pkgs = append(pkgs, entry.Name())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commitLintRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var root, pathCommitLintConfig, pathDocsCommitMessageGuidelines string
|
||||||
|
|
||||||
|
if root, err = cmd.Flags().GetString(cmdFlagRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathCommitLintConfig, err = cmd.Flags().GetString(cmdFlagFileConfigCommitLint); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathDocsCommitMessageGuidelines, err = cmd.Flags().GetString(cmdFlagFileDocsCommitMsgGuidelines); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := &CommitMessageTmpl{
|
||||||
|
Scopes: ScopesTmpl{
|
||||||
|
All: []string{},
|
||||||
|
Packages: []string{},
|
||||||
|
Extra: []NameDescriptionTmpl{},
|
||||||
|
},
|
||||||
|
Types: TypesTmpl{
|
||||||
|
List: []string{},
|
||||||
|
Details: []NameDescriptionTmpl{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
cmds []string
|
||||||
|
pkgs []string
|
||||||
|
)
|
||||||
|
|
||||||
|
if cmds, err = getGoPackages(filepath.Join(root, subPathCmd)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkgs, err = getGoPackages(filepath.Join(root, subPathInternal)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Scopes.All = append(data.Scopes.All, pkgs...)
|
||||||
|
data.Scopes.Packages = append(data.Scopes.Packages, pkgs...)
|
||||||
|
|
||||||
|
for _, scope := range commitScopesExtra {
|
||||||
|
switch scope.Name {
|
||||||
|
case subPathCmd:
|
||||||
|
data.Scopes.Extra = append(data.Scopes.Extra, NameDescriptionTmpl{Name: scope.Name, Description: fmt.Sprintf(scope.Description, strings.Join(cmds, "|"))})
|
||||||
|
default:
|
||||||
|
data.Scopes.Extra = append(data.Scopes.Extra, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Scopes.All = append(data.Scopes.All, scope.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cType := range commitTypes {
|
||||||
|
data.Types.List = append(data.Types.List, cType.Name)
|
||||||
|
data.Types.Details = append(data.Types.Details, cType)
|
||||||
|
|
||||||
|
data.Scopes.All = append(data.Scopes.All, cType.Scopes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Types.List = append(data.Types.List, commitTypesExtra...)
|
||||||
|
|
||||||
|
sort.Slice(data.Scopes.All, func(i, j int) bool {
|
||||||
|
return data.Scopes.All[i] < data.Scopes.All[j]
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Slice(data.Scopes.Packages, func(i, j int) bool {
|
||||||
|
return data.Scopes.Packages[i] < data.Scopes.Packages[j]
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Slice(data.Scopes.Extra, func(i, j int) bool {
|
||||||
|
return data.Scopes.Extra[i].Name < data.Scopes.Extra[j].Name
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Slice(data.Types.List, func(i, j int) bool {
|
||||||
|
return data.Types.List[i] < data.Types.List[j]
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Slice(data.Types.Details, func(i, j int) bool {
|
||||||
|
return data.Types.Details[i].Name < data.Types.Details[j].Name
|
||||||
|
})
|
||||||
|
|
||||||
|
var f *os.File
|
||||||
|
|
||||||
|
fullPathCommitLintConfig := filepath.Join(root, pathCommitLintConfig)
|
||||||
|
|
||||||
|
if f, err = os.Create(fullPathCommitLintConfig); err != nil {
|
||||||
|
return fmt.Errorf("failed to create output file '%s': %w", fullPathCommitLintConfig, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplDotCommitLintRC.Execute(f, data); err != nil {
|
||||||
|
return fmt.Errorf("failed to write output file '%s': %w", fullPathCommitLintConfig, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close output file '%s': %w", fullPathCommitLintConfig, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fullPathDocsCommitMessageGuidelines := filepath.Join(root, pathDocsCommitMessageGuidelines)
|
||||||
|
|
||||||
|
if f, err = os.Create(fullPathDocsCommitMessageGuidelines); err != nil {
|
||||||
|
return fmt.Errorf("failed to create output file '%s': %w", fullPathDocsCommitMessageGuidelines, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplDocsCommitMessageGuidelines.Execute(f, data); err != nil {
|
||||||
|
return fmt.Errorf("failed to write output file '%s': %w", fullPathDocsCommitMessageGuidelines, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close output file '%s': %w", fullPathDocsCommitMessageGuidelines, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -6,30 +6,14 @@ import (
|
||||||
|
|
||||||
func newDocsCmd() *cobra.Command {
|
func newDocsCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "docs",
|
Use: cmdUseDocs,
|
||||||
Short: "Generate docs",
|
Short: "Generate docs",
|
||||||
RunE: docsRunE,
|
RunE: rootSubCommandsRunE,
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.PersistentFlags().StringP("cwd", "C", "", "Sets the CWD for git commands")
|
cmd.AddCommand(newDocsCLICmd(), newDocsDataCmd(), newDocsDateCmd())
|
||||||
cmd.AddCommand(newDocsCLICmd(), newDocsDateCmd())
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func docsRunE(cmd *cobra.Command, args []string) (err error) {
|
|
||||||
for _, subCmd := range cmd.Commands() {
|
|
||||||
switch {
|
|
||||||
case subCmd.RunE != nil:
|
|
||||||
if err = subCmd.RunE(subCmd, args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case subCmd.Run != nil:
|
|
||||||
subCmd.Run(subCmd, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,52 +16,50 @@ import (
|
||||||
|
|
||||||
func newDocsCLICmd() *cobra.Command {
|
func newDocsCLICmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "cli",
|
Use: cmdUseDocsCLI,
|
||||||
Short: "Generate CLI docs",
|
Short: "Generate CLI docs",
|
||||||
RunE: docsCLIRunE,
|
RunE: docsCLIRunE,
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringP("directory", "d", "./docs/content/en/reference/cli", "The directory to store the markdown in")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func docsCLIRunE(cmd *cobra.Command, args []string) (err error) {
|
func docsCLIRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
var root string
|
var outputPath string
|
||||||
|
|
||||||
if root, err = cmd.Flags().GetString("directory"); err != nil {
|
if outputPath, err = getPFlagPath(cmd.Flags(), cmdFlagRoot, cmdFlagDocs, cmdFlagDocsContent, cmdFlagDocsCLIReference); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = os.MkdirAll(root, 0775); err != nil {
|
if err = os.MkdirAll(outputPath, 0775); err != nil {
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = genCLIDoc(commands.NewRootCmd(), filepath.Join(root, "authelia")); err != nil {
|
if err = genCLIDoc(commands.NewRootCmd(), filepath.Join(outputPath, "authelia")); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = genCLIDocWriteIndex(root, "authelia"); err != nil {
|
if err = genCLIDocWriteIndex(outputPath, "authelia"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = genCLIDoc(cmdscripts.NewRootCmd(), filepath.Join(root, "authelia-scripts")); err != nil {
|
if err = genCLIDoc(cmdscripts.NewRootCmd(), filepath.Join(outputPath, "authelia-scripts")); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = genCLIDocWriteIndex(root, "authelia-scripts"); err != nil {
|
if err = genCLIDocWriteIndex(outputPath, "authelia-scripts"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = genCLIDoc(newRootCmd(), filepath.Join(root, "authelia-gen")); err != nil {
|
if err = genCLIDoc(newRootCmd(), filepath.Join(outputPath, cmdUseRoot)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = genCLIDocWriteIndex(root, "authelia-gen"); err != nil {
|
if err = genCLIDocWriteIndex(outputPath, cmdUseRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +67,16 @@ func docsCLIRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func genCLIDoc(cmd *cobra.Command, path string) (err error) {
|
func genCLIDoc(cmd *cobra.Command, path string) (err error) {
|
||||||
|
if _, err = os.Stat(path); err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil || !os.IsNotExist(err) {
|
||||||
|
if err = os.RemoveAll(path); err != nil {
|
||||||
|
return fmt.Errorf("failed to remove docs: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err = os.Mkdir(path, 0755); err != nil {
|
if err = os.Mkdir(path, 0755); err != nil {
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/authelia/authelia/v4/internal/configuration"
|
||||||
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newDocsDataCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseDocsData,
|
||||||
|
Short: "Generate docs data files",
|
||||||
|
RunE: rootSubCommandsRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(newDocsDataMiscCmd(), newDocsDataKeysCmd())
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDocsDataMiscCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseDocsDataMisc,
|
||||||
|
Short: "Generate docs data file misc.json",
|
||||||
|
RunE: docsDataMiscRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func docsDataMiscRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
data := DocsDataMisc{
|
||||||
|
CSP: TemplateCSP{
|
||||||
|
PlaceholderNONCE: codeCSPNonce,
|
||||||
|
TemplateDefault: buildCSP(codeCSPProductionDefaultSrc, codeCSPValuesCommon, codeCSPValuesProduction),
|
||||||
|
TemplateDevelopment: buildCSP(codeCSPDevelopmentDefaultSrc, codeCSPValuesCommon, codeCSPValuesDevelopment),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
data.CSP.TemplateDefault = strings.ReplaceAll(data.CSP.TemplateDefault, "%s", codeCSPNonce)
|
||||||
|
data.CSP.TemplateDevelopment = strings.ReplaceAll(data.CSP.TemplateDevelopment, "%s", codeCSPNonce)
|
||||||
|
|
||||||
|
var (
|
||||||
|
outputPath string
|
||||||
|
dataJSON []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if outputPath, err = getPFlagPath(cmd.Flags(), cmdFlagRoot, cmdFlagDocs, cmdFlagDocsData, cmdFlagDocsDataMisc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dataJSON, err = json.Marshal(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = os.WriteFile(outputPath, dataJSON, 0600); err != nil {
|
||||||
|
return fmt.Errorf("failed to write file '%s': %w", outputPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDocsDataKeysCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseKeys,
|
||||||
|
Short: "Generate the docs data file for configuration keys",
|
||||||
|
RunE: docsKeysRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func docsKeysRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
//nolint:prealloc
|
||||||
|
var (
|
||||||
|
data []ConfigurationKey
|
||||||
|
)
|
||||||
|
|
||||||
|
keys := readTags("", reflect.TypeOf(schema.Configuration{}))
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
if strings.Contains(key, "[]") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ck := ConfigurationKey{
|
||||||
|
Path: key,
|
||||||
|
Secret: configuration.IsSecretKey(key),
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case ck.Secret:
|
||||||
|
ck.Env = configuration.ToEnvironmentSecretKey(key, configuration.DefaultEnvPrefix, configuration.DefaultEnvDelimiter)
|
||||||
|
default:
|
||||||
|
ck.Env = configuration.ToEnvironmentKey(key, configuration.DefaultEnvPrefix, configuration.DefaultEnvDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
data = append(data, ck)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
dataJSON []byte
|
||||||
|
outputPath string
|
||||||
|
)
|
||||||
|
|
||||||
|
if outputPath, err = getPFlagPath(cmd.Flags(), cmdFlagRoot, cmdFlagDocs, cmdFlagDocsData, cmdFlagDocsDataKeys); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dataJSON, err = json.Marshal(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = os.WriteFile(outputPath, dataJSON, 0600); err != nil {
|
||||||
|
return fmt.Errorf("failed to write file '%s': %w", outputPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -17,14 +17,13 @@ import (
|
||||||
|
|
||||||
func newDocsDateCmd() *cobra.Command {
|
func newDocsDateCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "date",
|
Use: cmdUseDocsDate,
|
||||||
Short: "Generate doc dates",
|
Short: "Generate doc dates",
|
||||||
RunE: docsDateRunE,
|
RunE: docsDateRunE,
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringP("directory", "d", "./docs/content", "The directory to modify")
|
|
||||||
cmd.Flags().String("commit-until", "HEAD", "The commit to check the logs until")
|
cmd.Flags().String("commit-until", "HEAD", "The commit to check the logs until")
|
||||||
cmd.Flags().String("commit-since", "", "The commit to check the logs since")
|
cmd.Flags().String("commit-since", "", "The commit to check the logs since")
|
||||||
|
|
||||||
|
@ -33,14 +32,14 @@ func newDocsDateCmd() *cobra.Command {
|
||||||
|
|
||||||
func docsDateRunE(cmd *cobra.Command, args []string) (err error) {
|
func docsDateRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
var (
|
var (
|
||||||
dir, cwd, commitUtil, commitSince, commitFilter string
|
pathDocsContent, cwd, commitUtil, commitSince, commitFilter string
|
||||||
)
|
)
|
||||||
|
|
||||||
if dir, err = cmd.Flags().GetString("directory"); err != nil {
|
if pathDocsContent, err = getPFlagPath(cmd.Flags(), cmdFlagRoot, cmdFlagDocs, cmdFlagDocsContent); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cwd, err = cmd.Flags().GetString("cwd"); err != nil {
|
if cwd, err = cmd.Flags().GetString(cmdFlagCwd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ func docsDateRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
commitFilter = fmt.Sprintf("%s...%s", commitUtil, commitSince)
|
commitFilter = fmt.Sprintf("%s...%s", commitUtil, commitSince)
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
|
return filepath.Walk(pathDocsContent, func(path string, info fs.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -76,7 +75,7 @@ func docsDateRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
frontmatter := map[string]interface{}{}
|
frontmatter := map[string]any{}
|
||||||
|
|
||||||
if err = yaml.Unmarshal(frontmatterBytes, frontmatter); err != nil {
|
if err = yaml.Unmarshal(frontmatterBytes, frontmatter); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -163,7 +162,7 @@ func replaceDates(path string, date time.Time, dateGit *time.Time) {
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
if found < 2 && frontmatter < 2 {
|
if found < 2 && frontmatter < 2 {
|
||||||
switch {
|
switch {
|
||||||
case scanner.Text() == frontmatterDelimiterLine:
|
case scanner.Text() == delimiterLineFrontMatter:
|
||||||
buf.Write(scanner.Bytes())
|
buf.Write(scanner.Bytes())
|
||||||
frontmatter++
|
frontmatter++
|
||||||
case frontmatter != 0 && strings.HasPrefix(scanner.Text(), "date: "):
|
case frontmatter != 0 && strings.HasPrefix(scanner.Text(), "date: "):
|
||||||
|
@ -207,13 +206,13 @@ func getFrontmatter(path string) []byte {
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
if start {
|
if start {
|
||||||
if scanner.Text() == frontmatterDelimiterLine {
|
if scanner.Text() == delimiterLineFrontMatter {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.Write(scanner.Bytes())
|
buf.Write(scanner.Bytes())
|
||||||
buf.Write(newline)
|
buf.Write(newline)
|
||||||
} else if scanner.Text() == frontmatterDelimiterLine {
|
} else if scanner.Text() == delimiterLineFrontMatter {
|
||||||
start = true
|
start = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newGitHubCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseGitHub,
|
||||||
|
Short: "Generate GitHub files",
|
||||||
|
RunE: rootSubCommandsRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(newGitHubIssueTemplatesCmd())
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGitHubIssueTemplatesCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseGitHubIssueTemplates,
|
||||||
|
Short: "Generate GitHub issue templates",
|
||||||
|
RunE: rootSubCommandsRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(newGitHubIssueTemplatesBugReportCmd(), newGitHubIssueTemplatesFeatureCmd())
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGitHubIssueTemplatesFeatureCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseGitHubIssueTemplatesFR,
|
||||||
|
Short: "Generate GitHub feature request issue template",
|
||||||
|
RunE: cmdGitHubIssueTemplatesFeatureRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGitHubIssueTemplatesBugReportCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseGitHubIssueTemplatesBR,
|
||||||
|
Short: "Generate GitHub bug report issue template",
|
||||||
|
RunE: cmdGitHubIssueTemplatesBugReportRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGitHubIssueTemplatesFeatureRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var (
|
||||||
|
cwd, file, root string
|
||||||
|
tags, tagsFuture []string
|
||||||
|
latestMajor, latestMinor, latestPatch, versions int
|
||||||
|
)
|
||||||
|
|
||||||
|
if cwd, err = cmd.Flags().GetString(cmdFlagCwd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if root, err = cmd.Flags().GetString(cmdFlagRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if file, err = cmd.Flags().GetString(cmdFlagFeatureRequest); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if versions, err = cmd.Flags().GetInt(cmdFlagVersions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tags, err = getGitTags(cwd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
latest := tags[0]
|
||||||
|
|
||||||
|
if _, err = fmt.Sscanf(latest, "v%d.%d.%d", &latestMajor, &latestMinor, &latestPatch); err != nil {
|
||||||
|
return fmt.Errorf("error occurred parsing version as semver: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
minor int
|
||||||
|
)
|
||||||
|
|
||||||
|
for minor = latestMinor + 1; minor < latestMinor+versions; minor++ {
|
||||||
|
tagsFuture = append(tagsFuture, fmt.Sprintf("v%d.%d.0", latestMajor, minor))
|
||||||
|
}
|
||||||
|
|
||||||
|
tagsFuture = append(tagsFuture, fmt.Sprintf("v%d.0.0", latestMajor+1))
|
||||||
|
|
||||||
|
var (
|
||||||
|
f *os.File
|
||||||
|
)
|
||||||
|
|
||||||
|
fullPath := filepath.Join(root, file)
|
||||||
|
|
||||||
|
if f, err = os.Create(fullPath); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file '%s': %w", fullPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := &tmplIssueTemplateData{
|
||||||
|
Labels: []string{labelTypeFeature.String(), labelStatusNeedsDesign.String(), labelPriorityNormal.String()},
|
||||||
|
Versions: tagsFuture,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplIssueTemplateFeature.Execute(f, data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGitHubIssueTemplatesBugReportRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var (
|
||||||
|
cwd, file, dirRoot string
|
||||||
|
latestMinor, versions int
|
||||||
|
|
||||||
|
tags []string
|
||||||
|
)
|
||||||
|
|
||||||
|
if cwd, err = cmd.Flags().GetString(cmdFlagCwd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dirRoot, err = cmd.Flags().GetString(cmdFlagRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if file, err = cmd.Flags().GetString(cmdFlagBugReport); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if versions, err = cmd.Flags().GetInt(cmdFlagVersions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tags, err = getGitTags(cwd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
latest := tags[0]
|
||||||
|
|
||||||
|
latestParts := strings.Split(latest, ".")
|
||||||
|
|
||||||
|
if len(latestParts) < 2 {
|
||||||
|
return fmt.Errorf("error extracting latest minor version from tag: %s does not appear to be a semver", latest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if latestMinor, err = strconv.Atoi(latestParts[1]); err != nil {
|
||||||
|
return fmt.Errorf("error extracting latest minor version from tag: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:prealloc
|
||||||
|
var (
|
||||||
|
tagsRecent []string
|
||||||
|
parts []string
|
||||||
|
minor int
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
if parts = strings.Split(tag, "."); len(parts) < 2 {
|
||||||
|
return fmt.Errorf("error extracting minor version from tag: %s does not appear to be a semver", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if minor, err = strconv.Atoi(parts[1]); err != nil {
|
||||||
|
return fmt.Errorf("error extracting minor version from tag: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if minor < latestMinor-versions {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
tagsRecent = append(tagsRecent, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
f *os.File
|
||||||
|
)
|
||||||
|
|
||||||
|
fullPath := filepath.Join(dirRoot, file)
|
||||||
|
|
||||||
|
if f, err = os.Create(fullPath); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file '%s': %w", fullPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := &tmplIssueTemplateData{
|
||||||
|
Labels: []string{labelTypeBugUnconfirmed.String(), labelStatusNeedsTriage.String(), labelPriorityNormal.String()},
|
||||||
|
Versions: tagsRecent,
|
||||||
|
Proxies: []string{"Caddy", "Traefik", "Envoy", "Istio", "NGINX", "SWAG", "NGINX Proxy Manager", "HAProxy"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplGitHubIssueTemplateBug.Execute(f, data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGitTags(cwd string) (tags []string, err error) {
|
||||||
|
var (
|
||||||
|
args []string
|
||||||
|
tagsOutput []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(cwd) != 0 {
|
||||||
|
args = append(args, "-C", cwd)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, "tag", "--sort=-creatordate")
|
||||||
|
|
||||||
|
cmd := exec.Command("git", args...)
|
||||||
|
|
||||||
|
if tagsOutput, err = cmd.Output(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Split(string(tagsOutput), "\n"), nil
|
||||||
|
}
|
|
@ -0,0 +1,215 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"golang.org/x/text/language/display"
|
||||||
|
|
||||||
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newLocalesCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseLocales,
|
||||||
|
Short: "Generate locales files",
|
||||||
|
RunE: localesRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func localesRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var (
|
||||||
|
root, pathLocales string
|
||||||
|
pathWebI18NIndex, pathDocsDataLanguages string
|
||||||
|
)
|
||||||
|
|
||||||
|
if root, err = cmd.Flags().GetString(cmdFlagRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathLocales, err = cmd.Flags().GetString(cmdFlagDirLocales); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathWebI18NIndex, err = cmd.Flags().GetString(cmdFlagFileWebI18N); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathDocsDataLanguages, err = getPFlagPath(cmd.Flags(), cmdFlagRoot, cmdFlagDocs, cmdFlagDocsData, cmdFlagDocsDataLanguages); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := getLanguages(filepath.Join(root, pathLocales))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fullPathWebI18NIndex := filepath.Join(root, pathWebI18NIndex)
|
||||||
|
|
||||||
|
var (
|
||||||
|
f *os.File
|
||||||
|
dataJSON []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if f, err = os.Create(fullPathWebI18NIndex); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file '%s': %w", fullPathWebI18NIndex, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tmplWebI18NIndex.Execute(f, data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dataJSON, err = json.Marshal(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fullPathDocsDataLanguages := filepath.Join(root, pathDocsDataLanguages)
|
||||||
|
|
||||||
|
if err = os.WriteFile(fullPathDocsDataLanguages, dataJSON, 0600); err != nil {
|
||||||
|
return fmt.Errorf("failed to write file '%s': %w", fullPathDocsDataLanguages, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gocyclo
|
||||||
|
func getLanguages(dir string) (languages *Languages, err error) {
|
||||||
|
//nolint:prealloc
|
||||||
|
var locales []string
|
||||||
|
|
||||||
|
languages = &Languages{
|
||||||
|
Defaults: DefaultsLanguages{
|
||||||
|
Namespace: localeNamespaceDefault,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultTag language.Tag
|
||||||
|
|
||||||
|
if defaultTag, err = language.Parse(localeDefault); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse default language: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
languages.Defaults.Language = Language{
|
||||||
|
Display: display.English.Tags().Name(defaultTag),
|
||||||
|
Locale: localeDefault,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = filepath.Walk(dir, func(path string, info fs.FileInfo, errWalk error) (err error) {
|
||||||
|
if errWalk != nil {
|
||||||
|
return errWalk
|
||||||
|
}
|
||||||
|
|
||||||
|
nameLower := strings.ToLower(info.Name())
|
||||||
|
ext := filepath.Ext(nameLower)
|
||||||
|
ns := strings.Replace(nameLower, ext, "", 1)
|
||||||
|
|
||||||
|
if ext != ".json" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !utils.IsStringInSlice(ns, languages.Namespaces) {
|
||||||
|
languages.Namespaces = append(languages.Namespaces, ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
fdir, _ := filepath.Split(path)
|
||||||
|
|
||||||
|
locale := filepath.Base(fdir)
|
||||||
|
|
||||||
|
if utils.IsStringInSlice(locale, locales) {
|
||||||
|
for i, l := range languages.Languages {
|
||||||
|
if l.Locale == locale {
|
||||||
|
if utils.IsStringInSlice(ns, languages.Languages[i].Namespaces) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
languages.Languages[i].Namespaces = append(languages.Languages[i].Namespaces, ns)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var localeReal string
|
||||||
|
|
||||||
|
parts := strings.SplitN(locale, "-", 2)
|
||||||
|
if len(parts) == 2 && strings.EqualFold(parts[0], parts[1]) {
|
||||||
|
localeReal = parts[0]
|
||||||
|
} else {
|
||||||
|
localeReal = locale
|
||||||
|
}
|
||||||
|
|
||||||
|
var tag language.Tag
|
||||||
|
|
||||||
|
if tag, err = language.Parse(localeReal); err != nil {
|
||||||
|
return fmt.Errorf("failed to parse language '%s': %w", localeReal, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l := Language{
|
||||||
|
Display: display.English.Tags().Name(tag),
|
||||||
|
Locale: localeReal,
|
||||||
|
Namespaces: []string{ns},
|
||||||
|
Fallbacks: []string{languages.Defaults.Language.Locale},
|
||||||
|
Tag: tag,
|
||||||
|
}
|
||||||
|
|
||||||
|
languages.Languages = append(languages.Languages, l)
|
||||||
|
|
||||||
|
locales = append(locales, l.Locale)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var langs []Language //nolint:prealloc
|
||||||
|
|
||||||
|
for i, lang := range languages.Languages {
|
||||||
|
p := lang.Tag.Parent()
|
||||||
|
|
||||||
|
if p.String() == "und" || strings.Contains(p.String(), "-") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if utils.IsStringInSlice(p.String(), locales) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.String() != lang.Locale {
|
||||||
|
lang.Fallbacks = append([]string{p.String()}, lang.Fallbacks...)
|
||||||
|
}
|
||||||
|
|
||||||
|
languages.Languages[i] = lang
|
||||||
|
|
||||||
|
l := Language{
|
||||||
|
Display: display.English.Tags().Name(p),
|
||||||
|
Locale: p.String(),
|
||||||
|
Namespaces: lang.Namespaces,
|
||||||
|
Fallbacks: []string{languages.Defaults.Language.Locale},
|
||||||
|
Tag: p,
|
||||||
|
}
|
||||||
|
|
||||||
|
langs = append(langs, l)
|
||||||
|
|
||||||
|
locales = append(locales, l.Locale)
|
||||||
|
}
|
||||||
|
|
||||||
|
languages.Languages = append(languages.Languages, langs...)
|
||||||
|
|
||||||
|
sort.Slice(languages.Languages, func(i, j int) bool {
|
||||||
|
return languages.Languages[i].Locale == localeDefault || languages.Languages[i].Locale < languages.Languages[j].Locale
|
||||||
|
})
|
||||||
|
|
||||||
|
return languages, nil
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rootCmd *cobra.Command
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd = newRootCmd()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRootCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: cmdUseRoot,
|
||||||
|
Short: "Authelia's generator tooling",
|
||||||
|
RunE: rootSubCommandsRunE,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.PersistentFlags().StringP(cmdFlagCwd, "C", "", "Sets the CWD for git commands")
|
||||||
|
cmd.PersistentFlags().StringP(cmdFlagRoot, "d", dirCurrent, "The repository root")
|
||||||
|
cmd.PersistentFlags().StringSliceP(cmdFlagExclude, "X", nil, "Sets the names of excluded generators")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagFeatureRequest, fileGitHubIssueTemplateFR, "Sets the path of the feature request issue template file")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagBugReport, fileGitHubIssueTemplateBR, "Sets the path of the bug report issue template file")
|
||||||
|
cmd.PersistentFlags().Int(cmdFlagVersions, 5, "the maximum number of minor versions to list in output templates")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDirLocales, dirLocales, "The locales directory in relation to the root")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagFileWebI18N, fileWebI18NIndex, "The i18n typescript configuration file in relation to the root")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDocsDataLanguages, fileDocsDataLanguages, "The languages docs data file in relation to the docs data folder")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDocsDataMisc, fileDocsDataMisc, "The misc docs data file in relation to the docs data folder")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDocsCLIReference, dirDocsCLIReference, "The directory to store the markdown in")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDocs, dirDocs, "The directory with the docs")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDocsContent, dirDocsContent, "The directory with the docs content")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDocsData, dirDocsData, "The directory with the docs data")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagFileConfigKeys, fileCodeConfigKeys, "Sets the path of the keys file")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagDocsDataKeys, fileDocsDataConfigKeys, "Sets the path of the docs keys file")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagPackageConfigKeys, pkgConfigSchema, "Sets the package name of the keys file")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagFileScriptsGen, fileScriptsGen, "Sets the path of the authelia-scripts gen file")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagFileServerGenerated, fileServerGenerated, "Sets the path of the server generated file")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagPackageScriptsGen, pkgScriptsGen, "Sets the package name of the authelia-scripts gen file")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagFileConfigCommitLint, fileCICommitLintConfig, "The commit lint javascript configuration file in relation to the root")
|
||||||
|
cmd.PersistentFlags().String(cmdFlagFileDocsCommitMsgGuidelines, fileDocsCommitMessageGuidelines, "The commit message guidelines documentation file in relation to the root")
|
||||||
|
|
||||||
|
cmd.AddCommand(newCodeCmd(), newDocsCmd(), newGitHubCmd(), newLocalesCmd(), newCommitLintCmd())
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func rootSubCommandsRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var exclude []string
|
||||||
|
|
||||||
|
if exclude, err = cmd.Flags().GetStringSlice(cmdFlagExclude); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
subCmds := cmd.Commands()
|
||||||
|
|
||||||
|
switch cmd.Use {
|
||||||
|
case cmdUseRoot:
|
||||||
|
sort.Slice(subCmds, func(i, j int) bool {
|
||||||
|
switch subCmds[j].Use {
|
||||||
|
case cmdUseDocs:
|
||||||
|
// Ensure `docs` subCmd is last.
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return subCmds[i].Use < subCmds[j].Use
|
||||||
|
}
|
||||||
|
})
|
||||||
|
case cmdUseDocs:
|
||||||
|
sort.Slice(subCmds, func(i, j int) bool {
|
||||||
|
switch subCmds[j].Use {
|
||||||
|
case cmdUseDocsDate:
|
||||||
|
// Ensure `date` subCmd is last.
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return subCmds[i].Use < subCmds[j].Use
|
||||||
|
}
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
sort.Slice(subCmds, func(i, j int) bool {
|
||||||
|
return subCmds[i].Use < subCmds[j].Use
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, subCmd := range subCmds {
|
||||||
|
if subCmd.Use == cmdUseCompletion || strings.HasPrefix(subCmd.Use, "help ") || utils.IsStringSliceContainsAny([]string{resolveCmdName(subCmd), subCmd.Use}, exclude) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.SetArgs(rootCmdGetArgs(subCmd, args))
|
||||||
|
|
||||||
|
if err = rootCmd.Execute(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveCmdName(cmd *cobra.Command) string {
|
||||||
|
parent := cmd.Parent()
|
||||||
|
|
||||||
|
if parent != nil && parent.Use != cmd.Use && parent.Use != cmdUseRoot {
|
||||||
|
return resolveCmdName(parent) + "." + cmd.Use
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd.Use
|
||||||
|
}
|
||||||
|
|
||||||
|
func rootCmdGetArgs(cmd *cobra.Command, args []string) []string {
|
||||||
|
for {
|
||||||
|
if cmd == rootCmd {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append([]string{cmd.Use}, args...)
|
||||||
|
|
||||||
|
cmd = cmd.Parent()
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
|
@ -1,7 +1,113 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
const (
|
const (
|
||||||
dateFmtRFC2822 = "Mon, _2 Jan 2006 15:04:05 -0700"
|
dirCurrent = "./"
|
||||||
dateFmtYAML = "2006-01-02T15:04:05-07:00"
|
dirLocales = "internal/server/locales"
|
||||||
frontmatterDelimiterLine = "---"
|
|
||||||
|
subPathCmd = "cmd"
|
||||||
|
subPathInternal = "internal"
|
||||||
|
|
||||||
|
fileCICommitLintConfig = "web/.commitlintrc.js"
|
||||||
|
fileWebI18NIndex = "web/src/i18n/index.ts"
|
||||||
|
|
||||||
|
fileDocsCommitMessageGuidelines = "docs/content/en/contributing/guidelines/commit-message.md"
|
||||||
|
|
||||||
|
fileCodeConfigKeys = "internal/configuration/schema/keys.go"
|
||||||
|
fileServerGenerated = "internal/server/gen.go"
|
||||||
|
fileScriptsGen = "cmd/authelia-scripts/cmd/gen.go"
|
||||||
|
|
||||||
|
dirDocs = "docs"
|
||||||
|
dirDocsContent = "content"
|
||||||
|
dirDocsData = "data"
|
||||||
|
dirDocsCLIReference = "en/reference/cli"
|
||||||
|
|
||||||
|
fileDocsDataLanguages = "languages.json"
|
||||||
|
fileDocsDataMisc = "misc.json"
|
||||||
|
fileDocsDataConfigKeys = "configkeys.json"
|
||||||
|
|
||||||
|
fileGitHubIssueTemplateFR = ".github/ISSUE_TEMPLATE/feature-request.yml"
|
||||||
|
fileGitHubIssueTemplateBR = ".github/ISSUE_TEMPLATE/bug-report.yml"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dateFmtRFC2822 = "Mon, _2 Jan 2006 15:04:05 -0700"
|
||||||
|
dateFmtYAML = "2006-01-02T15:04:05-07:00"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
delimiterLineFrontMatter = "---"
|
||||||
|
|
||||||
|
localeDefault = "en"
|
||||||
|
localeNamespaceDefault = "portal"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
pkgConfigSchema = "schema"
|
||||||
|
pkgScriptsGen = "cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cmdUseRoot = "authelia-gen"
|
||||||
|
cmdUseCompletion = "completion"
|
||||||
|
cmdUseDocs = "docs"
|
||||||
|
cmdUseDocsDate = "date"
|
||||||
|
cmdUseDocsCLI = "cli"
|
||||||
|
cmdUseDocsData = "data"
|
||||||
|
cmdUseDocsDataMisc = "misc"
|
||||||
|
cmdUseGitHub = "github"
|
||||||
|
cmdUseGitHubIssueTemplates = "issue-templates"
|
||||||
|
cmdUseGitHubIssueTemplatesFR = "feature-request"
|
||||||
|
cmdUseGitHubIssueTemplatesBR = "bug-report"
|
||||||
|
cmdUseLocales = "locales"
|
||||||
|
cmdUseCommitLint = "commit-lint"
|
||||||
|
cmdUseCode = "code"
|
||||||
|
cmdUseCodeScripts = "scripts"
|
||||||
|
cmdUseKeys = "keys"
|
||||||
|
cmdUseServer = "server"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cmdFlagRoot = "dir.root"
|
||||||
|
cmdFlagExclude = "exclude"
|
||||||
|
cmdFlagVersions = "versions"
|
||||||
|
cmdFlagDirLocales = "dir.locales"
|
||||||
|
cmdFlagDocsCLIReference = "dir.docs.cli-reference"
|
||||||
|
cmdFlagDocsContent = "dir.docs.content"
|
||||||
|
cmdFlagDocsData = "dir.docs.data"
|
||||||
|
cmdFlagDocs = "dir.docs"
|
||||||
|
cmdFlagDocsDataLanguages = "file.docs.data.languages"
|
||||||
|
cmdFlagDocsDataMisc = "file.docs.data.misc"
|
||||||
|
cmdFlagDocsDataKeys = "file.docs.data.keys"
|
||||||
|
cmdFlagCwd = "cwd"
|
||||||
|
cmdFlagFileConfigKeys = "file.configuration-keys"
|
||||||
|
cmdFlagFileScriptsGen = "file.scripts.gen"
|
||||||
|
cmdFlagFileServerGenerated = "file.server.generated"
|
||||||
|
cmdFlagFileConfigCommitLint = "file.commit-lint-config"
|
||||||
|
cmdFlagFileDocsCommitMsgGuidelines = "file.docs-commit-msg-guidelines"
|
||||||
|
cmdFlagFileWebI18N = "file.web-i18n"
|
||||||
|
cmdFlagFeatureRequest = "file.feature-request"
|
||||||
|
cmdFlagBugReport = "file.bug-report"
|
||||||
|
cmdFlagPackageConfigKeys = "package.configuration.keys"
|
||||||
|
cmdFlagPackageScriptsGen = "package.scripts.gen"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
codeCSPProductionDefaultSrc = "'self'"
|
||||||
|
codeCSPDevelopmentDefaultSrc = "'self' 'unsafe-eval'"
|
||||||
|
codeCSPNonce = "${NONCE}"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
codeCSPValuesCommon = []CSPValue{
|
||||||
|
{Name: "default-src", Value: ""},
|
||||||
|
{Name: "frame-src", Value: "'none'"},
|
||||||
|
{Name: "object-src", Value: "'none'"},
|
||||||
|
{Name: "style-src", Value: "'self' 'nonce-%s'"},
|
||||||
|
{Name: "frame-ancestors", Value: "'none'"},
|
||||||
|
{Name: "base-uri", Value: "'self'"},
|
||||||
|
}
|
||||||
|
|
||||||
|
codeCSPValuesProduction = []CSPValue{}
|
||||||
|
|
||||||
|
codeCSPValuesDevelopment = []CSPValue{}
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getPFlagPath(flags *pflag.FlagSet, flagNames ...string) (fullPath string, err error) {
|
||||||
|
if len(flagNames) == 0 {
|
||||||
|
return "", fmt.Errorf("no flag names")
|
||||||
|
}
|
||||||
|
|
||||||
|
var p string
|
||||||
|
|
||||||
|
for i, flagName := range flagNames {
|
||||||
|
if p, err = flags.GetString(flagName); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to lookup flag '%s': %w", flagName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
fullPath = p
|
||||||
|
} else {
|
||||||
|
fullPath = filepath.Join(fullPath, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildCSP(defaultSrc string, ruleSets ...[]CSPValue) string {
|
||||||
|
var rules []string
|
||||||
|
|
||||||
|
for _, ruleSet := range ruleSets {
|
||||||
|
for _, rule := range ruleSet {
|
||||||
|
switch rule.Name {
|
||||||
|
case "default-src":
|
||||||
|
rules = append(rules, fmt.Sprintf("%s %s", rule.Name, defaultSrc))
|
||||||
|
default:
|
||||||
|
rules = append(rules, fmt.Sprintf("%s %s", rule.Name, rule.Value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(rules, "; ")
|
||||||
|
}
|
|
@ -1,29 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed templates/*
|
|
||||||
var templatesFS embed.FS
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if err := newRootCmd().Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRootCmd() *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "authelia-gen",
|
|
||||||
Short: "Authelia's generator tooling",
|
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.AddCommand(newAllCmd(), newCodeCmd(), newDocsCmd())
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed templates/*
|
||||||
|
var templatesFS embed.FS
|
||||||
|
|
||||||
|
var (
|
||||||
|
funcMap = template.FuncMap{
|
||||||
|
"stringsContains": strings.Contains,
|
||||||
|
"join": strings.Join,
|
||||||
|
"joinX": fmJoinX,
|
||||||
|
}
|
||||||
|
|
||||||
|
tmplCodeConfigurationSchemaKeys = template.Must(newTMPL("internal_configuration_schema_keys.go"))
|
||||||
|
tmplGitHubIssueTemplateBug = template.Must(newTMPL("github_issue_template_bug_report.yml"))
|
||||||
|
tmplIssueTemplateFeature = template.Must(newTMPL("github_issue_template_feature.yml"))
|
||||||
|
tmplWebI18NIndex = template.Must(newTMPL("web_i18n_index.ts"))
|
||||||
|
tmplDotCommitLintRC = template.Must(newTMPL("dot_commitlintrc.js"))
|
||||||
|
tmplDocsCommitMessageGuidelines = template.Must(newTMPL("docs-contributing-development-commitmsg.md"))
|
||||||
|
tmplScriptsGen = template.Must(newTMPL("cmd-authelia-scripts-gen.go"))
|
||||||
|
tmplServer = template.Must(newTMPL("server_gen.go"))
|
||||||
|
)
|
||||||
|
|
||||||
|
func fmJoinX(elems []string, sep string, n int, p string) string {
|
||||||
|
buf := strings.Builder{}
|
||||||
|
|
||||||
|
c := 0
|
||||||
|
e := len(elems) - 1
|
||||||
|
|
||||||
|
for i := 0; i <= e; i++ {
|
||||||
|
if c+len(elems[i])+1 > n {
|
||||||
|
c = 0
|
||||||
|
|
||||||
|
buf.WriteString(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
c += len(elems[i]) + 1
|
||||||
|
|
||||||
|
buf.WriteString(elems[i])
|
||||||
|
|
||||||
|
if i < e {
|
||||||
|
buf.WriteString(sep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTMPL(name string) (tmpl *template.Template, err error) {
|
||||||
|
return template.New(name).Funcs(funcMap).Parse(mustLoadTmplFS(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustLoadTmplFS(tmpl string) string {
|
||||||
|
var (
|
||||||
|
content []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if content, err = templatesFS.ReadFile(fmt.Sprintf("templates/%s.tmpl", tmpl)); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(content)
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Code generated by go generate. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Run the following command to generate this file:
|
||||||
|
// go run ./cmd/authelia-gen code scripts
|
||||||
|
//
|
||||||
|
|
||||||
|
package {{ .Package }}
|
||||||
|
|
||||||
|
const (
|
||||||
|
versionSwaggerUI = "{{ .VersionSwaggerUI }}"
|
||||||
|
)
|
|
@ -0,0 +1,139 @@
|
||||||
|
---
|
||||||
|
title: "Commit Message"
|
||||||
|
description: "Authelia Development Commit Message Guidelines"
|
||||||
|
lead: "This section covers the git commit message guidelines we use for development."
|
||||||
|
date: 2021-01-30T19:29:07+11:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
contributing:
|
||||||
|
parent: "guidelines"
|
||||||
|
weight: 320
|
||||||
|
toc: true
|
||||||
|
aliases:
|
||||||
|
- /docs/contributing/commitmsg-guidelines.html
|
||||||
|
- /contributing/development/guidelines-commit-message/
|
||||||
|
---
|
||||||
|
|
||||||
|
The reasons for these conventions are as follows:
|
||||||
|
|
||||||
|
* simple navigation though git history
|
||||||
|
* easier to read git history
|
||||||
|
|
||||||
|
## Commit Message Format
|
||||||
|
|
||||||
|
Each commit message consists of a __header__, a __body__, and a __footer__.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<header>
|
||||||
|
<BLANK LINE>
|
||||||
|
<body>
|
||||||
|
<BLANK LINE>
|
||||||
|
<footer>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `header` is mandatory and must conform to the [Commit Message Header](#commit-message-header) format. The header
|
||||||
|
cannot be longer than 72 characters.
|
||||||
|
|
||||||
|
The `body` is mandatory for all commits except for those of type "docs". When the body is present it must be at least 20
|
||||||
|
characters long and must conform to the [Commit Message Body](#commit-message-body) format.
|
||||||
|
|
||||||
|
The `footer` is optional. The [Commit Message Footer](#commit-message-footer) format describes what the footer is used
|
||||||
|
for, and the structure it must have.
|
||||||
|
|
||||||
|
### Commit Message Header
|
||||||
|
|
||||||
|
```text
|
||||||
|
<type>(<scope>): <summary>
|
||||||
|
│ │ │
|
||||||
|
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||||
|
│ │
|
||||||
|
│ └─⫸ Commit Scope: {{ joinX .Scopes.All "|" 70 "\n │ " }}
|
||||||
|
│
|
||||||
|
└─⫸ Commit Type: {{ join .Types.List "|" }}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||||
|
|
||||||
|
#### Allowed type values:
|
||||||
|
{{ range .Types.Details }}
|
||||||
|
* __{{ .Name }}__ {{ .Description }}
|
||||||
|
{{- if .Scopes }}
|
||||||
|
(example scopes: {{ join .Scopes ", " }})
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
#### Allowed scope values:
|
||||||
|
|
||||||
|
The scope should be the name of the package affected (as perceived by the person reading the changelog generated from
|
||||||
|
commit messages).
|
||||||
|
{{ range .Scopes.Packages }}
|
||||||
|
* {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
There are currently a few exceptions to the "use package name" rule:
|
||||||
|
{{ range .Scopes.Extra }}
|
||||||
|
* `{{ .Name }}`: {{ .Description }}
|
||||||
|
{{- end }}
|
||||||
|
* none/empty string: useful for `test`, `refactor` and changes that are done across multiple packages
|
||||||
|
(e.g. `test: add missing unit tests`) and for docs changes that are not related to a specific package
|
||||||
|
(e.g. `docs: fix typo in tutorial`).
|
||||||
|
|
||||||
|
#### Summary
|
||||||
|
|
||||||
|
Use the summary field to provide a succinct description of the change:
|
||||||
|
|
||||||
|
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||||
|
* don't capitalize the first letter
|
||||||
|
* no dot (.) at the end
|
||||||
|
|
||||||
|
### Commit Message Body
|
||||||
|
|
||||||
|
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||||
|
|
||||||
|
Explain the motivation for the change in the commit message body. This commit message should explain *why* you are
|
||||||
|
making the change. You can include a comparison of the previous behavior with the new behavior in order to illustrate
|
||||||
|
the impact of the change.
|
||||||
|
|
||||||
|
### Commit Message Footer
|
||||||
|
|
||||||
|
The footer can contain information about breaking changes and is also the place to reference GitHub issues and other PRs
|
||||||
|
that this commit closes or is related to.
|
||||||
|
|
||||||
|
```text
|
||||||
|
BREAKING CHANGE: <breaking change summary>
|
||||||
|
<BLANK LINE>
|
||||||
|
<breaking change description + migration instructions>
|
||||||
|
<BLANK LINE>
|
||||||
|
<BLANK LINE>
|
||||||
|
Fixes #<issue number>
|
||||||
|
```
|
||||||
|
|
||||||
|
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a
|
||||||
|
blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||||
|
|
||||||
|
### Revert Commits
|
||||||
|
|
||||||
|
If the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit.
|
||||||
|
|
||||||
|
The content of the commit message body should contain:
|
||||||
|
|
||||||
|
* information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
||||||
|
* a clear description of the reason for reverting the commit message.
|
||||||
|
|
||||||
|
## Commit Message Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fix(logging): disabled colored logging outputs when file is specified
|
||||||
|
|
||||||
|
In some scenarios if a user has a log_file_path specified and a TTY seems to be detected this causes terminal coloring outputs to be written to the file.
|
||||||
|
This in turn will cause issues when attempting to utilise the log with the provided fail2ban regexes.
|
||||||
|
|
||||||
|
We now override any TTY detection/logging treatments and disable coloring/removal of the timestamp when a user is utilising the text based logger to a file.
|
||||||
|
|
||||||
|
Fixes #1480.
|
||||||
|
```
|
||||||
|
|
||||||
|
This document is based on [AngularJS Git Commit Message Format].
|
||||||
|
|
||||||
|
[AngularJS Git Commit Message Format]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
|
@ -0,0 +1,25 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: ["@commitlint/config-conventional"],
|
||||||
|
rules: {
|
||||||
|
"body-max-line-length": [2, "always", "Infinity"],
|
||||||
|
"body-min-length": [2, "always", 20],
|
||||||
|
"header-case": [2, "always", "lower-case"],
|
||||||
|
"header-max-length": [2, "always", 72],
|
||||||
|
"type-enum": [
|
||||||
|
2,
|
||||||
|
"always",
|
||||||
|
["{{ join .Types.List "\", \"" }}"],
|
||||||
|
],
|
||||||
|
"scope-enum": [
|
||||||
|
2,
|
||||||
|
"always",
|
||||||
|
[
|
||||||
|
{{- range .Scopes.All }}
|
||||||
|
"{{ . }}",
|
||||||
|
{{- end }}
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
defaultIgnores: true,
|
||||||
|
helpUrl: "https://www.authelia.com/contributing/guidelines/commit-message/",
|
||||||
|
};
|
|
@ -0,0 +1,109 @@
|
||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
description: Report a bug
|
||||||
|
labels:
|
||||||
|
{{- range .Labels }}
|
||||||
|
- {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report. If you are unsure if this is actually a bug we generally recommend creating a [Question and Answer Discussion](https://github.com/authelia/authelia/discussions/new?category=q-a) first.
|
||||||
|
|
||||||
|
Please review the following requirements before submitting this issue type:
|
||||||
|
|
||||||
|
1. Please ensure you do not report security vulnerabilities via this method. See our [Security Policy](https://www.authelia.com/security-policy).
|
||||||
|
2. Please try to give as much information as possible for us to be able to reproduce the issue and provide a quick fix.
|
||||||
|
3. Please ensure an issue does not already exist for this potential bug.
|
||||||
|
4. Please only provide specific versions. Latest is not a version.
|
||||||
|
5. Please read the [Troubleshooting Sanitization](https://www.authelia.com/r/sanitize) reference guide if you plan on removing or adjusting any values for the logs or configuration files.
|
||||||
|
6. Please consider including a [HTTP Archive File](https://www.authelia.com/r/har) if you're having redirection issues.
|
||||||
|
- type: dropdown
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
description: What version(s) of Authelia can you reproduce this bug on?
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
{{- range .Versions }}
|
||||||
|
- {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: deployment
|
||||||
|
attributes:
|
||||||
|
label: Deployment Method
|
||||||
|
description: How are you deploying Authelia?
|
||||||
|
options:
|
||||||
|
- Docker
|
||||||
|
- Kubernetes
|
||||||
|
- Bare-metal
|
||||||
|
- Other
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: proxy
|
||||||
|
attributes:
|
||||||
|
label: Reverse Proxy
|
||||||
|
description: What reverse proxy are you using?
|
||||||
|
options:
|
||||||
|
{{- range .Proxies }}
|
||||||
|
- {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: proxy-version
|
||||||
|
attributes:
|
||||||
|
label: Reverse Proxy Version
|
||||||
|
description: What is the version of your reverse proxy?
|
||||||
|
placeholder: x.x.x
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Describe the bug
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Reproduction
|
||||||
|
description: Describe how we can reproduce this issue
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expectations
|
||||||
|
attributes:
|
||||||
|
label: Expectations
|
||||||
|
description: Describe the desired or expected results
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Logs
|
||||||
|
description: Provide the logs (the template will automatically put this content in a code block)
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: configuration
|
||||||
|
attributes:
|
||||||
|
label: Configuration
|
||||||
|
description: Provide the Authelia configuration file (the template will automatically put this content in a code block)
|
||||||
|
render: yaml
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: documentation
|
||||||
|
attributes:
|
||||||
|
label: Documentation
|
||||||
|
description: Provide any relevant specification or other documentation if applicable
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
...
|
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
description: Submit a Feature Request
|
||||||
|
labels:
|
||||||
|
{{- range .Labels }}
|
||||||
|
- {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this feature request. A feature request is created as issue for the purpose of tracking the design and implementation of a feature.
|
||||||
|
|
||||||
|
Please review the following requirements before submitting this issue type:
|
||||||
|
|
||||||
|
1. Ensure there are no other similar feature requests.
|
||||||
|
2. Make sure you've checked the [Documentation](https://www.authelia.com) doesn't clearly document the features existence already.
|
||||||
|
3. Consider creating an [Idea Discussion](https://github.com/authelia/authelia/discussions/new?category=ideas) which can be voted on instead if one doesn't exist.
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Describe the feature
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: use-case
|
||||||
|
attributes:
|
||||||
|
label: Use Case
|
||||||
|
description: Provide a use case
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: details
|
||||||
|
attributes:
|
||||||
|
label: Details
|
||||||
|
description: Describe the feature in detail
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: documentation
|
||||||
|
attributes:
|
||||||
|
label: Documentation
|
||||||
|
description: Provide any relevant specification or other documentation if applicable
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
...
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Code generated by go generate. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Run the following command to generate this file:
|
||||||
|
// go run ./cmd/authelia-gen code server
|
||||||
|
//
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
const (
|
||||||
|
placeholderCSPNonce = "{{ .PlaceholderNONCE }}"
|
||||||
|
tmplCSPDefault = "{{ .TemplateDefault }}"
|
||||||
|
tmplCSPDevelopment = "{{ .TemplateDevelopment }}"
|
||||||
|
)
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Code generated by go generate. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Run the following command to generate this file:
|
||||||
|
// go run ./cmd/authelia-gen locales
|
||||||
|
//
|
||||||
|
|
||||||
|
import i18n from "i18next";
|
||||||
|
import LanguageDetector from "i18next-browser-languagedetector";
|
||||||
|
import Backend from "i18next-http-backend";
|
||||||
|
import { initReactI18next } from "react-i18next";
|
||||||
|
|
||||||
|
import LocalStorageCustomDetector from "@i18n/detectors/localStorageCustom";
|
||||||
|
import { getBasePath } from "@utils/BasePath";
|
||||||
|
|
||||||
|
const basePath = getBasePath();
|
||||||
|
|
||||||
|
const CustomLanguageDetector = new LanguageDetector();
|
||||||
|
|
||||||
|
CustomLanguageDetector.addDetector(LocalStorageCustomDetector);
|
||||||
|
|
||||||
|
i18n.use(Backend)
|
||||||
|
.use(CustomLanguageDetector)
|
||||||
|
.use(initReactI18next)
|
||||||
|
.init({
|
||||||
|
detection: {
|
||||||
|
order: ["querystring", "localStorageCustom", "navigator"],
|
||||||
|
lookupQuerystring: "lng",
|
||||||
|
lookupLocalStorage: "lng",
|
||||||
|
},
|
||||||
|
backend: {
|
||||||
|
loadPath: basePath + "/locales/{{"{{lng}}"}}/{{"{{ns}}"}}.json",
|
||||||
|
},
|
||||||
|
load: "all",
|
||||||
|
ns: [{{ range $i, $value := .Namespaces }}{{ if eq $i 0 }}"{{ $value }}"{{ else }}, "{{ $value }}"{{ end }}{{ end }}],
|
||||||
|
defaultNS: "{{ .Defaults.Namespace }}",
|
||||||
|
fallbackLng: {
|
||||||
|
default: ["{{ .Defaults.Language.Locale }}"],
|
||||||
|
{{- range .Languages }}
|
||||||
|
{{- if and (not (eq .Locale "en")) (not (eq (len .Fallbacks) 0)) }}
|
||||||
|
{{ if stringsContains .Locale "-" }}"{{ .Locale }}"{{ else }}{{ .Locale }}{{ end }}: [{{ range $i, $value := .Fallbacks }}{{ if eq $i 0 }}"{{ $value }}"{{ else }}, "{{ $value }}"{{ end }}{{ end }}],
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
},
|
||||||
|
supportedLngs: [
|
||||||
|
{{- range $i, $value := .Languages }}
|
||||||
|
"{{ $value.Locale }}",
|
||||||
|
{{- end }}
|
||||||
|
],
|
||||||
|
lowerCaseLng: false,
|
||||||
|
nonExplicitSupportedLngs: true,
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false,
|
||||||
|
},
|
||||||
|
debug: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
|
@ -0,0 +1,145 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tmplIssueTemplateData struct {
|
||||||
|
Labels []string
|
||||||
|
Versions []string
|
||||||
|
Proxies []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type tmplConfigurationKeysData struct {
|
||||||
|
Timestamp time.Time
|
||||||
|
Keys []string
|
||||||
|
Package string
|
||||||
|
}
|
||||||
|
|
||||||
|
type tmplScriptsGEnData struct {
|
||||||
|
Package string
|
||||||
|
VersionSwaggerUI string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitHubTagsJSON represents the JSON struct for the GitHub Tags API.
|
||||||
|
type GitHubTagsJSON struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DocsDataMisc represents the docs misc data schema.
|
||||||
|
type DocsDataMisc struct {
|
||||||
|
CSP TemplateCSP `json:"csp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateCSP represents the CSP template vars.
|
||||||
|
type TemplateCSP struct {
|
||||||
|
TemplateDefault string `json:"default"`
|
||||||
|
TemplateDevelopment string `json:"development"`
|
||||||
|
PlaceholderNONCE string `json:"nonce"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigurationKey is the docs json model for the Authelia configuration keys.
|
||||||
|
type ConfigurationKey struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Secret bool `json:"secret"`
|
||||||
|
Env string `json:"env"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Languages is the docs json model for the Authelia languages configuration.
|
||||||
|
type Languages struct {
|
||||||
|
Defaults DefaultsLanguages `json:"defaults"`
|
||||||
|
Namespaces []string `json:"namespaces"`
|
||||||
|
Languages []Language `json:"languages"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefaultsLanguages struct {
|
||||||
|
Language Language `json:"language"`
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Language is the docs json model for a language.
|
||||||
|
type Language struct {
|
||||||
|
Display string `json:"display"`
|
||||||
|
Locale string `json:"locale"`
|
||||||
|
Namespaces []string `json:"namespaces,omitempty"`
|
||||||
|
Fallbacks []string `json:"fallbacks,omitempty"`
|
||||||
|
|
||||||
|
Tag language.Tag `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
labelAreaPrefixPriority = "priority"
|
||||||
|
labelAreaPrefixType = "type"
|
||||||
|
labelAreaPrefixStatus = "status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type labelPriority int
|
||||||
|
|
||||||
|
//nolint:deadcode // Kept for future use.
|
||||||
|
const (
|
||||||
|
labelPriorityCritical labelPriority = iota
|
||||||
|
labelPriorityHigh
|
||||||
|
labelPriorityMedium
|
||||||
|
labelPriorityNormal
|
||||||
|
labelPriorityLow
|
||||||
|
)
|
||||||
|
|
||||||
|
var labelPriorityDescriptions = [...]string{
|
||||||
|
"Critical",
|
||||||
|
"High",
|
||||||
|
"Medium",
|
||||||
|
"Normal",
|
||||||
|
"Low",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p labelPriority) String() string {
|
||||||
|
return fmt.Sprintf("%s/%d/%s", labelAreaPrefixPriority, p+1, strings.ToLower(labelPriorityDescriptions[p]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p labelPriority) Description() string {
|
||||||
|
return labelPriorityDescriptions[p]
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelStatus int
|
||||||
|
|
||||||
|
const (
|
||||||
|
labelStatusNeedsDesign labelStatus = iota
|
||||||
|
labelStatusNeedsTriage
|
||||||
|
)
|
||||||
|
|
||||||
|
var labelStatusDescriptions = [...]string{
|
||||||
|
"needs-design",
|
||||||
|
"needs-triage",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s labelStatus) String() string {
|
||||||
|
return fmt.Sprintf("%s/%s", labelAreaPrefixStatus, labelStatusDescriptions[s])
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelType int
|
||||||
|
|
||||||
|
//nolint:deadcode // Kept for future use.
|
||||||
|
const (
|
||||||
|
labelTypeFeature labelType = iota
|
||||||
|
labelTypeBugUnconfirmed
|
||||||
|
labelTypeBug
|
||||||
|
)
|
||||||
|
|
||||||
|
var labelTypeDescriptions = [...]string{
|
||||||
|
"feature",
|
||||||
|
"bug/unconfirmed",
|
||||||
|
"bug",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t labelType) String() string {
|
||||||
|
return fmt.Sprintf("%s/%s", labelAreaPrefixType, labelTypeDescriptions[t])
|
||||||
|
}
|
||||||
|
|
||||||
|
type CSPValue struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
}
|
|
@ -168,8 +168,8 @@ func pnpmInstall() {
|
||||||
shell(fmt.Sprintf("cd %s/web && pnpm install", cwd))
|
shell(fmt.Sprintf("cd %s/web && pnpm install", cwd))
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootstrapPrintln(args ...interface{}) {
|
func bootstrapPrintln(args ...any) {
|
||||||
a := make([]interface{}, 0)
|
a := make([]any, 0)
|
||||||
a = append(a, "[BOOTSTRAP]")
|
a = append(a, "[BOOTSTRAP]")
|
||||||
a = append(a, args...)
|
a = append(a, args...)
|
||||||
fmt.Println(a...)
|
fmt.Println(a...)
|
||||||
|
|
|
@ -40,7 +40,7 @@ func cmdBuildRun(cobraCmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
cmdCleanRun(cobraCmd, args)
|
cmdCleanRun(cobraCmd, args)
|
||||||
|
|
||||||
xflags, err := getXFlags(branch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
buildMetaData, err := getBuild(branch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,11 @@ func cmdBuildRun(cobraCmd *cobra.Command, args []string) {
|
||||||
if buildkite {
|
if buildkite {
|
||||||
log.Info("Building Authelia Go binaries with gox...")
|
log.Info("Building Authelia Go binaries with gox...")
|
||||||
|
|
||||||
buildAutheliaBinaryGOX(xflags)
|
buildAutheliaBinaryGOX(buildMetaData.XFlags())
|
||||||
} else {
|
} else {
|
||||||
log.Info("Building Authelia Go binary...")
|
log.Info("Building Authelia Go binary...")
|
||||||
|
|
||||||
buildAutheliaBinaryGO(xflags)
|
buildAutheliaBinaryGO(buildMetaData.XFlags())
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanAssets()
|
cleanAssets()
|
||||||
|
@ -146,8 +146,7 @@ func buildFrontend(branch string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildSwagger() {
|
func buildSwagger() {
|
||||||
swaggerVer := "4.13.0"
|
cmd := utils.CommandWithStdout("bash", "-c", "wget -q https://github.com/swagger-api/swagger-ui/archive/v"+versionSwaggerUI+".tar.gz -O ./v"+versionSwaggerUI+".tar.gz")
|
||||||
cmd := utils.CommandWithStdout("bash", "-c", "wget -q https://github.com/swagger-api/swagger-ui/archive/v"+swaggerVer+".tar.gz -O ./v"+swaggerVer+".tar.gz")
|
|
||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -161,14 +160,14 @@ func buildSwagger() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = utils.CommandWithStdout("tar", "-C", "internal/server/public_html/api", "--exclude=index.html", "--strip-components=2", "-xf", "v"+swaggerVer+".tar.gz", "swagger-ui-"+swaggerVer+"/dist")
|
cmd = utils.CommandWithStdout("tar", "-C", "internal/server/public_html/api", "--exclude=index.html", "--strip-components=2", "-xf", "v"+versionSwaggerUI+".tar.gz", "swagger-ui-"+versionSwaggerUI+"/dist")
|
||||||
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = utils.CommandWithStdout("rm", "./v"+swaggerVer+".tar.gz")
|
cmd = utils.CommandWithStdout("rm", "./v"+versionSwaggerUI+".tar.gz")
|
||||||
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -13,15 +13,17 @@ import (
|
||||||
|
|
||||||
var container string
|
var container string
|
||||||
|
|
||||||
var containers = []string{"dev", "coverage"}
|
var (
|
||||||
var defaultContainer = "dev"
|
containers = []string{"dev", "coverage"}
|
||||||
var ciBranch = os.Getenv("BUILDKITE_BRANCH")
|
defaultContainer = "dev"
|
||||||
var ciPullRequest = os.Getenv("BUILDKITE_PULL_REQUEST")
|
ciBranch = os.Getenv("BUILDKITE_BRANCH")
|
||||||
var ciTag = os.Getenv("BUILDKITE_TAG")
|
ciPullRequest = os.Getenv("BUILDKITE_PULL_REQUEST")
|
||||||
var dockerTags = regexp.MustCompile(`v(?P<Patch>(?P<Minor>(?P<Major>\d+)\.\d+)\.\d+.*)`)
|
ciTag = os.Getenv("BUILDKITE_TAG")
|
||||||
var ignoredSuffixes = regexp.MustCompile("alpha|beta")
|
dockerTags = regexp.MustCompile(`v(?P<Patch>(?P<Minor>(?P<Major>\d+)\.\d+)\.\d+.*)`)
|
||||||
var publicRepo = regexp.MustCompile(`.*:.*`)
|
ignoredSuffixes = regexp.MustCompile("alpha|beta")
|
||||||
var tags = dockerTags.FindStringSubmatch(ciTag)
|
publicRepo = regexp.MustCompile(`.*:.*`)
|
||||||
|
tags = dockerTags.FindStringSubmatch(ciTag)
|
||||||
|
)
|
||||||
|
|
||||||
func newDockerCmd() (cmd *cobra.Command) {
|
func newDockerCmd() (cmd *cobra.Command) {
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
|
@ -98,15 +100,14 @@ func cmdDockerPushManifestRun(_ *cobra.Command, _ []string) {
|
||||||
log.Infof("Detected tags: '%s' | '%s' | '%s'", tags[1], tags[2], tags[3])
|
log.Infof("Detected tags: '%s' | '%s' | '%s'", tags[1], tags[2], tags[3])
|
||||||
login(docker, dockerhub)
|
login(docker, dockerhub)
|
||||||
login(docker, ghcr)
|
login(docker, ghcr)
|
||||||
deployManifest(docker, tags[1])
|
|
||||||
publishDockerReadme(docker)
|
|
||||||
|
|
||||||
if !ignoredSuffixes.MatchString(ciTag) {
|
if ignoredSuffixes.MatchString(ciTag) {
|
||||||
deployManifest(docker, tags[2])
|
deployManifest(docker, tags[1])
|
||||||
deployManifest(docker, tags[3])
|
} else {
|
||||||
deployManifest(docker, "latest")
|
deployManifest(docker, tags[1], tags[2], tags[3], "latest")
|
||||||
publishDockerReadme(docker)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishDockerReadme(docker)
|
||||||
} else {
|
} else {
|
||||||
log.Fatal("Docker manifest will not be published, the specified tag does not conform to the standard")
|
log.Fatal("Docker manifest will not be published, the specified tag does not conform to the standard")
|
||||||
}
|
}
|
||||||
|
@ -143,13 +144,12 @@ func dockerBuildOfficialImage(arch string) error {
|
||||||
filename := "Dockerfile"
|
filename := "Dockerfile"
|
||||||
dockerfile := fmt.Sprintf("%s.%s", filename, arch)
|
dockerfile := fmt.Sprintf("%s.%s", filename, arch)
|
||||||
|
|
||||||
flags, err := getXFlags(ciBranch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
buildMetaData, err := getBuild(ciBranch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return docker.Build(IntermediateDockerImageName, dockerfile, ".",
|
return docker.Build(IntermediateDockerImageName, dockerfile, ".", buildMetaData)
|
||||||
strings.Join(flags, " "))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func login(docker *Docker, registry string) {
|
func login(docker *Docker, registry string) {
|
||||||
|
@ -181,13 +181,17 @@ func login(docker *Docker, registry string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deployManifest(docker *Docker, tag string) {
|
func deployManifest(docker *Docker, tag ...string) {
|
||||||
log.Infof("Docker manifest %s:%s will be deployed on %s and %s", DockerImageName, tag, dockerhub, ghcr)
|
tags = make([]string, 0)
|
||||||
|
|
||||||
dockerhub := dockerhub + "/" + DockerImageName + ":" + tag
|
log.Infof("The following Docker manifest(s) will be deployed on %s and %s", dockerhub, ghcr)
|
||||||
ghcr := ghcr + "/" + DockerImageName + ":" + tag
|
|
||||||
|
|
||||||
if err := docker.Manifest(dockerhub, ghcr); err != nil {
|
for _, t := range tag {
|
||||||
|
log.Infof("- %s:%s", DockerImageName, t)
|
||||||
|
tags = append(tags, dockerhub+"/"+DockerImageName+":"+t, ghcr+"/"+DockerImageName+":"+t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := docker.Manifest(tags); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Code generated by go generate. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Run the following command to generate this file:
|
||||||
|
// go run ./cmd/authelia-gen code scripts
|
||||||
|
//
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
const (
|
||||||
|
versionSwaggerUI = "4.15.2"
|
||||||
|
)
|
|
@ -2,66 +2,63 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getXFlags(branch, build, extra string) (flags []string, err error) {
|
func getBuild(branch, buildNumber, extra string) (b *Build, err error) {
|
||||||
if branch == "" {
|
var out string
|
||||||
out, _, err := utils.RunCommandAndReturnOutput("git rev-parse --abbrev-ref HEAD")
|
|
||||||
if err != nil {
|
b = &Build{
|
||||||
return flags, fmt.Errorf("error getting branch with git rev-parse: %w", err)
|
Branch: branch,
|
||||||
|
Extra: extra,
|
||||||
|
}
|
||||||
|
|
||||||
|
if buildNumber != "" {
|
||||||
|
if b.Number, err = strconv.Atoi(buildNumber); err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing provided build number: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Branch == "" {
|
||||||
|
if out, _, err = utils.RunCommandAndReturnOutput("git rev-parse --abbrev-ref HEAD"); err != nil {
|
||||||
|
return nil, fmt.Errorf("error getting branch with git rev-parse: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if out == "" {
|
if out == "" {
|
||||||
branch = "master"
|
b.Branch = "master"
|
||||||
} else {
|
} else {
|
||||||
branch = out
|
b.Branch = out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gitTagCommit, _, err := utils.RunCommandAndReturnOutput("git rev-list --tags --max-count=1")
|
var (
|
||||||
if err != nil {
|
gitTagCommit string
|
||||||
return flags, fmt.Errorf("error getting tag commit with git rev-list: %w", err)
|
)
|
||||||
|
|
||||||
|
if gitTagCommit, _, err = utils.RunCommandAndReturnOutput("git rev-list --tags --max-count=1"); err != nil {
|
||||||
|
return nil, fmt.Errorf("error getting tag commit with git rev-list: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tag, _, err := utils.RunCommandAndReturnOutput(fmt.Sprintf("git describe --tags --abbrev=0 %s", gitTagCommit))
|
if b.Tag, _, err = utils.RunCommandAndReturnOutput(fmt.Sprintf("git describe --tags --abbrev=0 %s", gitTagCommit)); err != nil {
|
||||||
if err != nil {
|
return nil, fmt.Errorf("error getting tag with git describe: %w", err)
|
||||||
return flags, fmt.Errorf("error getting tag with git describe: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
commit, _, err := utils.RunCommandAndReturnOutput("git rev-parse HEAD")
|
if b.Commit, _, err = utils.RunCommandAndReturnOutput("git rev-parse HEAD"); err != nil {
|
||||||
if err != nil {
|
return nil, fmt.Errorf("error getting commit with git rev-parse: %w", err)
|
||||||
return flags, fmt.Errorf("error getting commit with git rev-parse: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var states []string
|
if gitTagCommit == b.Commit {
|
||||||
|
b.Tagged = true
|
||||||
if gitTagCommit == commit {
|
|
||||||
states = append(states, "tagged")
|
|
||||||
} else {
|
|
||||||
states = append(states, "untagged")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exitCode, _ := utils.RunCommandAndReturnOutput("git diff --quiet"); exitCode != 0 {
|
if _, exitCode, _ := utils.RunCommandAndReturnOutput("git diff --quiet"); exitCode == 0 {
|
||||||
states = append(states, "dirty")
|
b.Clean = true
|
||||||
} else {
|
|
||||||
states = append(states, "clean")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if build == "" {
|
b.Date = time.Now()
|
||||||
build = "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
return []string{
|
return b, nil
|
||||||
fmt.Sprintf(fmtLDFLAGSX, "BuildBranch", branch),
|
|
||||||
fmt.Sprintf(fmtLDFLAGSX, "BuildTag", tag),
|
|
||||||
fmt.Sprintf(fmtLDFLAGSX, "BuildCommit", commit),
|
|
||||||
fmt.Sprintf(fmtLDFLAGSX, "BuildDate", time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700")),
|
|
||||||
fmt.Sprintf(fmtLDFLAGSX, "BuildState", strings.Join(states, " ")),
|
|
||||||
fmt.Sprintf(fmtLDFLAGSX, "BuildExtra", extra),
|
|
||||||
fmt.Sprintf(fmtLDFLAGSX, "BuildNumber", build),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -8,11 +15,20 @@ import (
|
||||||
type Docker struct{}
|
type Docker struct{}
|
||||||
|
|
||||||
// Build build a docker image.
|
// Build build a docker image.
|
||||||
func (d *Docker) Build(tag, dockerfile, target, ldflags string) error {
|
func (d *Docker) Build(tag, dockerfile, target string, buildMetaData *Build) error {
|
||||||
return utils.CommandWithStdout(
|
args := []string{"build", "-t", tag, "-f", dockerfile, "--progress=plain"}
|
||||||
"docker", "build", "-t", tag, "-f", dockerfile,
|
|
||||||
"--progress=plain", "--build-arg", "LDFLAGS_EXTRA="+ldflags,
|
for label, value := range buildMetaData.ContainerLabels() {
|
||||||
target).Run()
|
if value == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, "--label", fmt.Sprintf("%s=%s", label, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, "--build-arg", "LDFLAGS_EXTRA="+strings.Join(buildMetaData.XFlags(), " "), target)
|
||||||
|
|
||||||
|
return utils.CommandWithStdout("docker", args...).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag tag a docker image.
|
// Tag tag a docker image.
|
||||||
|
@ -26,11 +42,107 @@ func (d *Docker) Login(username, password, registry string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifest push a docker manifest to dockerhub.
|
// Manifest push a docker manifest to dockerhub.
|
||||||
func (d *Docker) Manifest(tag1, tag2 string) error {
|
func (d *Docker) Manifest(tags []string) error {
|
||||||
return utils.CommandWithStdout("docker", "build", "-t", tag1, "-t", tag2, "--platform", "linux/amd64,linux/arm/v7,linux/arm64", "--builder", "buildx", "--push", ".").Run()
|
args := []string{"build"}
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
args = append(args, "-t", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations := ""
|
||||||
|
|
||||||
|
buildMetaData, err := getBuild(ciBranch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for label, value := range buildMetaData.ContainerLabels() {
|
||||||
|
if value == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations += fmt.Sprintf("annotation.%s=%s,", label, value)
|
||||||
|
args = append(args, "--label", fmt.Sprintf("%s=%s", label, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseImageTag string
|
||||||
|
|
||||||
|
from, err := getDockerfileDirective("Dockerfile", "FROM")
|
||||||
|
if err == nil {
|
||||||
|
baseImageTag = from[strings.IndexRune(from, ':')+1:]
|
||||||
|
args = append(args, "--label", "org.opencontainers.image.base.name=docker.io/library/alpine:"+baseImageTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.Get("https://hub.docker.com/v2/repositories/library/alpine/tags/" + baseImageTag + "/images")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
images := DockerImages{}
|
||||||
|
|
||||||
|
if err = json.NewDecoder(resp.Body).Decode(&images); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
digestAMD64, digestARM, digestARM64 string
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, platform := range []string{"linux/amd64", "linux/arm/v7", "linux/arm64"} {
|
||||||
|
for _, image := range images {
|
||||||
|
if !image.Match(platform) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch platform {
|
||||||
|
case "linux/amd64":
|
||||||
|
digestAMD64 = image.Digest
|
||||||
|
case "linux/arm/v7":
|
||||||
|
digestARM = image.Digest
|
||||||
|
case "linux/arm64":
|
||||||
|
digestARM64 = image.Digest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalArgs := make([]string, len(args))
|
||||||
|
|
||||||
|
copy(finalArgs, args)
|
||||||
|
|
||||||
|
finalArgs = append(finalArgs, "--output", "type=image,\"name="+dockerhub+"/"+DockerImageName+","+ghcr+"/"+DockerImageName+"\","+annotations+"annotation.org.opencontainers.image.base.name=docker.io/library/alpine:"+baseImageTag+",annotation[linux/amd64].org.opencontainers.image.base.digest="+digestAMD64+",annotation[linux/arm/v7].org.opencontainers.image.base.digest="+digestARM+",annotation[linux/arm64].org.opencontainers.image.base.digest="+digestARM64, "--platform", "linux/amd64,linux/arm/v7,linux/arm64", "--builder", "buildx", "--push", ".")
|
||||||
|
|
||||||
|
if err = utils.CommandWithStdout("docker", finalArgs...).Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublishReadme push README.md to dockerhub.
|
// PublishReadme push README.md to dockerhub.
|
||||||
func (d *Docker) PublishReadme() error {
|
func (d *Docker) PublishReadme() error {
|
||||||
return utils.CommandWithStdout("bash", "-c", `token=$(curl -fs --retry 3 -H "Content-Type: application/json" -X "POST" -d '{"username": "'$DOCKER_USERNAME'", "password": "'$DOCKER_PASSWORD'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) && jq -n --arg msg "$(cat README.md | sed -r 's/(\<img\ src\=\")(\.\/)/\1https:\/\/github.com\/authelia\/authelia\/raw\/master\//' | sed 's/\.\//https:\/\/github.com\/authelia\/authelia\/blob\/master\//g' | sed '/start \[contributing\]/ a <a href="https://github.com/authelia/authelia/graphs/contributors"><img src="https://opencollective.com/authelia-sponsors/contributors.svg?width=890" /></a>' | sed '/Thanks goes to/,/### Backers/{/### Backers/!d}')" '{"registry":"registry-1.docker.io","full_description": $msg }' | curl -fs --retry 3 -o /dev/null -L -X "PATCH" -H "Content-Type: application/json" -H "Authorization: JWT $token" -d @- https://hub.docker.com/v2/repositories/authelia/authelia/`).Run()
|
return utils.CommandWithStdout("bash", "-c", `token=$(curl -fs --retry 3 -H "Content-Type: application/json" -X "POST" -d '{"username": "'$DOCKER_USERNAME'", "password": "'$DOCKER_PASSWORD'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) && jq -n --arg msg "$(cat README.md | sed -r 's/(\<img\ src\=\")(\.\/)/\1https:\/\/github.com\/authelia\/authelia\/raw\/master\//' | sed 's/\.\//https:\/\/github.com\/authelia\/authelia\/blob\/master\//g' | sed '/start \[contributing\]/ a <a href="https://github.com/authelia/authelia/graphs/contributors"><img src="https://opencollective.com/authelia-sponsors/contributors.svg?width=890" /></a>' | sed '/Thanks goes to/,/### Backers/{/### Backers/!d}')" '{"registry":"registry-1.docker.io","full_description": $msg }' | curl -fs --retry 3 -o /dev/null -L -X "PATCH" -H "Content-Type: application/json" -H "Authorization: JWT $token" -d @- https://hub.docker.com/v2/repositories/authelia/authelia/`).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDockerfileDirective(filePath, directive string) (from string, err error) {
|
||||||
|
var f *os.File
|
||||||
|
|
||||||
|
if f, err = os.Open(filePath); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
s := bufio.NewScanner(f)
|
||||||
|
|
||||||
|
for s.Scan() {
|
||||||
|
data := s.Text()
|
||||||
|
|
||||||
|
if strings.HasPrefix(data, directive+" ") {
|
||||||
|
return data[5:], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,130 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
// HostEntry represents an entry in /etc/hosts.
|
// HostEntry represents an entry in /etc/hosts.
|
||||||
type HostEntry struct {
|
type HostEntry struct {
|
||||||
Domain string
|
Domain string
|
||||||
IP string
|
IP string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DockerImages represents some of the data from the docker images API.
|
||||||
|
type DockerImages []DockerImage
|
||||||
|
|
||||||
|
// DockerImage represents some of the data from the docker images API.
|
||||||
|
type DockerImage struct {
|
||||||
|
Architecture string `json:"architecture"`
|
||||||
|
Variant any `json:"variant"`
|
||||||
|
Digest string `json:"digest"`
|
||||||
|
OS string `json:"os"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match returns true if this image matches the platform.
|
||||||
|
func (d DockerImage) Match(platform string) bool {
|
||||||
|
parts := []string{d.OS, d.Architecture}
|
||||||
|
|
||||||
|
if strings.Join(parts, "/") == platform {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Variant == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
parts = append(parts, d.Variant.(string))
|
||||||
|
|
||||||
|
return strings.Join(parts, "/") == platform
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build represents a builds metadata.
|
||||||
|
type Build struct {
|
||||||
|
Branch string
|
||||||
|
Tag string
|
||||||
|
Commit string
|
||||||
|
Tagged bool
|
||||||
|
Clean bool
|
||||||
|
Extra string
|
||||||
|
Number int
|
||||||
|
Date time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// States returns the state tags for this Build.
|
||||||
|
func (b Build) States() []string {
|
||||||
|
var states []string
|
||||||
|
|
||||||
|
if b.Tagged {
|
||||||
|
states = append(states, "tagged")
|
||||||
|
} else {
|
||||||
|
states = append(states, "untagged")
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Clean {
|
||||||
|
states = append(states, "clean")
|
||||||
|
} else {
|
||||||
|
states = append(states, "dirty")
|
||||||
|
}
|
||||||
|
|
||||||
|
return states
|
||||||
|
}
|
||||||
|
|
||||||
|
// State returns the state tags string for this Build.
|
||||||
|
func (b Build) State() string {
|
||||||
|
return strings.Join(b.States(), " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// XFlags returns the XFlags for this Build.
|
||||||
|
func (b Build) XFlags() []string {
|
||||||
|
return []string{
|
||||||
|
fmt.Sprintf(fmtLDFLAGSX, "BuildBranch", b.Branch),
|
||||||
|
fmt.Sprintf(fmtLDFLAGSX, "BuildTag", b.Tag),
|
||||||
|
fmt.Sprintf(fmtLDFLAGSX, "BuildCommit", b.Commit),
|
||||||
|
fmt.Sprintf(fmtLDFLAGSX, "BuildDate", b.Date.Format("Mon, 02 Jan 2006 15:04:05 -0700")),
|
||||||
|
fmt.Sprintf(fmtLDFLAGSX, "BuildState", b.State()),
|
||||||
|
fmt.Sprintf(fmtLDFLAGSX, "BuildExtra", b.Extra),
|
||||||
|
fmt.Sprintf(fmtLDFLAGSX, "BuildNumber", strconv.Itoa(b.Number)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerLabels returns the container labels for this Build.
|
||||||
|
func (b Build) ContainerLabels() (labels map[string]string) {
|
||||||
|
var version string
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case b.Clean && b.Tagged:
|
||||||
|
version = utils.VersionAdv(b.Tag, b.State(), b.Commit, b.Branch, b.Extra)
|
||||||
|
case b.Clean:
|
||||||
|
version = fmt.Sprintf("%s-pre+%s.%s", b.Tag, b.Branch, b.Commit)
|
||||||
|
case b.Tagged:
|
||||||
|
version = fmt.Sprintf("%s-dirty", b.Tag)
|
||||||
|
default:
|
||||||
|
version = fmt.Sprintf("%s-dirty+%s.%s", b.Tag, b.Branch, b.Commit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(version, "v") && len(version) > 1 {
|
||||||
|
version = version[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
labels = map[string]string{
|
||||||
|
"org.opencontainers.image.created": b.Date.Format(time.RFC3339),
|
||||||
|
"org.opencontainers.image.authors": "",
|
||||||
|
"org.opencontainers.image.url": "https://github.com/authelia/authelia/pkgs/container/authelia",
|
||||||
|
"org.opencontainers.image.documentation": "https://www.authelia.com",
|
||||||
|
"org.opencontainers.image.source": fmt.Sprintf("https://github.com/authelia/authelia/tree/%s", b.Commit),
|
||||||
|
"org.opencontainers.image.version": version,
|
||||||
|
"org.opencontainers.image.revision": b.Commit,
|
||||||
|
"org.opencontainers.image.vendor": "Authelia",
|
||||||
|
"org.opencontainers.image.licenses": "Apache-2.0",
|
||||||
|
"org.opencontainers.image.ref.name": "",
|
||||||
|
"org.opencontainers.image.title": "authelia",
|
||||||
|
"org.opencontainers.image.description": "Authelia is an open-source authentication and authorization server providing two-factor authentication and single sign-on (SSO) for your applications via a web portal.",
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
|
@ -37,10 +37,10 @@ func cmdXFlagsRun(cobraCmd *cobra.Command, _ []string) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
flags, err := getXFlags("", build, extra)
|
buildMetaData, err := getBuild("", build, extra)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(strings.Join(flags, " "))
|
fmt.Println(strings.Join(buildMetaData.XFlags(), " "))
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
10
crowdin.yml
10
crowdin.yml
|
@ -6,14 +6,4 @@ files:
|
||||||
- source: /internal/server/locales/en/*
|
- source: /internal/server/locales/en/*
|
||||||
translation: /internal/server/locales/%locale%/%original_file_name%
|
translation: /internal/server/locales/%locale%/%original_file_name%
|
||||||
skip_untranslated_files: true
|
skip_untranslated_files: true
|
||||||
languages_mapping:
|
|
||||||
locale:
|
|
||||||
"de-DE": de
|
|
||||||
"en-EN": en
|
|
||||||
"es-ES": es
|
|
||||||
"fr-FR": fr
|
|
||||||
"nl-NL": nl
|
|
||||||
"pt-PT": pt
|
|
||||||
"ru-RU": ru
|
|
||||||
"zh-CH": zh
|
|
||||||
...
|
...
|
||||||
|
|
|
@ -48,18 +48,18 @@
|
||||||
weight = 10
|
weight = 10
|
||||||
|
|
||||||
[[footer]]
|
[[footer]]
|
||||||
name = "Privacy"
|
name = "Privacy Policy"
|
||||||
url = "/information/privacy-policy"
|
url = "/policies/privacy"
|
||||||
weight = 10
|
weight = 10
|
||||||
|
|
||||||
[[footer]]
|
[[footer]]
|
||||||
name = "Code of Conduct"
|
name = "Security Policy"
|
||||||
url = "/information/code-of-conduct"
|
url = "/policies/security"
|
||||||
weight = 20
|
weight = 20
|
||||||
|
|
||||||
[[footer]]
|
[[footer]]
|
||||||
name = "Security"
|
name = "Code of Conduct"
|
||||||
url = "/information/security"
|
url = "/code-of-conduct"
|
||||||
weight = 30
|
weight = 30
|
||||||
|
|
||||||
[[footer]]
|
[[footer]]
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
---
|
||||||
|
title: "4.37: Pre-Release Notes"
|
||||||
|
description: "Authelia 4.37 is just around the corner. This version has several additional features and improvements to existing features. In this blog post we'll discuss the new features and roughly what it means for users."
|
||||||
|
lead: "Pre-Release Notes for 4.37"
|
||||||
|
excerpt: "Authelia 4.37 is just around the corner. This version has several additional features and improvements to existing features. In this blog post we'll discuss the new features and roughly what it means for users."
|
||||||
|
date: 2022-09-26T06:55:09+10:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
categories: ["News", "Release Notes"]
|
||||||
|
tags: ["releases", "pre-release-notes"]
|
||||||
|
contributors: ["James Elliott"]
|
||||||
|
pinned: false
|
||||||
|
homepage: false
|
||||||
|
---
|
||||||
|
|
||||||
|
Authelia [4.37](https://github.com/authelia/authelia/milestone/16) is just around the corner. This version has several
|
||||||
|
additional features and improvements to existing features. In this blog post we'll discuss the new features and roughly
|
||||||
|
what it means for users.
|
||||||
|
|
||||||
|
_**Note:** These features are still subject to change however it represents the most likely features._
|
||||||
|
|
||||||
|
This blog entry (and technically the blog itself) is part of a new effort I'm making for which I'm not entirely sure how
|
||||||
|
useful it'll be but I'd love to hear your feedback regardless. We don't use any analytics or interactive components to
|
||||||
|
gauge the consumption or reception of the website so it is invaluable to get this feedback.
|
||||||
|
|
||||||
|
## Envoy Support
|
||||||
|
|
||||||
|
We'll be supporting [Envoy] and [Istio] in this release. Support for this proxy mostly completes our proxy support status
|
||||||
|
with all major proxies supported excluding Microsoft IIS.
|
||||||
|
|
||||||
|
[Envoy]: https://www.envoyproxy.io/
|
||||||
|
[Istio]: https://istio.io/
|
||||||
|
|
||||||
|
## OpenID Connect Improvements
|
||||||
|
|
||||||
|
Several items from the [OpenID Connect Roadmap](../../roadmap/active/openid-connect.md) are being checked off in this
|
||||||
|
release.
|
||||||
|
|
||||||
|
### Hashed Client Secrets
|
||||||
|
|
||||||
|
We'll be supporting hashed OpenID Connect client secrets in this release. People will still be able to use plaintext
|
||||||
|
secrets if they wish however we'll be recommending people utilize PBKDF2, BCrypt or SHA512 SHA2CRYPT (see
|
||||||
|
[Password Algorithms](#password-algorithms) for a full compatibility list). This doesn't change anything for OpenID
|
||||||
|
Connect Relying Parties, it only requires a change in the Authelia configuration.
|
||||||
|
|
||||||
|
### Consent Modes
|
||||||
|
|
||||||
|
Currently we support an explicit consent mode, and a pre-configured consent mode if the pre-configured duration is set.
|
||||||
|
In this release we're planning to support an implicit consent mode which will never ask users for any consent. In
|
||||||
|
addition it will make the consent mode configuration slightly more explicit.
|
||||||
|
|
||||||
|
### JWKS Certificate Chain
|
||||||
|
|
||||||
|
Currently we do not support JWKS certificates, we only support private keys. We will support advertising the Certificate
|
||||||
|
Chain via the JWKS endpoint in this release. This means when provided with a Certificate Chain will be able to
|
||||||
|
theoretically validate the level of trust associated with the JWKS.
|
||||||
|
|
||||||
|
Some applications theoretically require this, most probably don't support it at all. However the beauty of this change
|
||||||
|
is that if it's not supported by the other party they can just ignore it. We've yet to have users request this but it's
|
||||||
|
likely inevitable that someone will ask or some third party will require it at some point, so we're preemptively
|
||||||
|
implementing it.
|
||||||
|
|
||||||
|
## Container Annotations / Labels
|
||||||
|
|
||||||
|
In this release we're going to start adding the [OCI Image Format Specification]'s set of [Annotations] to all of our
|
||||||
|
images.
|
||||||
|
|
||||||
|
For the time being we will also add the [Annotations] as container labels. This is because [Annotations] are a
|
||||||
|
relatively unsupported specification at this stage. A majority of use cases for the [Annotations] either actually use
|
||||||
|
labels or fallback to labels.
|
||||||
|
|
||||||
|
[OCI Image Format Specification]: https://github.com/opencontainers/image-spec
|
||||||
|
[Annotations]: https://github.com/opencontainers/image-spec/blob/main/annotations.md
|
||||||
|
|
||||||
|
## Password Algorithms
|
||||||
|
|
||||||
|
Several new password hashing algorithms will be supported in this release. The list of supported algorithms will become:
|
||||||
|
|
||||||
|
* Argon2:
|
||||||
|
* Argon2id (previously supported)
|
||||||
|
* Argon2i
|
||||||
|
* Argon2d
|
||||||
|
* PBKDF2:
|
||||||
|
* SHA1
|
||||||
|
* SHA224
|
||||||
|
* SHA256
|
||||||
|
* SHA384
|
||||||
|
* SHA512
|
||||||
|
* SCrypt
|
||||||
|
* BCrypt
|
||||||
|
* SHA2 CRYPT:
|
||||||
|
* SHA256
|
||||||
|
* SHA512 (previously supported)
|
||||||
|
|
||||||
|
## Users YAML File Authentication Backend
|
||||||
|
|
||||||
|
In addition to the [Password Algorithms](#password-algorithms) changes we'll also be adding a few major features to the
|
||||||
|
Users YAML File Authentication Backend.
|
||||||
|
|
||||||
|
### Automatic Reload
|
||||||
|
|
||||||
|
Administrators will be able to allow automatic reload the YAML file with the users database for deployments of the YAML
|
||||||
|
File backend. This change will not extend to the main configuration file at this time.
|
||||||
|
|
||||||
|
### Email Lookup
|
||||||
|
|
||||||
|
Administrators will be able to allow users to use their email or their username to login similar to how this can be done
|
||||||
|
with an LDAP filter already, bringing feature parity to the YAML File backend.
|
||||||
|
|
||||||
|
## Mutual TLS Support
|
||||||
|
|
||||||
|
This release will add support for Mutual TLS for Redis, LDAP, and SMTP. This improves compatibility with these systems
|
||||||
|
when password authentication is not desired.
|
||||||
|
|
||||||
|
## Query Parameter Authorization Criteria
|
||||||
|
|
||||||
|
We'll be adding a very specific query parameter matcher to the access control rules in this release. It will allow
|
||||||
|
individually targeting specific query arguments and testing if they exist/don't exist, equal/don't equal a value, or if
|
||||||
|
they match/don't match a specific Regular Expression.
|
||||||
|
|
||||||
|
This rule type takes a performance hit when compared to the resources rule type, so the resources rule type is generally
|
||||||
|
encouraged. However for complex matching of query parameters a Regular Expression is hard to get exactly right. This
|
||||||
|
feature alleviates this issue.
|
||||||
|
|
||||||
|
## Compatibility Features
|
||||||
|
|
||||||
|
Compatibility Features are toggle on features which allows operation with a third party. Usually they're implemented to
|
||||||
|
allow ignoring a specific specification the third party has not implemented correctly.
|
||||||
|
|
||||||
|
We'll be adding the following compatibility features in this release:
|
||||||
|
|
||||||
|
* LDAP Servers which do not support querying the RootDSE for supported controls or extensions.
|
||||||
|
* SMTP Servers which advertise support for STARTTLS but do not actually support it.
|
|
@ -47,4 +47,4 @@ future.
|
||||||
|
|
||||||
[Hugo]: https://gohugo.io/
|
[Hugo]: https://gohugo.io/
|
||||||
[Doks]: https://getdoks.org/
|
[Doks]: https://getdoks.org/
|
||||||
[Documentation Contributing]: ../../contributing/prologue/documentation.md
|
[Documentation Contributing]: ../../contributing/prologue/documentation-contributions.md
|
||||||
|
|
|
@ -20,13 +20,36 @@ aliases:
|
||||||
authentication_backend:
|
authentication_backend:
|
||||||
file:
|
file:
|
||||||
path: /config/users.yml
|
path: /config/users.yml
|
||||||
|
watch: false
|
||||||
|
search:
|
||||||
|
email: false
|
||||||
|
case_insensitive: false
|
||||||
password:
|
password:
|
||||||
algorithm: argon2id
|
algorithm: argon2
|
||||||
iterations: 3
|
argon2:
|
||||||
key_length: 32
|
variant: argon2id
|
||||||
salt_length: 16
|
iterations: 3
|
||||||
parallelism: 4
|
memory: 65536
|
||||||
memory: 64
|
parallelism: 4
|
||||||
|
key_length: 32
|
||||||
|
salt_length: 16
|
||||||
|
scrypt:
|
||||||
|
iterations: 16
|
||||||
|
block_size: 8
|
||||||
|
parallelism: 1
|
||||||
|
key_length: 32
|
||||||
|
salt_length: 16
|
||||||
|
pbkdf2:
|
||||||
|
variant: sha512
|
||||||
|
iterations: 310000
|
||||||
|
salt_length: 16
|
||||||
|
sha2crypt:
|
||||||
|
variant: sha512
|
||||||
|
iterations: 50000
|
||||||
|
salt_length: 16
|
||||||
|
bcrypt:
|
||||||
|
variant: standard
|
||||||
|
cost: 12
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
@ -39,70 +62,37 @@ The path to the file with the user details list. Supported file types are:
|
||||||
|
|
||||||
* [YAML File](../../reference/guides/passwords.md#yaml-format)
|
* [YAML File](../../reference/guides/passwords.md#yaml-format)
|
||||||
|
|
||||||
### password
|
### watch
|
||||||
|
|
||||||
#### algorithm
|
{{< confkey type="boolean" default="false" required="no" >}}
|
||||||
|
|
||||||
{{< confkey type="string" default="argon2id" required="no" >}}
|
Enables reloading the database by watching it for changes.
|
||||||
|
|
||||||
Controls the hashing algorithm used for hashing new passwords. Value must be one of:
|
### search
|
||||||
|
|
||||||
* `argon2id` for the [Argon2] `id` variant
|
Username searching functionality options.
|
||||||
* `sha512` for the [SHA Crypt] `SHA512` variant
|
|
||||||
|
|
||||||
#### iterations
|
*__Important Note:__ This functionality is experimental.*
|
||||||
|
|
||||||
{{< confkey type="integer" required="no" >}}
|
#### email
|
||||||
|
|
||||||
Controls the number of hashing iterations done by the other hashing settings ([Argon2] parameter `t`, [SHA Crypt]
|
{{< confkey type="boolean" default="false" required="no" >}}
|
||||||
parameter `rounds`). This affects the effective cost of hashing.
|
|
||||||
|
|
||||||
| Algorithm | Minimum | Default | Recommended |
|
Allows users to login using their email address. If enabled two users must not have the same emails and their usernames
|
||||||
|:---------:|:-------:|:-------:|:------------------------------------------------------------------------------------------:|
|
must not be an email.
|
||||||
| argon2id | 1 | 3 | [See Recommendations](../../reference/guides/passwords.md#recommended-parameters-argon2id) |
|
|
||||||
| sha512 | 1000 | 50000 | [See Recommendations](../../reference/guides/passwords.md#recommended-parameters-sha512) |
|
|
||||||
|
|
||||||
#### key_length
|
*__Note:__ Emails are always checked using case-insensitive lookup.*
|
||||||
|
|
||||||
{{< confkey type="integer" default="32" required="no" >}}
|
#### case_insensitive
|
||||||
|
|
||||||
*__Important:__ This setting is specific to the `argon2id` algorithm and unused with the `sha512` algorithm.*
|
{{< confkey type="boolean" default="false" required="no" >}}
|
||||||
|
|
||||||
Sets the key length of the [Argon2] hash output. The minimum value is `16` with the recommended value of `32` being set
|
Enabling this search option allows users to login with their username regardless of case. If enabled users must only
|
||||||
as the default.
|
have lowercase usernames.
|
||||||
|
|
||||||
#### salt_length
|
*__Note:__ Emails are always checked using case-insensitive lookup.*
|
||||||
|
|
||||||
{{< confkey type="integer" default="16" required="no" >}}
|
## Password Options
|
||||||
|
|
||||||
Controls the length of the random salt added to each password before hashing. There is not a compelling reason to have
|
|
||||||
this set to anything other than `16`, however the minimum is `8` with the recommended value of `16` being set as the
|
|
||||||
default.
|
|
||||||
|
|
||||||
#### parallelism
|
|
||||||
|
|
||||||
{{< confkey type="integer" default="4" required="no" >}}
|
|
||||||
|
|
||||||
*__Important:__ This setting is specific to the `argon2id` algorithm and unused with the `sha512` algorithm.*
|
|
||||||
|
|
||||||
Sets the number of threads used by [Argon2] when hashing passwords ([Argon2] parameter `p`). The minimum value is `1`
|
|
||||||
with the recommended value of `4` being set as the default. This affects the effective cost of hashing.
|
|
||||||
|
|
||||||
#### memory
|
|
||||||
|
|
||||||
{{< confkey type="integer" default="64" required="no" >}}
|
|
||||||
|
|
||||||
*__Important:__ This setting is specific to the `argon2id` algorithm and unused with the `sha512` algorithm.*
|
|
||||||
|
|
||||||
Sets the amount of memory in megabytes allocated to a single password hashing calculation ([Argon2] parameter `m`). This
|
|
||||||
affects the effective cost of hashing.
|
|
||||||
|
|
||||||
This memory is released by go after the hashing process completes, however the operating system may not reclaim the
|
|
||||||
memory until a later time such as when the system is experiencing memory pressure which may cause the appearance of more
|
|
||||||
memory being in use than Authelia is actually actively using. Authelia will typically reuse this memory if it has not be
|
|
||||||
reclaimed as long as another hashing calculation is not still utilizing it.
|
|
||||||
|
|
||||||
## Reference
|
|
||||||
|
|
||||||
A [reference guide](../../reference/guides/passwords.md) exists specifically for choosing password hashing values. This
|
A [reference guide](../../reference/guides/passwords.md) exists specifically for choosing password hashing values. This
|
||||||
section contains far more information than is practical to include in this configuration document. See the
|
section contains far more information than is practical to include in this configuration document. See the
|
||||||
|
@ -110,5 +100,164 @@ section contains far more information than is practical to include in this confi
|
||||||
|
|
||||||
This guide contains examples such as the [User / Password File](../../reference/guides/passwords.md#user--password-file).
|
This guide contains examples such as the [User / Password File](../../reference/guides/passwords.md#user--password-file).
|
||||||
|
|
||||||
|
### algorithm
|
||||||
|
|
||||||
|
{{< confkey type="string" default="argon2" required="no" >}}
|
||||||
|
|
||||||
|
Controls the hashing algorithm used for hashing new passwords. Value must be one of:
|
||||||
|
|
||||||
|
* `argon2` for the [Argon2](#argon2) algorithm
|
||||||
|
* `scrypt` for the [Scrypt](#scrypt) algorithm
|
||||||
|
* `pbkdf2` for the [PBKDF2](#pbkdf2) algorithm
|
||||||
|
* `sha2crypt` for the [SHA2Crypt](#sha2crypt) algorithm
|
||||||
|
* `bcrypt` for the [Bcrypt](#bcrypt) algorithm
|
||||||
|
|
||||||
|
### argon2
|
||||||
|
|
||||||
|
The [Argon2] algorithm implementation. This is one of the only algorithms that was designed purely with password hashing
|
||||||
|
in mind and is subsequently one of the best algorithms to date for security.
|
||||||
|
|
||||||
|
#### variant
|
||||||
|
|
||||||
|
{{< confkey type="string" default="argon2id" required="no" >}}
|
||||||
|
|
||||||
|
Controls the variant when hashing passwords using [Argon2]. Recommended `argon2id`.
|
||||||
|
Permitted values `argon2id`, `argon2i`, `argon2d`.
|
||||||
|
|
||||||
|
#### iterations
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="3" required="no" >}}
|
||||||
|
|
||||||
|
Controls the number of iterations when hashing passwords using [Argon2].
|
||||||
|
|
||||||
|
#### memory
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="65536" required="no" >}}
|
||||||
|
|
||||||
|
Controls the amount of memory in kibibytes when hashing passwords using [Argon2].
|
||||||
|
|
||||||
|
#### parallelism
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="4" required="no" >}}
|
||||||
|
|
||||||
|
Controls the parallelism factor when hashing passwords using [Argon2].
|
||||||
|
|
||||||
|
#### key_length
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="32" required="no" >}}
|
||||||
|
|
||||||
|
Controls the output key length when hashing passwords using [Argon2].
|
||||||
|
|
||||||
|
#### salt_length
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="16" required="no" >}}
|
||||||
|
|
||||||
|
Controls the output salt length when hashing passwords using [Argon2].
|
||||||
|
|
||||||
|
### scrypt
|
||||||
|
|
||||||
|
The [Scrypt] algorithm implementation.
|
||||||
|
|
||||||
|
#### iterations
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="16" required="no" >}}
|
||||||
|
|
||||||
|
Controls the number of iterations when hashing passwords using [Scrypt].
|
||||||
|
|
||||||
|
#### block_size
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="8" required="no" >}}
|
||||||
|
|
||||||
|
Controls the block size when hashing passwords using [Scrypt].
|
||||||
|
|
||||||
|
#### parallelism
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="1" required="no" >}}
|
||||||
|
|
||||||
|
Controls the parallelism factor when hashing passwords using [Scrypt].
|
||||||
|
|
||||||
|
#### key_length
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="32" required="no" >}}
|
||||||
|
|
||||||
|
Controls the output key length when hashing passwords using [Scrypt].
|
||||||
|
|
||||||
|
#### salt_length
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="16" required="no" >}}
|
||||||
|
|
||||||
|
Controls the output salt length when hashing passwords using [Scrypt].
|
||||||
|
|
||||||
|
### pbkdf2
|
||||||
|
|
||||||
|
The [PBKDF2] algorithm implementation.
|
||||||
|
|
||||||
|
#### variant
|
||||||
|
|
||||||
|
{{< confkey type="string" default="sha512" required="no" >}}
|
||||||
|
|
||||||
|
Controls the variant when hashing passwords using [PBKDF2]. Recommended `sha512`.
|
||||||
|
Permitted values `sha1`, `sha224`, `sha256`, `sha384`, `sha512`.
|
||||||
|
|
||||||
|
#### iterations
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="310000" required="no" >}}
|
||||||
|
|
||||||
|
Controls the number of iterations when hashing passwords using [PBKDF2].
|
||||||
|
|
||||||
|
#### salt_length
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="16" required="no" >}}
|
||||||
|
|
||||||
|
Controls the output salt length when hashing passwords using [PBKDF2].
|
||||||
|
|
||||||
|
### sha2crypt
|
||||||
|
|
||||||
|
The [SHA2 Crypt] algorithm implementation.
|
||||||
|
|
||||||
|
#### variant
|
||||||
|
|
||||||
|
{{< confkey type="string" default="sha512" required="no" >}}
|
||||||
|
|
||||||
|
Controls the variant when hashing passwords using [SHA2 Crypt]. Recommended `sha512`.
|
||||||
|
Permitted values `sha256`, `sha512`.
|
||||||
|
|
||||||
|
#### iterations
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="50000" required="no" >}}
|
||||||
|
|
||||||
|
Controls the number of iterations when hashing passwords using [SHA2 Crypt].
|
||||||
|
|
||||||
|
#### salt_length
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="16" required="no" >}}
|
||||||
|
|
||||||
|
Controls the output salt length when hashing passwords using [SHA2 Crypt].
|
||||||
|
|
||||||
|
### bcrypt
|
||||||
|
|
||||||
|
The [Bcrypt] algorithm implementation.
|
||||||
|
|
||||||
|
#### variant
|
||||||
|
|
||||||
|
{{< confkey type="string" default="standard" required="no" >}}
|
||||||
|
|
||||||
|
Controls the variant when hashing passwords using [Bcrypt]. Recommended `standard`.
|
||||||
|
Permitted values `standard`, `sha256`.
|
||||||
|
|
||||||
|
*__Important Note:__ The `sha256` variant is a special variant designed by
|
||||||
|
[Passlib](https://passlib.readthedocs.io/en/stable/lib/passlib.hash.bcrypt_sha256.html). This variant passes the
|
||||||
|
password through a SHA256 HMAC before passing it to the [Bcrypt] algorithm, effectively bypassing the 72 byte password
|
||||||
|
truncation that [Bcrypt] does. It is not supported by many other systems.*
|
||||||
|
|
||||||
|
#### cost
|
||||||
|
|
||||||
|
{{< confkey type="integer" default="12" required="no" >}}
|
||||||
|
|
||||||
|
Controls the hashing cost when hashing passwords using [Bcrypt].
|
||||||
|
|
||||||
[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html
|
[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html
|
||||||
[SHA Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
|
[Scrypt]: https://en.wikipedia.org/wiki/Scrypt
|
||||||
|
[PBKDF2]: https://www.ietf.org/rfc/rfc2898.html
|
||||||
|
[SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
|
||||||
|
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
|
||||||
|
|
|
@ -28,13 +28,81 @@ authentication_backend:
|
||||||
server_name: ldap.example.com
|
server_name: ldap.example.com
|
||||||
skip_verify: false
|
skip_verify: false
|
||||||
minimum_version: TLS1.2
|
minimum_version: TLS1.2
|
||||||
|
maximum_version: TLS1.3
|
||||||
|
certificate_chain: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC5jCCAc6gAwIBAgIRAK4Sj7FiN6PXo/urPfO4E7owDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAPKv3pSyP4ozGEiVLJ14dIWFCEGEgq7WUMI0SZZqQA2ID0L59U/Q
|
||||||
|
/Usyy7uC9gfMUzODTpANtkOjFQcQAsxlR1FOjVBrX5QgjSvXwbQn3DtwMA7XWSl6
|
||||||
|
LuYx2rBYSlMSN5UZQm/RxMtXfLK2b51WgEEYDFi+nECSqKzR4R54eOPkBEWRfvuY
|
||||||
|
91AMjlhpivg8e4JWkq4LVQUKbmiFYwIdK8XQiN4blY9WwXwJFYs5sQ/UYMwBFi0H
|
||||||
|
kWOh7GEjfxgoUOPauIueZSMSlQp7zqAH39N0ZSYb6cS0Npj57QoWZSY3ak87ebcR
|
||||||
|
Nf4rCvZLby7LoN7qYCKxmCaDD3x2+NYpWH8CAwEAAaM1MDMwDgYDVR0PAQH/BAQD
|
||||||
|
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHSITqIQSNzonFl3DzxHPEzr2hp6peo45buAAtu8FZHoA+U7Icfh
|
||||||
|
/ZXjPg7Xz+hgFwM/DTNGXkMWacQA/PaNWvZspgRJf2AXvNbMSs2UQODr7Tbv+Fb4
|
||||||
|
lyblmMUNYFMCFVAMU0eIxXAFq2qcwv8UMcQFT0Z/35s6PVOakYnAGGQjTfp5Ljuq
|
||||||
|
wsdc/xWmM0cHWube6sdRRUD7SY20KU/kWzl8iFO0VbSSrDf1AlEhnLEkp1SPaxXg
|
||||||
|
OdBnl98MeoramNiJ7NT6Jnyb3zZ578fjaWfThiBpagItI8GZmG4s4Ovh2JbheN8i
|
||||||
|
ZsjNr9jqHTjhyLVbDRlmJzcqoj4JhbKs6/I^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDBDCCAeygAwIBAgIRALJsPg21kA0zY4F1wUCIuoMwDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAMXHBvVxUzYk0u34/DINMSF+uiOekKOAjOrC6Mi9Ww8ytPVO7t2S
|
||||||
|
zfTvM+XnEJqkFQFgimERfG/eGhjF9XIEY6LtnXe8ATvOK4nTwdufzBaoeQu3Gd50
|
||||||
|
5VXr6OHRo//ErrGvFXwP3g8xLePABsi/fkH3oDN+ztewOBMDzpd+KgTrk8ysv2ou
|
||||||
|
kNRMKFZZqASvCgv0LD5KWvUCnL6wgf1oTXG7aztduA4oSkUP321GpOmBC5+5ElU7
|
||||||
|
ysoRzvD12o9QJ/IfEaulIX06w9yVMo60C/h6A3U6GdkT1SiyTIqR7v7KU/IWd/Qi
|
||||||
|
Lfftcj91VhCmJ73Meff2e2S2PrpjdXbG5FMCAwEAAaNTMFEwDgYDVR0PAQH/BAQD
|
||||||
|
AgKkMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
|
||||||
|
Z7AtA3mzFc0InSBA5fiMfeLXA3owDQYJKoZIhvcNAQELBQADggEBAEE5hm1mtlk/
|
||||||
|
kviCoHH4evbpw7rxPxDftIQlqYTtvMM4eWY/6icFoSZ4fUHEWYyps8SsPu/8f2tf
|
||||||
|
71LGgZn0FdHi1QU2H8m0HHK7TFw+5Q6RLrLdSyk0PItJ71s9en7r8pX820nAFEHZ
|
||||||
|
HkOSfJZ7B5hFgUDkMtVM6bardXAhoqcMk4YCU96e9d4PB4eI+xGc+mNuYvov3RbB
|
||||||
|
D0s8ICyojeyPVLerz4wHjZu68Z5frAzhZ68YbzNs8j2fIBKKHkHyLG1iQyF+LJVj
|
||||||
|
2PjCP+auJsj6fQQpMGoyGtpLcSDh+ptcTngUD8JsWipzTCjmaNqdPHAOYmcgtf4b
|
||||||
|
qocikt3WAdU^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
private_key: |
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEA8q/elLI/ijMYSJUsnXh0hYUIQYSCrtZQwjRJlmpADYgPQvn1
|
||||||
|
T9D9SzLLu4L2B8xTM4NOkA22Q6MVBxACzGVHUU6NUGtflCCNK9fBtCfcO3AwDtdZ
|
||||||
|
KXou5jHasFhKUxI3lRlCb9HEy1d8srZvnVaAQRgMWL6cQJKorNHhHnh44+QERZF+
|
||||||
|
+5j3UAyOWGmK+Dx7glaSrgtVBQpuaIVjAh0rxdCI3huVj1bBfAkVizmxD9RgzAEW
|
||||||
|
LQeRY6HsYSN/GChQ49q4i55lIxKVCnvOoAff03RlJhvpxLQ2mPntChZlJjdqTzt5
|
||||||
|
txE1/isK9ktvLsug3upgIrGYJoMPfHb41ilYfwIDAQABAoIBAQDTOdFf2JjHH1um
|
||||||
|
aPgRAvNf9v7Nj5jytaRKs5nM6iNf46ls4QPreXnMhqSeSwj6lpNgBYxOgzC9Q+cc
|
||||||
|
Y4ob/paJJPaIJTxmP8K/gyWcOQlNToL1l+eJ20eQoZm23NGr5fIsunSBwLEpTrdB
|
||||||
|
ENqqtcwhW937K8Pxy/Q1nuLyU2bc6Tn/ivLozc8n27dpQWWKh8537VY7ancIaACr
|
||||||
|
LJJLYxKqhQpjtBWAyCDvZQirnAOm9KnvIHaGXIswCZ4Xbsu0Y9NL+woARPyRVQvG
|
||||||
|
jfxy4EmO9s1s6y7OObSukwKDSNihAKHx/VIbvVWx8g2Lv5fGOa+J2Y7o9Qurs8t5
|
||||||
|
BQwMTt0BAoGBAPUw5Z32EszNepAeV3E2mPFUc5CLiqAxagZJuNDO2pKtyN29ETTR
|
||||||
|
Ma4O1cWtGb6RqcNNN/Iukfkdk27Q5nC9VJSUUPYelOLc1WYOoUf6oKRzE72dkMQV
|
||||||
|
R4bf6TkjD+OVR17fAfkswkGahZ5XA7j48KIQ+YC4jbnYKSxZTYyKPjH/AoGBAP1i
|
||||||
|
tqXt36OVlP+y84wWqZSjMelBIVa9phDVGJmmhz3i1cMni8eLpJzWecA3pfnG6Tm9
|
||||||
|
ze5M4whASleEt+M00gEvNaU9ND+z0wBfi+/DwJYIbv8PQdGrBiZFrPhTPjGQUldR
|
||||||
|
lXccV2meeLZv7TagVxSi3DO6dSJfSEHyemd5j9mBAoGAX8Hv+0gOQZQCSOTAq8Nx
|
||||||
|
6dZcp9gHlNaXnMsP9eTDckOSzh636JPGvj6m+GPJSSbkURUIQ3oyokMNwFqvlNos
|
||||||
|
fTaLhAOfjBZI9WnDTTQxpugWjphJ4HqbC67JC/qIiw5S6FdaEvGLEEoD4zoChywZ
|
||||||
|
9oGAn+fz2d/0/JAH/FpFPgsCgYEAp/ipZgPzziiZ9ov1wbdAQcWRj7RaWnssPFpX
|
||||||
|
jXwEiXT3CgEMO4MJ4+KWIWOChrti3qFBg6i6lDyyS6Qyls7sLFbUdC7HlTcrOEMe
|
||||||
|
rBoTcCI1GqZNlqWOVQ65ZIEiaI7o1vPBZo2GMQEZuq8mDKFsOMThvvTrM5cAep84
|
||||||
|
n6HJR4ECgYABWcbsSnr0MKvVth/inxjbKapbZnp2HUCuw87Ie5zK2Of/tbC20wwk
|
||||||
|
yKw3vrGoE3O1t1g2m2tn8UGGASeZ842jZWjIODdSi5+icysQGuULKt86h/woz2SQ
|
||||||
|
27GoE2i5mh6Yez6VAYbUuns3FcwIsMyWLq043Tu2DNkx9ijOOAuQzw^invalid..
|
||||||
|
DO NOT USE==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
base_dn: DC=example,DC=com
|
base_dn: DC=example,DC=com
|
||||||
additional_users_dn: ou=users
|
additional_users_dn: OU=users
|
||||||
users_filter: (&({username_attribute}={input})(objectClass=person))
|
users_filter: (&({username_attribute}={input})(objectClass=person))
|
||||||
username_attribute: uid
|
username_attribute: uid
|
||||||
mail_attribute: mail
|
mail_attribute: mail
|
||||||
display_name_attribute: displayName
|
display_name_attribute: displayName
|
||||||
additional_groups_dn: ou=groups
|
additional_groups_dn: OU=groups
|
||||||
groups_filter: (&(member={dn})(objectClass=groupOfNames))
|
groups_filter: (&(member={dn})(objectClass=groupOfNames))
|
||||||
group_name_attribute: cn
|
group_name_attribute: cn
|
||||||
permit_referrals: false
|
permit_referrals: false
|
||||||
|
@ -198,6 +266,13 @@ server and utilizing a service account.*
|
||||||
Permits binding to the server without a password. For this option to be enabled both the [password](#password)
|
Permits binding to the server without a password. For this option to be enabled both the [password](#password)
|
||||||
configuration option must be blank and the [password_reset disable](introduction.md#disable) option must be `true`.
|
configuration option must be blank and the [password_reset disable](introduction.md#disable) option must be `true`.
|
||||||
|
|
||||||
|
### permit_feature_detection_failure
|
||||||
|
|
||||||
|
{{< confkey type="boolean" default="false" required="no" >}}
|
||||||
|
|
||||||
|
Authelia searches for the RootDSE to discover supported controls and extensions. This option is a compatability option
|
||||||
|
which *__should not__* be enabled unless the LDAP server returns an error when searching for the RootDSE.
|
||||||
|
|
||||||
### user
|
### user
|
||||||
|
|
||||||
{{< confkey type="string" required="yes" >}}
|
{{< confkey type="string" required="yes" >}}
|
||||||
|
@ -214,7 +289,7 @@ especially for containerized deployments.*
|
||||||
The password paired with the [user](#user) used to bind to the LDAP server for lookup and password change operations.
|
The password paired with the [user](#user) used to bind to the LDAP server for lookup and password change operations.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters and the user password is changed to this value.
|
characters and the user password is changed to this value.
|
||||||
|
|
||||||
## Refresh Interval
|
## Refresh Interval
|
||||||
|
|
|
@ -33,33 +33,72 @@ The following snippet provides a sample-configuration for the OIDC identity prov
|
||||||
identity_providers:
|
identity_providers:
|
||||||
oidc:
|
oidc:
|
||||||
hmac_secret: this_is_a_secret_abc123abc123abc
|
hmac_secret: this_is_a_secret_abc123abc123abc
|
||||||
|
issuer_certificate_chain: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC5jCCAc6gAwIBAgIRAK4Sj7FiN6PXo/urPfO4E7owDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAPKv3pSyP4ozGEiVLJ14dIWFCEGEgq7WUMI0SZZqQA2ID0L59U/Q
|
||||||
|
/Usyy7uC9gfMUzODTpANtkOjFQcQAsxlR1FOjVBrX5QgjSvXwbQn3DtwMA7XWSl6
|
||||||
|
LuYx2rBYSlMSN5UZQm/RxMtXfLK2b51WgEEYDFi+nECSqKzR4R54eOPkBEWRfvuY
|
||||||
|
91AMjlhpivg8e4JWkq4LVQUKbmiFYwIdK8XQiN4blY9WwXwJFYs5sQ/UYMwBFi0H
|
||||||
|
kWOh7GEjfxgoUOPauIueZSMSlQp7zqAH39N0ZSYb6cS0Npj57QoWZSY3ak87ebcR
|
||||||
|
Nf4rCvZLby7LoN7qYCKxmCaDD3x2+NYpWH8CAwEAAaM1MDMwDgYDVR0PAQH/BAQD
|
||||||
|
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHSITqIQSNzonFl3DzxHPEzr2hp6peo45buAAtu8FZHoA+U7Icfh
|
||||||
|
/ZXjPg7Xz+hgFwM/DTNGXkMWacQA/PaNWvZspgRJf2AXvNbMSs2UQODr7Tbv+Fb4
|
||||||
|
lyblmMUNYFMCFVAMU0eIxXAFq2qcwv8UMcQFT0Z/35s6PVOakYnAGGQjTfp5Ljuq
|
||||||
|
wsdc/xWmM0cHWube6sdRRUD7SY20KU/kWzl8iFO0VbSSrDf1AlEhnLEkp1SPaxXg
|
||||||
|
OdBnl98MeoramNiJ7NT6Jnyb3zZ578fjaWfThiBpagItI8GZmG4s4Ovh2JbheN8i
|
||||||
|
ZsjNr9jqHTjhyLVbDRlmJzcqoj4JhbKs6/I^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDBDCCAeygAwIBAgIRALJsPg21kA0zY4F1wUCIuoMwDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAMXHBvVxUzYk0u34/DINMSF+uiOekKOAjOrC6Mi9Ww8ytPVO7t2S
|
||||||
|
zfTvM+XnEJqkFQFgimERfG/eGhjF9XIEY6LtnXe8ATvOK4nTwdufzBaoeQu3Gd50
|
||||||
|
5VXr6OHRo//ErrGvFXwP3g8xLePABsi/fkH3oDN+ztewOBMDzpd+KgTrk8ysv2ou
|
||||||
|
kNRMKFZZqASvCgv0LD5KWvUCnL6wgf1oTXG7aztduA4oSkUP321GpOmBC5+5ElU7
|
||||||
|
ysoRzvD12o9QJ/IfEaulIX06w9yVMo60C/h6A3U6GdkT1SiyTIqR7v7KU/IWd/Qi
|
||||||
|
Lfftcj91VhCmJ73Meff2e2S2PrpjdXbG5FMCAwEAAaNTMFEwDgYDVR0PAQH/BAQD
|
||||||
|
AgKkMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
|
||||||
|
Z7AtA3mzFc0InSBA5fiMfeLXA3owDQYJKoZIhvcNAQELBQADggEBAEE5hm1mtlk/
|
||||||
|
kviCoHH4evbpw7rxPxDftIQlqYTtvMM4eWY/6icFoSZ4fUHEWYyps8SsPu/8f2tf
|
||||||
|
71LGgZn0FdHi1QU2H8m0HHK7TFw+5Q6RLrLdSyk0PItJ71s9en7r8pX820nAFEHZ
|
||||||
|
HkOSfJZ7B5hFgUDkMtVM6bardXAhoqcMk4YCU96e9d4PB4eI+xGc+mNuYvov3RbB
|
||||||
|
D0s8ICyojeyPVLerz4wHjZu68Z5frAzhZ68YbzNs8j2fIBKKHkHyLG1iQyF+LJVj
|
||||||
|
2PjCP+auJsj6fQQpMGoyGtpLcSDh+ptcTngUD8JsWipzTCjmaNqdPHAOYmcgtf4b
|
||||||
|
qocikt3WAdU^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
issuer_private_key: |
|
issuer_private_key: |
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
MXIEogIB$AKCAQEAxZVJP3WF//PG2fLQoEC9DtdiFG/+00vqlbVzz47nyxKONIPI
|
MIIEpAIBAAKCAQEA8q/elLI/ijMYSJUsnXh0hYUIQYSCrtZQwjRJlmpADYgPQvn1
|
||||||
lmL3UdmqpGTKMe/5Brqse4ZAKlQHiDbwzK9ypnfigtHuvh/JO0S7ChP70RC67ed1
|
T9D9SzLLu4L2B8xTM4NOkA22Q6MVBxACzGVHUU6NUGtflCCNK9fBtCfcO3AwDtdZ
|
||||||
HV1nyfz5eW3llbtGJPrlYLqITNgctHp6zmRUFtSzPj9qFvozI93LJi492yL1+vu8
|
KXou5jHasFhKUxI3lRlCb9HEy1d8srZvnVaAQRgMWL6cQJKorNHhHnh44+QERZF+
|
||||||
Un3Dm8+Qq6XM2tPdEcldB/dtBwOWoF+8eOOVsu0TDuB5bwlhBVGJuSAuzBPRS2bF
|
+5j3UAyOWGmK+Dx7glaSrgtVBQpuaIVjAh0rxdCI3huVj1bBfAkVizmxD9RgzAEW
|
||||||
Ga4uk0JDdkDOMCEQxC5uWDFxgfERSMFyfLVWD47woDbuWEBq10c0z+dpWPMp7Ain
|
LQeRY6HsYSN/GChQ49q4i55lIxKVCnvOoAff03RlJhvpxLQ2mPntChZlJjdqTzt5
|
||||||
YnnkqicwCN88Z0zid6MmMQ65F4+9Hc+qC/p6xwIDAQABAoIBAGlhaAHKor+Su3o/
|
txE1/isK9ktvLsug3upgIrGYJoMPfHb41ilYfwIDAQABAoIBAQDTOdFf2JjHH1um
|
||||||
AXqXTL5/rbYMzbLQiLt0XeJT69jpeqMTroZXHmWvXE3128mqnf0yzw/K2Ko6yxGh
|
aPgRAvNf9v7Nj5jytaRKs5nM6iNf46ls4QPreXnMhqSeSwj6lpNgBYxOgzC9Q+cc
|
||||||
i+j/onya8FqpsVYCCgfsbn2/js1AyRJeIp6Y1ORsYnqbXJnxmkXa80AV/OBPW2/+
|
Y4ob/paJJPaIJTxmP8K/gyWcOQlNToL1l+eJ20eQoZm23NGr5fIsunSBwLEpTrdB
|
||||||
60TtSdQrebY3iFPc+i2k+9bPTvpyyDLKlz8UwdZG+k5uyYNIyQTccz+PjwsIvDij
|
ENqqtcwhW937K8Pxy/Q1nuLyU2bc6Tn/ivLozc8n27dpQWWKh8537VY7ancIaACr
|
||||||
7tKYamhhLN3QXt3/aZTFpjTgezP4WyriZxjWrddHowc47q2rwNS95ND39JcysJAc
|
LJJLYxKqhQpjtBWAyCDvZQirnAOm9KnvIHaGXIswCZ4Xbsu0Y9NL+woARPyRVQvG
|
||||||
0Pcbu8A5lVa7Fx33uOtzDfKWIW7xVEN+OtPgN+FbTjXcXk5IZedl+pW5lU5P++G/
|
jfxy4EmO9s1s6y7OObSukwKDSNihAKHx/VIbvVWx8g2Lv5fGOa+J2Y7o9Qurs8t5
|
||||||
ZPvz+WECgYEA9g6HwdODW3e68bOqsFoKg35+vfUFMzlyMF8HFylNVfnLpTEDr637
|
BQwMTt0BAoGBAPUw5Z32EszNepAeV3E2mPFUc5CLiqAxagZJuNDO2pKtyN29ETTR
|
||||||
owzMFvcUxVd71b+gV5nnnbI+riUFIgyR8vhCjhy4moopDPahC4/KwN4NG6uz+i1h
|
Ma4O1cWtGb6RqcNNN/Iukfkdk27Q5nC9VJSUUPYelOLc1WYOoUf6oKRzE72dkMQV
|
||||||
AB6D5+zn2BjnO/5xMMFGlApWtRNmJVGYlNDj3bXKh2VXzzy03VNeD8kCgYEAzZFL
|
R4bf6TkjD+OVR17fAfkswkGahZ5XA7j48KIQ+YC4jbnYKSxZTYyKPjH/AoGBAP1i
|
||||||
OlzoRB1HKpTWIECcuvxofMxLOLb3zs0k2t/FYNYIpovmGWCCAULz13y53e5+/+5m
|
tqXt36OVlP+y84wWqZSjMelBIVa9phDVGJmmhz3i1cMni8eLpJzWecA3pfnG6Tm9
|
||||||
7I9VUZJFaIhaZ36qVBApCKdru69pZMkWCcQO9jELFcx51Ez7OgJWzu7GS1QJCPKC
|
ze5M4whASleEt+M00gEvNaU9ND+z0wBfi+/DwJYIbv8PQdGrBiZFrPhTPjGQUldR
|
||||||
fEDxI0rZK21j93/Sl/nUnEir7CYpQ+wvCaGuHg8CgYAXgbncfY1+DokwkB6NbHy2
|
lXccV2meeLZv7TagVxSi3DO6dSJfSEHyemd5j9mBAoGAX8Hv+0gOQZQCSOTAq8Nx
|
||||||
pT4Mfbz6cNGE538w6kQ2I4AeDvmwLentYMqaow478CinegAiflSPTzkHwAemghbr
|
6dZcp9gHlNaXnMsP9eTDckOSzh636JPGvj6m+GPJSSbkURUIQ3oyokMNwFqvlNos
|
||||||
ZGZPV1UXhn13fJRUG2+eT1hnPVcbXnx223N0k8Bud6qXo65CnyRT/kzcTbcjd5Eh
|
fTaLhAOfjBZI9WnDTTQxpugWjphJ4HqbC67JC/qIiw5S6FdaEvGLEEoD4zoChywZ
|
||||||
Hne2daicmMTzynPo9Q72aQKBgBmobO9X8VWvIdbaxO85oVZlctVA2pK1o7CYQmVf
|
9oGAn+fz2d/0/JAH/FpFPgsCgYEAp/ipZgPzziiZ9ov1wbdAQcWRj7RaWnssPFpX
|
||||||
UM+JZ4MCKzI3rYJizPS0iK5+ujNPmmEkcs2/qBIoEsCgOrpLWhPOcc/3UPxXbPzD
|
jXwEiXT3CgEMO4MJ4+KWIWOChrti3qFBg6i6lDyyS6Qyls7sLFbUdC7HlTcrOEMe
|
||||||
D+sCrBOIdhxdj23qJNOnUfDNCGOpgUfpAzAYg4q8GKInvi1h7XukRnEvQi9MJ4LY
|
rBoTcCI1GqZNlqWOVQ65ZIEiaI7o1vPBZo2GMQEZuq8mDKFsOMThvvTrM5cAep84
|
||||||
P1dZAoGASGcGnTMkmeSXP8ux+dvQJAiJskn/sJIgBZ5uq5GRCeLBUosRSVxM75UK
|
n6HJR4ECgYABWcbsSnr0MKvVth/inxjbKapbZnp2HUCuw87Ie5zK2Of/tbC20wwk
|
||||||
vAh/c/RBj+pYXVKuPuHGZCQJxsdcRXzXNGouUtgbaYML5Me/Hagt20QzDRBfuGBg
|
yKw3vrGoE3O1t1g2m2tn8UGGASeZ842jZWjIODdSi5+icysQGuULKt86h/woz2SQ
|
||||||
qeZBJaXhjElvw6PUWtg4x+LYRCBpq/bS3LK3ozZrSTukVkKDegw=
|
27GoE2i5mh6Yez6VAYbUuns3FcwIsMyWLq043Tu2DNkx9ijOOAuQzw^invalid..
|
||||||
|
DO NOT USE==
|
||||||
-----END RSA PRIVATE KEY-----
|
-----END RSA PRIVATE KEY-----
|
||||||
access_token_lifespan: 1h
|
access_token_lifespan: 1h
|
||||||
authorize_code_lifespan: 1m
|
authorize_code_lifespan: 1m
|
||||||
|
@ -79,11 +118,12 @@ identity_providers:
|
||||||
clients:
|
clients:
|
||||||
- id: myapp
|
- id: myapp
|
||||||
description: My Application
|
description: My Application
|
||||||
secret: this_is_a_secret
|
secret: '$plaintext$this_is_a_secret'
|
||||||
sector_identifier: ''
|
sector_identifier: ''
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
pre_configured_consent_duration: ''
|
consent_mode: explicit
|
||||||
|
pre_configured_consent_duration: 1w
|
||||||
audience: []
|
audience: []
|
||||||
scopes:
|
scopes:
|
||||||
- openid
|
- openid
|
||||||
|
@ -117,9 +157,26 @@ The HMAC secret used to sign the [JWT]'s. The provided string is hashed to a SHA
|
||||||
purpose of meeting the required format.
|
purpose of meeting the required format.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters.
|
characters.
|
||||||
|
|
||||||
|
### issuer_certificate_chain
|
||||||
|
|
||||||
|
{{< confkey type="string" required="no" >}}
|
||||||
|
|
||||||
|
The certificate chain/bundle to be used with the [issuer_private_key](#issuer_private_key) DER base64 ([RFC4648])
|
||||||
|
encoded PEM format used to sign/encrypt the [OpenID Connect] [JWT]'s. When configured it enables the [x5c] and [x5t]
|
||||||
|
JSON key's in the JWKs [Discoverable Endpoint](../../integration/openid-connect/introduction.md#discoverable-endpoints)
|
||||||
|
as per [RFC7517].
|
||||||
|
|
||||||
|
[RFC7517]: https://www.rfc-editor.org/rfc/rfc7517
|
||||||
|
[x5c]: https://www.rfc-editor.org/rfc/rfc7517#section-4.7
|
||||||
|
[x5t]: https://www.rfc-editor.org/rfc/rfc7517#section-4.8
|
||||||
|
|
||||||
|
The first certificate in the chain must have the public key for the [issuer_private_key](#issuer_private_key), each
|
||||||
|
certificate in the chain must be valid for the current date, and each certificate in the chain should be signed by the
|
||||||
|
certificate immediately following it if present.
|
||||||
|
|
||||||
### issuer_private_key
|
### issuer_private_key
|
||||||
|
|
||||||
{{< confkey type="string" required="yes" >}}
|
{{< confkey type="string" required="yes" >}}
|
||||||
|
@ -127,9 +184,16 @@ characters.
|
||||||
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
|
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
|
||||||
especially for containerized deployments.*
|
especially for containerized deployments.*
|
||||||
|
|
||||||
The private key in DER base64 ([RFC4648]) encoded PEM format used to encrypt the [OpenID Connect] [JWT]'s. The key must
|
The private key used to sign/encrypt the [OpenID Connect] issued [JWT]'s. The key must be generated by the administrator
|
||||||
be generated by the administrator and can be done by following the
|
and can be done by following the [Generating an RSA Keypair](../../reference/guides/generating-secure-values.md#generating-an-rsa-keypair) guide.
|
||||||
[Generating an RSA Keypair](../miscellaneous/guides.md#generating-an-rsa-keypair) guide.
|
|
||||||
|
The private key *__MUST__*:
|
||||||
|
* Be a PEM block encoded in the DER base64 format ([RFC4648]).
|
||||||
|
* Be an RSA Key.
|
||||||
|
* Have a key size of at least 2048 bits.
|
||||||
|
|
||||||
|
If the [issuer_certificate_chain](#issuer_certificate_chain) is provided the private key must include matching public
|
||||||
|
key data for the first certificate in the chain.
|
||||||
|
|
||||||
### access_token_lifespan
|
### access_token_lifespan
|
||||||
|
|
||||||
|
@ -288,10 +352,10 @@ A friendly description for this client shown in the UI. This defaults to the sam
|
||||||
{{< confkey type="string" required="situational" >}}
|
{{< confkey type="string" required="situational" >}}
|
||||||
|
|
||||||
The shared secret between Authelia and the application consuming this client. This secret must match the secret
|
The shared secret between Authelia and the application consuming this client. This secret must match the secret
|
||||||
configured in the application. Currently this is stored in plain text.
|
configured in the application.
|
||||||
|
|
||||||
This secret must be generated by the administrator and can be done by following the
|
This secret must be generated by the administrator and can be done by following the
|
||||||
[Generating a Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) guide.
|
[Generating Client Secrets](../../integration/openid-connect/specific-information.md#generating-client-secrets) guide.
|
||||||
|
|
||||||
This must be provided when the client is a confidential client type, and must be blank when using the public client
|
This must be provided when the client is a confidential client type, and must be blank when using the public client
|
||||||
type. To set the client type to public see the [public](#public) configuration option.
|
type. To set the client type to public see the [public](#public) configuration option.
|
||||||
|
@ -345,19 +409,38 @@ URI.
|
||||||
|
|
||||||
The authorization policy for this client: either `one_factor` or `two_factor`.
|
The authorization policy for this client: either `one_factor` or `two_factor`.
|
||||||
|
|
||||||
|
#### consent_mode
|
||||||
|
|
||||||
|
{{< confkey type="string" default="auto" required="no" >}}
|
||||||
|
|
||||||
|
Configures the consent mode. The following table describes the different modes:
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
|
||||||
|
| auto | Automatically determined (default). Uses `explicit` unless [pre_configured_consent_duration] is specified in which case uses `pre-configured`. |
|
||||||
|
| explicit | Requires the user provide unique explicit consent for every authorization. |
|
||||||
|
| implicit | Automatically assumes consent for every authorization, never asking the user if they wish to give consent. *__Note:__* this option is not technically part of the specification. |
|
||||||
|
| pre-configured | Allows the end-user to remember their consent for the [pre_configured_consent_duration]. |
|
||||||
|
|
||||||
|
[pre_configured_consent_duration]: #pre_configured_consent_duration
|
||||||
|
|
||||||
#### pre_configured_consent_duration
|
#### pre_configured_consent_duration
|
||||||
|
|
||||||
{{< confkey type="duration" required="no" >}}
|
{{< confkey type="duration" default="1w" required="no" >}}
|
||||||
|
|
||||||
*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see
|
*__Note:__ This setting uses the [duration notation format](../prologue/common.md#duration-notation-format). Please see
|
||||||
the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.*
|
the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.*
|
||||||
|
|
||||||
Configuring this enables users of this client to remember their consent as a pre-configured consent. The period of time
|
Specifying this in the configuration without a consent [consent_mode] enables the `pre-configured` mode. If this is
|
||||||
dictates how long a users choice to remember the pre-configured consent lasts.
|
specified as well as the [consent_mode] then it only has an effect if the [consent_mode] is `pre-configured` or `auto`.
|
||||||
|
|
||||||
|
The period of time dictates how long a users choice to remember the pre-configured consent lasts.
|
||||||
|
|
||||||
Pre-configured consents are only valid if the subject, client id are exactly the same and the requested scopes/audience
|
Pre-configured consents are only valid if the subject, client id are exactly the same and the requested scopes/audience
|
||||||
match exactly with the granted scopes/audience.
|
match exactly with the granted scopes/audience.
|
||||||
|
|
||||||
|
[consent_mode]: #consent_mode
|
||||||
|
|
||||||
#### audience
|
#### audience
|
||||||
|
|
||||||
{{< confkey type="list(string)" required="no" >}}
|
{{< confkey type="list(string)" required="no" >}}
|
||||||
|
|
|
@ -50,3 +50,7 @@ Can be replaced by this environment variable configuration:
|
||||||
AUTHELIA_LOG_LEVEL=info
|
AUTHELIA_LOG_LEVEL=info
|
||||||
AUTHELIA_SERVER_BUFFERS_READ=4096
|
AUTHELIA_SERVER_BUFFERS_READ=4096
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
{{% table-config-keys secrets="false" %}}
|
||||||
|
|
|
@ -52,33 +52,32 @@ Here is the list of the environment variables which are considered secrets and c
|
||||||
secrets can be loaded into the configuration if they end with one of the suffixes above, you can set the value of any
|
secrets can be loaded into the configuration if they end with one of the suffixes above, you can set the value of any
|
||||||
other configuration using the environment but instead of loading a file the value of the environment variable is used.
|
other configuration using the environment but instead of loading a file the value of the environment variable is used.
|
||||||
|
|
||||||
| Configuration Key | Environment Variable |
|
{{% table-config-keys secrets="true" %}}
|
||||||
|:---------------------------------------------------:|:--------------------------------------------------------:|
|
|
||||||
| [server.tls.key] | AUTHELIA_SERVER_TLS_KEY_FILE |
|
|
||||||
| [jwt_secret] | AUTHELIA_JWT_SECRET_FILE |
|
|
||||||
| [duo_api.secret_key] | AUTHELIA_DUO_API_SECRET_KEY_FILE |
|
|
||||||
| [session.secret] | AUTHELIA_SESSION_SECRET_FILE |
|
|
||||||
| [session.redis.password] | AUTHELIA_SESSION_REDIS_PASSWORD_FILE |
|
|
||||||
| [session.redis.high_availability.sentinel_password] | AUTHELIA_REDIS_HIGH_AVAILABILITY_SENTINEL_PASSWORD_FILE |
|
|
||||||
| [storage.encryption_key] | AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE |
|
|
||||||
| [storage.mysql.password] | AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE |
|
|
||||||
| [storage.postgres.password] | AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE |
|
|
||||||
| [notifier.smtp.password] | AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE |
|
|
||||||
| [authentication_backend.ldap.password] | AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE |
|
|
||||||
| [identity_providers.oidc.issuer_private_key] | AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE |
|
|
||||||
| [identity_providers.oidc.hmac_secret] | AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE |
|
|
||||||
|
|
||||||
[server.tls.key]: ../miscellaneous/server.md#key
|
[server.tls.key]: ../miscellaneous/server.md#key
|
||||||
[jwt_secret]: ../miscellaneous/introduction.md#jwt_secret
|
[jwt_secret]: ../miscellaneous/introduction.md#jwt_secret
|
||||||
|
[duo_api.integration_key]: ../second-factor/duo.md#integration_key
|
||||||
[duo_api.secret_key]: ../second-factor/duo.md#secret_key
|
[duo_api.secret_key]: ../second-factor/duo.md#secret_key
|
||||||
[session.secret]: ../session/introduction.md#secret
|
[session.secret]: ../session/introduction.md#secret
|
||||||
[session.redis.password]: ../session/redis.md#password
|
[session.redis.password]: ../session/redis.md#password
|
||||||
|
[session.redis.tls.certificate_chain]: ../session/redis.md#tls
|
||||||
|
[session.redis.tls.private_key]: ../session/redis.md#tls
|
||||||
[session.redis.high_availability.sentinel_password]: ../session/redis.md#sentinel_password
|
[session.redis.high_availability.sentinel_password]: ../session/redis.md#sentinel_password
|
||||||
[storage.encryption_key]: ../storage/introduction.md#encryption_key
|
[storage.encryption_key]: ../storage/introduction.md#encryption_key
|
||||||
[storage.mysql.password]: ../storage/mysql.md#password
|
[storage.mysql.password]: ../storage/mysql.md#password
|
||||||
|
[storage.mysql.tls.certificate_chain]: ../storage/mysql.md#tls
|
||||||
|
[storage.mysql.tls.private_key]: ../storage/mysql.md#tls
|
||||||
[storage.postgres.password]: ../storage/postgres.md#password
|
[storage.postgres.password]: ../storage/postgres.md#password
|
||||||
|
[storage.postgres.tls.certificate_chain]: ../storage/postgres.md#tls
|
||||||
|
[storage.postgres.tls.private_key]: ../storage/postgres.md#tls
|
||||||
|
[storage.postgres.ssl.key]: ../storage/postgres.md
|
||||||
[notifier.smtp.password]: ../notifications/smtp.md#password
|
[notifier.smtp.password]: ../notifications/smtp.md#password
|
||||||
|
[notifier.smtp.tls.certificate_chain]: ../notifications/smtp.md#tls
|
||||||
|
[notifier.smtp.tls.private_key]: ../notifications/smtp.md#tls
|
||||||
[authentication_backend.ldap.password]: ../first-factor/ldap.md#password
|
[authentication_backend.ldap.password]: ../first-factor/ldap.md#password
|
||||||
|
[authentication_backend.ldap.tls.certificate_chain]: ../first-factor/ldap.md#tls
|
||||||
|
[authentication_backend.ldap.tls.private_key]: ../first-factor/ldap.md#tls
|
||||||
|
[identity_providers.oidc.issuer_certificate_chain]: ../identity-providers/open-id-connect.md#issuer_certificate_chain
|
||||||
[identity_providers.oidc.issuer_private_key]: ../identity-providers/open-id-connect.md#issuer_private_key
|
[identity_providers.oidc.issuer_private_key]: ../identity-providers/open-id-connect.md#issuer_private_key
|
||||||
[identity_providers.oidc.hmac_secret]: ../identity-providers/open-id-connect.md#hmac_secret
|
[identity_providers.oidc.hmac_secret]: ../identity-providers/open-id-connect.md#hmac_secret
|
||||||
|
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
---
|
|
||||||
title: "Guides"
|
|
||||||
description: "Miscellaneous Guides for Configuration."
|
|
||||||
lead: "This section contains miscellaneous guides used in the configuration."
|
|
||||||
date: 2022-06-15T17:51:47+10:00
|
|
||||||
draft: false
|
|
||||||
images: []
|
|
||||||
menu:
|
|
||||||
configuration:
|
|
||||||
parent: "miscellaneous"
|
|
||||||
weight: 199500
|
|
||||||
toc: true
|
|
||||||
---
|
|
||||||
|
|
||||||
## Generating a Random Alphanumeric String
|
|
||||||
|
|
||||||
Some sections of the configuration recommend generating a random string. There are many ways to accomplish this, one
|
|
||||||
possible way on Linux is utilizing the following command which prints a string with a length in characters of
|
|
||||||
`${LENGTH}` to `stdout`. The string will only contain alphanumeric characters.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
LENGTH=64
|
|
||||||
tr -cd '[:alnum:]' < /dev/urandom | fold -w "${LENGTH}" | head -n 1 | tr -d '\n' ; echo
|
|
||||||
```
|
|
||||||
|
|
||||||
## Generating an RSA Keypair
|
|
||||||
|
|
||||||
Some sections of the configuration need an RSA keypair. There are many ways to achieve this, this section explains two
|
|
||||||
such ways.
|
|
||||||
|
|
||||||
### openssl
|
|
||||||
|
|
||||||
The `openssl` command on Linux can be used to generate a RSA 4096 bit keypair:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl genrsa -out private.pem 4096
|
|
||||||
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
|
|
||||||
```
|
|
||||||
|
|
||||||
### authelia
|
|
||||||
|
|
||||||
The __Authelia__ docker container or CLI binary can be used to generate a RSA 4096 bit keypair:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:latest authelia crypto pair rsa generate --bits 4096 --directory /keys
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
authelia crypto pair rsa generate --directory /path/to/keys
|
|
||||||
```
|
|
||||||
|
|
||||||
## Generating an RSA Self-Signed Certificate
|
|
||||||
|
|
||||||
Some sections of the configuration need a certificate and it may be possible to use a self-signed certificate. There are
|
|
||||||
many ways to achieve this, this section explains two such ways.
|
|
||||||
|
|
||||||
### openssl
|
|
||||||
|
|
||||||
The `openssl` command on Linux can be used to generate a RSA 4096 bit self-signed certificate for the domain
|
|
||||||
`example.com`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -subj '/CN=example.com'
|
|
||||||
```
|
|
||||||
|
|
||||||
### authelia
|
|
||||||
|
|
||||||
The __Authelia__ docker container or binary can be used to generate a RSA 4096 bit self-signed certificate for the
|
|
||||||
domain `example.com`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia authelia crypto certificate rsa generate --common-name example.com --directory /keys
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
authelia crypto certificate rsa generate --common-name example.com --directory /path/to/keys
|
|
||||||
```
|
|
|
@ -73,7 +73,7 @@ default_2fa_method: totp
|
||||||
especially for containerized deployments.*
|
especially for containerized deployments.*
|
||||||
|
|
||||||
Defines the secret used to craft JWT tokens leveraged by the identity verification process. This can a random string.
|
Defines the secret used to craft JWT tokens leveraged by the identity verification process. This can a random string.
|
||||||
It's strongly recommended this is a [Random Alphanumeric String](guides.md#generating-a-random-alphanumeric-string) with
|
It's strongly recommended this is a [Random Alphanumeric String](../../reference/guides/generating-secure-values.md/#generating-a-random-alphanumeric-string) with
|
||||||
64 or more characters.
|
64 or more characters.
|
||||||
|
|
||||||
### theme
|
### theme
|
||||||
|
|
|
@ -35,9 +35,9 @@ server:
|
||||||
read: 4096
|
read: 4096
|
||||||
write: 4096
|
write: 4096
|
||||||
timeouts:
|
timeouts:
|
||||||
read: 10s
|
read: 6s
|
||||||
write: 10s
|
write: 6s
|
||||||
idle: 10s
|
idle: 30s
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
@ -130,7 +130,7 @@ security on lower areas of the OSI model. However it required, if you specify bo
|
||||||
[tls certificate](#certificate) options, Authelia will listen for TLS connections.
|
[tls certificate](#certificate) options, Authelia will listen for TLS connections.
|
||||||
|
|
||||||
The key must be generated by the administrator and can be done by following the
|
The key must be generated by the administrator and can be done by following the
|
||||||
[Generating an RSA Self Signed Certificate](../miscellaneous/guides.md#generating-an-rsa-self-signed-certificate)
|
[Generating an RSA Self Signed Certificate](../../reference/guides/generating-secure-values.md#generating-an-rsa-self-signed-certificate)
|
||||||
guide provided a self-signed certificate is fit for purpose. If a self-signed certificate is fit for purpose is beyond
|
guide provided a self-signed certificate is fit for purpose. If a self-signed certificate is fit for purpose is beyond
|
||||||
the scope of the documentation and if it is not fit for purpose we instead recommend generating a certificate signing
|
the scope of the documentation and if it is not fit for purpose we instead recommend generating a certificate signing
|
||||||
request or obtaining a certificate signed by one of the many ACME certificate providers. Methods to achieve this are
|
request or obtaining a certificate signed by one of the many ACME certificate providers. Methods to achieve this are
|
||||||
|
@ -161,11 +161,11 @@ or intermediate certificates. If no item is provided mutual TLS is disabled.
|
||||||
|
|
||||||
{{< confkey type="string" required="no" >}}
|
{{< confkey type="string" required="no" >}}
|
||||||
|
|
||||||
This customizes the value of the Content-Security-Policy header. It will replace all instances of `${NONCE}` with the
|
This customizes the value of the Content-Security-Policy header. It will replace all instances of the below placeholder
|
||||||
nonce value of the Authelia react bundle. This is an advanced option to customize and you should do sufficient research
|
with the nonce value of the Authelia react bundle. This is an advanced option to customize and you should do sufficient
|
||||||
about how browsers utilize and understand this header before attempting to customize it.
|
research about how browsers utilize and understand this header before attempting to customize it.
|
||||||
|
|
||||||
For example, the default CSP template is `default-src 'self'; frame-src 'none'; object-src 'none'; style-src 'self' 'nonce-${NONCE}'; frame-ancestors 'none'; base-uri 'self'`.
|
{{< csp >}}
|
||||||
|
|
||||||
### buffers
|
### buffers
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,80 @@ notifier:
|
||||||
subject: "[Authelia] {title}"
|
subject: "[Authelia] {title}"
|
||||||
startup_check_address: test@authelia.com
|
startup_check_address: test@authelia.com
|
||||||
disable_require_tls: false
|
disable_require_tls: false
|
||||||
|
disable_starttls: false
|
||||||
disable_html_emails: false
|
disable_html_emails: false
|
||||||
tls:
|
tls:
|
||||||
server_name: smtp.example.com
|
server_name: smtp.example.com
|
||||||
skip_verify: false
|
skip_verify: false
|
||||||
minimum_version: TLS1.2
|
minimum_version: TLS1.2
|
||||||
|
maximum_version: TLS1.3
|
||||||
|
certificate_chain: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC5jCCAc6gAwIBAgIRAK4Sj7FiN6PXo/urPfO4E7owDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAPKv3pSyP4ozGEiVLJ14dIWFCEGEgq7WUMI0SZZqQA2ID0L59U/Q
|
||||||
|
/Usyy7uC9gfMUzODTpANtkOjFQcQAsxlR1FOjVBrX5QgjSvXwbQn3DtwMA7XWSl6
|
||||||
|
LuYx2rBYSlMSN5UZQm/RxMtXfLK2b51WgEEYDFi+nECSqKzR4R54eOPkBEWRfvuY
|
||||||
|
91AMjlhpivg8e4JWkq4LVQUKbmiFYwIdK8XQiN4blY9WwXwJFYs5sQ/UYMwBFi0H
|
||||||
|
kWOh7GEjfxgoUOPauIueZSMSlQp7zqAH39N0ZSYb6cS0Npj57QoWZSY3ak87ebcR
|
||||||
|
Nf4rCvZLby7LoN7qYCKxmCaDD3x2+NYpWH8CAwEAAaM1MDMwDgYDVR0PAQH/BAQD
|
||||||
|
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHSITqIQSNzonFl3DzxHPEzr2hp6peo45buAAtu8FZHoA+U7Icfh
|
||||||
|
/ZXjPg7Xz+hgFwM/DTNGXkMWacQA/PaNWvZspgRJf2AXvNbMSs2UQODr7Tbv+Fb4
|
||||||
|
lyblmMUNYFMCFVAMU0eIxXAFq2qcwv8UMcQFT0Z/35s6PVOakYnAGGQjTfp5Ljuq
|
||||||
|
wsdc/xWmM0cHWube6sdRRUD7SY20KU/kWzl8iFO0VbSSrDf1AlEhnLEkp1SPaxXg
|
||||||
|
OdBnl98MeoramNiJ7NT6Jnyb3zZ578fjaWfThiBpagItI8GZmG4s4Ovh2JbheN8i
|
||||||
|
ZsjNr9jqHTjhyLVbDRlmJzcqoj4JhbKs6/I^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDBDCCAeygAwIBAgIRALJsPg21kA0zY4F1wUCIuoMwDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAMXHBvVxUzYk0u34/DINMSF+uiOekKOAjOrC6Mi9Ww8ytPVO7t2S
|
||||||
|
zfTvM+XnEJqkFQFgimERfG/eGhjF9XIEY6LtnXe8ATvOK4nTwdufzBaoeQu3Gd50
|
||||||
|
5VXr6OHRo//ErrGvFXwP3g8xLePABsi/fkH3oDN+ztewOBMDzpd+KgTrk8ysv2ou
|
||||||
|
kNRMKFZZqASvCgv0LD5KWvUCnL6wgf1oTXG7aztduA4oSkUP321GpOmBC5+5ElU7
|
||||||
|
ysoRzvD12o9QJ/IfEaulIX06w9yVMo60C/h6A3U6GdkT1SiyTIqR7v7KU/IWd/Qi
|
||||||
|
Lfftcj91VhCmJ73Meff2e2S2PrpjdXbG5FMCAwEAAaNTMFEwDgYDVR0PAQH/BAQD
|
||||||
|
AgKkMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
|
||||||
|
Z7AtA3mzFc0InSBA5fiMfeLXA3owDQYJKoZIhvcNAQELBQADggEBAEE5hm1mtlk/
|
||||||
|
kviCoHH4evbpw7rxPxDftIQlqYTtvMM4eWY/6icFoSZ4fUHEWYyps8SsPu/8f2tf
|
||||||
|
71LGgZn0FdHi1QU2H8m0HHK7TFw+5Q6RLrLdSyk0PItJ71s9en7r8pX820nAFEHZ
|
||||||
|
HkOSfJZ7B5hFgUDkMtVM6bardXAhoqcMk4YCU96e9d4PB4eI+xGc+mNuYvov3RbB
|
||||||
|
D0s8ICyojeyPVLerz4wHjZu68Z5frAzhZ68YbzNs8j2fIBKKHkHyLG1iQyF+LJVj
|
||||||
|
2PjCP+auJsj6fQQpMGoyGtpLcSDh+ptcTngUD8JsWipzTCjmaNqdPHAOYmcgtf4b
|
||||||
|
qocikt3WAdU^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
private_key: |
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEA8q/elLI/ijMYSJUsnXh0hYUIQYSCrtZQwjRJlmpADYgPQvn1
|
||||||
|
T9D9SzLLu4L2B8xTM4NOkA22Q6MVBxACzGVHUU6NUGtflCCNK9fBtCfcO3AwDtdZ
|
||||||
|
KXou5jHasFhKUxI3lRlCb9HEy1d8srZvnVaAQRgMWL6cQJKorNHhHnh44+QERZF+
|
||||||
|
+5j3UAyOWGmK+Dx7glaSrgtVBQpuaIVjAh0rxdCI3huVj1bBfAkVizmxD9RgzAEW
|
||||||
|
LQeRY6HsYSN/GChQ49q4i55lIxKVCnvOoAff03RlJhvpxLQ2mPntChZlJjdqTzt5
|
||||||
|
txE1/isK9ktvLsug3upgIrGYJoMPfHb41ilYfwIDAQABAoIBAQDTOdFf2JjHH1um
|
||||||
|
aPgRAvNf9v7Nj5jytaRKs5nM6iNf46ls4QPreXnMhqSeSwj6lpNgBYxOgzC9Q+cc
|
||||||
|
Y4ob/paJJPaIJTxmP8K/gyWcOQlNToL1l+eJ20eQoZm23NGr5fIsunSBwLEpTrdB
|
||||||
|
ENqqtcwhW937K8Pxy/Q1nuLyU2bc6Tn/ivLozc8n27dpQWWKh8537VY7ancIaACr
|
||||||
|
LJJLYxKqhQpjtBWAyCDvZQirnAOm9KnvIHaGXIswCZ4Xbsu0Y9NL+woARPyRVQvG
|
||||||
|
jfxy4EmO9s1s6y7OObSukwKDSNihAKHx/VIbvVWx8g2Lv5fGOa+J2Y7o9Qurs8t5
|
||||||
|
BQwMTt0BAoGBAPUw5Z32EszNepAeV3E2mPFUc5CLiqAxagZJuNDO2pKtyN29ETTR
|
||||||
|
Ma4O1cWtGb6RqcNNN/Iukfkdk27Q5nC9VJSUUPYelOLc1WYOoUf6oKRzE72dkMQV
|
||||||
|
R4bf6TkjD+OVR17fAfkswkGahZ5XA7j48KIQ+YC4jbnYKSxZTYyKPjH/AoGBAP1i
|
||||||
|
tqXt36OVlP+y84wWqZSjMelBIVa9phDVGJmmhz3i1cMni8eLpJzWecA3pfnG6Tm9
|
||||||
|
ze5M4whASleEt+M00gEvNaU9ND+z0wBfi+/DwJYIbv8PQdGrBiZFrPhTPjGQUldR
|
||||||
|
lXccV2meeLZv7TagVxSi3DO6dSJfSEHyemd5j9mBAoGAX8Hv+0gOQZQCSOTAq8Nx
|
||||||
|
6dZcp9gHlNaXnMsP9eTDckOSzh636JPGvj6m+GPJSSbkURUIQ3oyokMNwFqvlNos
|
||||||
|
fTaLhAOfjBZI9WnDTTQxpugWjphJ4HqbC67JC/qIiw5S6FdaEvGLEEoD4zoChywZ
|
||||||
|
9oGAn+fz2d/0/JAH/FpFPgsCgYEAp/ipZgPzziiZ9ov1wbdAQcWRj7RaWnssPFpX
|
||||||
|
jXwEiXT3CgEMO4MJ4+KWIWOChrti3qFBg6i6lDyyS6Qyls7sLFbUdC7HlTcrOEMe
|
||||||
|
rBoTcCI1GqZNlqWOVQ65ZIEiaI7o1vPBZo2GMQEZuq8mDKFsOMThvvTrM5cAep84
|
||||||
|
n6HJR4ECgYABWcbsSnr0MKvVth/inxjbKapbZnp2HUCuw87Ie5zK2Of/tbC20wwk
|
||||||
|
yKw3vrGoE3O1t1g2m2tn8UGGASeZ842jZWjIODdSi5+icysQGuULKt86h/woz2SQ
|
||||||
|
27GoE2i5mh6Yez6VAYbUuns3FcwIsMyWLq043Tu2DNkx9ijOOAuQzw^invalid..
|
||||||
|
DO NOT USE==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
@ -60,7 +129,7 @@ The port the SMTP service is listening on.
|
||||||
|
|
||||||
A connection is securely established with TLS after a succesful STARTTLS negotiation.
|
A connection is securely established with TLS after a succesful STARTTLS negotiation.
|
||||||
|
|
||||||
[Port 465 is an exception][docs-security-smtp-port] when supported by the mail server as a `submissions` service port.
|
[Port 465 is an exception][docs-security-smtp-port] when supported by the mail server as a `submissions` service port.
|
||||||
STARTTLS negotiation is not required for this port, the connection is implicitly established with TLS.
|
STARTTLS negotiation is not required for this port, the connection is implicitly established with TLS.
|
||||||
|
|
||||||
[docs-security-smtp-port]: ../../overview/security/measures.md#smtp-ports
|
[docs-security-smtp-port]: ../../overview/security/measures.md#smtp-ports
|
||||||
|
@ -87,7 +156,7 @@ especially for containerized deployments.*
|
||||||
The password paired with the [username](#username) sent for authentication with the SMTP server.
|
The password paired with the [username](#username) sent for authentication with the SMTP server.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters and the user password is changed to this value.
|
characters and the user password is changed to this value.
|
||||||
|
|
||||||
### sender
|
### sender
|
||||||
|
@ -132,6 +201,18 @@ to leave this as is, but you can customize it if you have issues or you desire t
|
||||||
For security reasons the default settings for Authelia require the SMTP connection is encrypted by TLS. See [security]
|
For security reasons the default settings for Authelia require the SMTP connection is encrypted by TLS. See [security]
|
||||||
for more information. This option disables this measure (not recommended).
|
for more information. This option disables this measure (not recommended).
|
||||||
|
|
||||||
|
### disable_starttls
|
||||||
|
|
||||||
|
{{< confkey type="boolean" default="false" required="no" >}}
|
||||||
|
|
||||||
|
Some SMTP servers ignore SMTP specifications and claim to support STARTTLS when they in fact do not.
|
||||||
|
For security reasons Authelia refuses to send messages to these servers.
|
||||||
|
This option disables this measure and is enabled *__AT YOUR OWN RISK__*. It's *__strongly recommended__*
|
||||||
|
that instead of enabling this option you either fix the issue with the SMTP server's configuration or
|
||||||
|
have the administrators of the server fix it. If the issue can't be fixed by configuration we recommend
|
||||||
|
lodging an issue with the authors of the SMTP server.
|
||||||
|
See [security] for more information.
|
||||||
|
|
||||||
### disable_html_emails
|
### disable_html_emails
|
||||||
|
|
||||||
{{< confkey type="boolean" default="false" required="no" >}}
|
{{< confkey type="boolean" default="false" required="no" >}}
|
||||||
|
|
|
@ -129,10 +129,39 @@ instead you should tweak the `server_name` option, and the global option
|
||||||
|
|
||||||
{{< confkey type="string" default="TLS1.2" required="no" >}}
|
{{< confkey type="string" default="TLS1.2" required="no" >}}
|
||||||
|
|
||||||
The key `minimum_version` controls the minimum TLS version Authelia will use when opening TLS connections.
|
Controls the minimum TLS version Authelia will use when performing TLS handshakes.
|
||||||
The possible values are `TLS1.3`, `TLS1.2`, `TLS1.1`, `TLS1.0`. Anything other than `TLS1.3` or `TLS1.2`
|
The possible values are `TLS1.3`, `TLS1.2`, `TLS1.1`, `TLS1.0`, `SSL3.0`. Anything other than `TLS1.3` or `TLS1.2`
|
||||||
are very old and deprecated. You should avoid using these and upgrade your backend service instead of decreasing
|
are very old and deprecated. You should avoid using these and upgrade your backend service instead of decreasing
|
||||||
this value.
|
this value. At the time of this writing `SSL3.0` will always produce errors.
|
||||||
|
|
||||||
|
### maximum_version
|
||||||
|
|
||||||
|
{{< confkey type="string" default="TLS1.3" required="no" >}}
|
||||||
|
|
||||||
|
Controls the maximum TLS version Authelia will use when performing TLS handshakes.
|
||||||
|
The possible values are `TLS1.3`, `TLS1.2`, `TLS1.1`, `TLS1.0`, `SSL3.0`. Anything other than `TLS1.3` or `TLS1.2`
|
||||||
|
are very old and deprecated. You should avoid using these and upgrade your backend service instead of decreasing
|
||||||
|
this value. At the time of this writing `SSL3.0` will always produce errors.
|
||||||
|
|
||||||
|
### certificate_chain
|
||||||
|
|
||||||
|
{{< confkey type="string" required="no" >}}
|
||||||
|
|
||||||
|
The certificate chain/bundle to be used with the [private_key](#private_key) to perform mutual TLS authentication with
|
||||||
|
the server.
|
||||||
|
|
||||||
|
The value must be one or more certificates encoded in the DER base64 ([RFC4648]) encoded PEM format.
|
||||||
|
|
||||||
|
### private_key
|
||||||
|
|
||||||
|
{{< confkey type="string" required="yes" >}}
|
||||||
|
|
||||||
|
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
|
||||||
|
especially for containerized deployments.*
|
||||||
|
|
||||||
|
The private key to be used with the [certificate_chain](#certificate_chain) for mutual TLS authentication.
|
||||||
|
|
||||||
|
The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format.
|
||||||
|
|
||||||
## Server Buffers
|
## Server Buffers
|
||||||
|
|
||||||
|
@ -152,7 +181,7 @@ Configures the maximum response size. The default of 4096 is generally sufficien
|
||||||
|
|
||||||
### read
|
### read
|
||||||
|
|
||||||
{{< confkey type="duration" default="2s" required="no" >}}
|
{{< confkey type="duration" default="6s" required="no" >}}
|
||||||
|
|
||||||
*__Note:__ This setting uses the [duration notation format](#duration-notation-format). Please see the
|
*__Note:__ This setting uses the [duration notation format](#duration-notation-format). Please see the
|
||||||
[common options](#duration-notation-format) documentation for information on this format.*
|
[common options](#duration-notation-format) documentation for information on this format.*
|
||||||
|
@ -161,7 +190,7 @@ Configures the server read timeout.
|
||||||
|
|
||||||
### write
|
### write
|
||||||
|
|
||||||
{{< confkey type="duration" default="2s" required="no" >}}
|
{{< confkey type="duration" default="6s" required="no" >}}
|
||||||
|
|
||||||
*__Note:__ This setting uses the [duration notation format](#duration-notation-format). Please see the
|
*__Note:__ This setting uses the [duration notation format](#duration-notation-format). Please see the
|
||||||
[common options](#duration-notation-format) documentation for information on this format.*
|
[common options](#duration-notation-format) documentation for information on this format.*
|
||||||
|
|
|
@ -42,6 +42,17 @@ access_control:
|
||||||
- HEAD
|
- HEAD
|
||||||
resources:
|
resources:
|
||||||
- '^/api.*'
|
- '^/api.*'
|
||||||
|
query:
|
||||||
|
- - operator: 'present'
|
||||||
|
key: 'secure'
|
||||||
|
- operator: 'absent'
|
||||||
|
key: 'insecure'
|
||||||
|
- - operator: 'pattern'
|
||||||
|
key: 'token'
|
||||||
|
value: '^(abc123|zyx789)$'
|
||||||
|
- operator: 'not pattern'
|
||||||
|
key: 'random'
|
||||||
|
value: '^(1|2)$'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
@ -51,11 +62,11 @@ access_control:
|
||||||
{{< confkey type="string" default="deny" required="no" >}}
|
{{< confkey type="string" default="deny" required="no" >}}
|
||||||
|
|
||||||
The default [policy](#policies) defines the policy applied if no [rules](#rules) section apply to the information known
|
The default [policy](#policies) defines the policy applied if no [rules](#rules) section apply to the information known
|
||||||
about the request. It is recommended that this is configured to [deny](#deny) for security reasons. Sites which you do
|
about the request. It is recommended that this is configured to [deny] for security reasons. Sites which you do
|
||||||
not wish to secure at all with Authelia should not be configured in your reverse proxy to perform authentication with
|
not wish to secure at all with Authelia should not be configured in your reverse proxy to perform authentication with
|
||||||
Authelia at all for performance reasons.
|
Authelia at all for performance reasons.
|
||||||
|
|
||||||
See [Policies](#policies) for more information.
|
See the [policies] section for more information.
|
||||||
|
|
||||||
### networks (global)
|
### networks (global)
|
||||||
|
|
||||||
|
@ -66,8 +77,8 @@ The main/global networks section contains a list of networks with a name label t
|
||||||
complicated network related configuration a lot cleaner and easier to read.
|
complicated network related configuration a lot cleaner and easier to read.
|
||||||
|
|
||||||
This section has two options, `name` and `networks`. Where the `networks` section is a list of IP addresses in CIDR
|
This section has two options, `name` and `networks`. Where the `networks` section is a list of IP addresses in CIDR
|
||||||
notation and where `name` is a friendly name to label the collection of networks for reuse in the [networks](#networks)
|
notation and where `name` is a friendly name to label the collection of networks for reuse in the [networks] section of
|
||||||
section of the [rules](#rules) section below.
|
the [rules] section below.
|
||||||
|
|
||||||
This configuration option *does nothing* by itself, it's only useful if you use these aliases in the [rules](#networks)
|
This configuration option *does nothing* by itself, it's only useful if you use these aliases in the [rules](#networks)
|
||||||
section below.
|
section below.
|
||||||
|
@ -77,7 +88,7 @@ section below.
|
||||||
{{< confkey type="list" required="no" >}}
|
{{< confkey type="list" required="no" >}}
|
||||||
|
|
||||||
The rules have many configuration options. A rule matches when all criteria of the rule match the request excluding the
|
The rules have many configuration options. A rule matches when all criteria of the rule match the request excluding the
|
||||||
`policy` which is the [policy](#policies) applied to the request.
|
[policy] which is the [policy](#policies) applied to the request.
|
||||||
|
|
||||||
A rule defines two primary things:
|
A rule defines two primary things:
|
||||||
|
|
||||||
|
@ -86,29 +97,29 @@ A rule defines two primary things:
|
||||||
|
|
||||||
The criteria is broken into several parts:
|
The criteria is broken into several parts:
|
||||||
|
|
||||||
* [domain](#domain): domain or list of domains targeted by the request.
|
* [domain]: domain or list of domains targeted by the request.
|
||||||
* [domain_regex](#domain_regex): regex form of [domain](#domain).
|
* [domain_regex]: regex form of [domain].
|
||||||
* [resources](#resources): pattern or list of patterns that the path should match.
|
* [resources]: pattern or list of patterns that the path should match.
|
||||||
* [subject](#subject): the user or group of users to define the policy for.
|
* [subject]: the user or group of users to define the policy for.
|
||||||
* [networks](#networks): the network addresses, ranges (CIDR notation) or groups from where the request originates.
|
* [networks]: the network addresses, ranges (CIDR notation) or groups from where the request originates.
|
||||||
* [methods](#methods): the http methods used in the request.
|
* [methods]: the http methods used in the request.
|
||||||
|
|
||||||
A rule is matched when all criteria of the rule match. Rules are evaluated in sequential order, and the first rule that
|
A rule is matched when all criteria of the rule match. Rules are evaluated in sequential order as per
|
||||||
is a match for a given request is the rule applied; subsequent rules have *no effect*. This is particularly
|
[Rule Matching Concept 1]. It's *__strongly recommended__* that individuals read the [Rule Matching](#rule-matching)
|
||||||
__important__ for bypass rules. Bypass rules should generally appear near the top of the rules list. However you need to
|
section.
|
||||||
carefully evaluate your rule list __in order__ to see which rule matches a particular scenario. A comprehensive
|
|
||||||
understanding of how rules apply is also recommended.
|
[rules]: #rules
|
||||||
|
|
||||||
#### domain
|
#### domain
|
||||||
|
|
||||||
{{< confkey type="list(string)" required="yes" >}}
|
{{< confkey type="list(string)" required="yes" >}}
|
||||||
|
|
||||||
*__Required:__ This criteria and/or the [domain_regex](#domain_regex) criteria are required.*
|
*__Required:__ This criteria and/or the [domain_regex] criteria are required.*
|
||||||
|
|
||||||
This criteria matches the domain name and has two methods of configuration, either as a single string or as a list of
|
This criteria matches the domain name and has two methods of configuration, either as a single string or as a list of
|
||||||
strings. When it's a list of strings the rule matches when __any__ of the domains in the list match the request domain.
|
strings. When it's a list of strings the rule matches when __any__ of the domains in the list match the request domain.
|
||||||
When used in conjunction with [domain_regex](#domain_regex) the rule will match when either the [domain](#domain) or the
|
When used in conjunction with [domain_regex] the rule will match when either the [domain] or the [domain_regex] criteria
|
||||||
[domain_regex](#domain_regex) criteria matches.
|
matches.
|
||||||
|
|
||||||
Rules may start with a few different wildcards:
|
Rules may start with a few different wildcards:
|
||||||
|
|
||||||
|
@ -117,9 +128,8 @@ Rules may start with a few different wildcards:
|
||||||
string __must__ be quoted like `"*.example.com"`.
|
string __must__ be quoted like `"*.example.com"`.
|
||||||
* The user wildcard is `{user}.`, which when in front of a domain dynamically matches the username of the user. For
|
* The user wildcard is `{user}.`, which when in front of a domain dynamically matches the username of the user. For
|
||||||
example `{user}.example.com` would match `fred.example.com` if the user logged in was named `fred`. *__Warning:__ this is
|
example `{user}.example.com` would match `fred.example.com` if the user logged in was named `fred`. *__Warning:__ this is
|
||||||
officially deprecated as the [domain_regex](#domain_regex) criteria completely replaces the functionality in a much
|
officially deprecated as the [domain_regex] criteria completely replaces the functionality in a much more useful
|
||||||
more useful way. It is strongly recommended you do not use this as it will be removed in a future version, most likely
|
way. It is strongly recommended you do not use this as it will be removed in a future version, most likely v5.0.0.*
|
||||||
v5.0.0.*
|
|
||||||
* The group wildcard is `{group}.`, which when in front of a domain dynamically matches if the logged in user has the
|
* The group wildcard is `{group}.`, which when in front of a domain dynamically matches if the logged in user has the
|
||||||
group in that location. For example `{group}.example.com` would match `admins.example.com` if the user logged in was
|
group in that location. For example `{group}.example.com` would match `admins.example.com` if the user logged in was
|
||||||
in the following groups `admins,users,people` because `admins` is in the list.
|
in the following groups `admins,users,people` because `admins` is in the list.
|
||||||
|
@ -129,6 +139,8 @@ or subdomains of that domain. This is because a website can only write cookies f
|
||||||
theoretically possible for us to do this with multiple domains however we would have to be security conscious in our
|
theoretically possible for us to do this with multiple domains however we would have to be security conscious in our
|
||||||
implementation, and it is not currently a priority.
|
implementation, and it is not currently a priority.
|
||||||
|
|
||||||
|
[domain]: #domain
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
*Single domain of `*.example.com` matched. All rules in this list are effectively the same rule just expressed in
|
*Single domain of `*.example.com` matched. All rules in this list are effectively the same rule just expressed in
|
||||||
|
@ -158,7 +170,7 @@ access_control:
|
||||||
policy: bypass
|
policy: bypass
|
||||||
```
|
```
|
||||||
|
|
||||||
*Multiple domains matched either via a static domain or via a [domain_regex](#domain_regex). This rule will match
|
*Multiple domains matched either via a static domain or via a [domain_regex]. This rule will match
|
||||||
either `apple.example.com`, `pub-data.example.com`, or `img-data.example.com`.*
|
either `apple.example.com`, `pub-data.example.com`, or `img-data.example.com`.*
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
@ -173,20 +185,20 @@ access_control:
|
||||||
|
|
||||||
{{< confkey type="list(string)" required="yes" >}}
|
{{< confkey type="list(string)" required="yes" >}}
|
||||||
|
|
||||||
*__Required:__ This criteria and/or the [domain](#domain) criteria are required.*
|
*__Required:__ This criteria and/or the [domain] criteria are required.*
|
||||||
|
|
||||||
*__Important Note:__ If you intend to use this criteria with a bypass rule please read
|
*__Important Note:__ If you intend to use this criteria with a bypass rule please read [Rule Matching Concept 2].*
|
||||||
[bypass and subjects](#bypass-and-user-identity) before doing so.*
|
|
||||||
|
|
||||||
*__Important Note:__ to utilize regex you must escape it properly. See
|
*__Important Note:__ to utilize regex you must escape it properly. See
|
||||||
[regular expressions](../prologue/common.md#regular-expressions) for more information.*
|
[regular expressions](../prologue/common.md#regular-expressions) for more information.*
|
||||||
|
|
||||||
This criteria matches the domain name and has two methods of configuration, either as a single string or as a list of
|
This criteria matches the domain name and has two methods of configuration, either as a single string or as a list of
|
||||||
strings. When it's a list of strings the rule matches when __any__ of the domains in the list match the request domain.
|
strings. When it's a list of strings the rule matches when __any__ of the domains in the list match the request domain.
|
||||||
When used in conjunction with [domain](#domain) the rule will match when either the [domain](#domain) or the
|
When used in conjunction with [domain] the rule will match when either the [domain] or the [domain_regex] criteria matches.
|
||||||
[domain_regex](#domain_regex) criteria matches.
|
|
||||||
|
|
||||||
In addition to standard regex patterns this criteria can match some [Named Regex Groups](#named-regex-groups).
|
In addition to standard regex patterns this criteria can match some [Named Regex Groups].
|
||||||
|
|
||||||
|
[domain_regex]: #domain_regex
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
|
@ -222,15 +234,14 @@ access_control:
|
||||||
The specific [policy](#policies) to apply to the selected rule. This is not criteria for a match, this is the action to
|
The specific [policy](#policies) to apply to the selected rule. This is not criteria for a match, this is the action to
|
||||||
take when a match is made.
|
take when a match is made.
|
||||||
|
|
||||||
|
[policy]: #policy
|
||||||
|
|
||||||
#### subject
|
#### subject
|
||||||
|
|
||||||
{{< confkey type="list(list(string))" required="no" >}}
|
{{< confkey type="list(list(string))" required="no" >}}
|
||||||
|
|
||||||
*__Note:__ this rule criteria __may not__ be used for the `bypass` policy the minimum required authentication level to
|
*__Note:__ this rule criteria __may not__ be used for the [bypass] policy the minimum required authentication level to
|
||||||
identify the subject is `one_factor`. We have taken an opinionated stance on preventing this configuration as it could
|
identify the subject is [one_factor]. See [Rule Matching Concept 2] for more information.*
|
||||||
result in problematic security scenarios with badly thought out configurations and cannot see a likely configuration
|
|
||||||
scenario that would require users to do this. If you have a scenario in mind please open an
|
|
||||||
[issue](https://github.com/authelia/authelia/issues/new) on GitHub.*
|
|
||||||
|
|
||||||
This criteria matches identifying characteristics about the subject. Currently this is either user or groups the user
|
This criteria matches identifying characteristics about the subject. Currently this is either user or groups the user
|
||||||
belongs to. This allows you to effectively control exactly what each user is authorized to access or to specifically
|
belongs to. This allows you to effectively control exactly what each user is authorized to access or to specifically
|
||||||
|
@ -241,6 +252,8 @@ The format of this rule is unique in as much as it is a list of lists. The logic
|
||||||
`OR` and `AND` logic. The first level of the list defines the `OR` logic, and the second level defines the `AND` logic.
|
`OR` and `AND` logic. The first level of the list defines the `OR` logic, and the second level defines the `AND` logic.
|
||||||
Additionally each level of these lists does not have to be explicitly defined.
|
Additionally each level of these lists does not have to be explicitly defined.
|
||||||
|
|
||||||
|
[subject]: #subject
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
*Matches when the user has the username `john`, __or__ the user is in the groups `admin` __and__ `app-name`, __or__ the
|
*Matches when the user has the username `john`, __or__ the user is in the groups `admin` __and__ `app-name`, __or__ the
|
||||||
|
@ -306,6 +319,8 @@ relevant methods are listed in this table:
|
||||||
| [RFC5789] | PATCH | [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) |
|
| [RFC5789] | PATCH | [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) |
|
||||||
| [RFC4918] | PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK | |
|
| [RFC4918] | PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK | |
|
||||||
|
|
||||||
|
[methods]: #methods
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
*Bypass `OPTIONS` requests to the `example.com` domain.*
|
*Bypass `OPTIONS` requests to the `example.com` domain.*
|
||||||
|
@ -341,6 +356,8 @@ privileges when a user is on the local networks.
|
||||||
There are a large number of scenarios regarding networks and the order of the rules. This provides a lot of flexibility
|
There are a large number of scenarios regarding networks and the order of the rules. This provides a lot of flexibility
|
||||||
for administrators to tune the security to their specific needs if desired.
|
for administrators to tune the security to their specific needs if desired.
|
||||||
|
|
||||||
|
[networks]: #networks
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
*Require [two_factor](#two_factor) for all clients other than internal clients and `112.134.145.167`. The first two
|
*Require [two_factor](#two_factor) for all clients other than internal clients and `112.134.145.167`. The first two
|
||||||
|
@ -394,6 +411,8 @@ It's important when configuring resource rules that you enclose them in quotes o
|
||||||
with escaping the expressions. Failure to do so may prevent Authelia from starting. It's technically optional but will
|
with escaping the expressions. Failure to do so may prevent Authelia from starting. It's technically optional but will
|
||||||
likely save you a lot of time if you do it for all resource rules.
|
likely save you a lot of time if you do it for all resource rules.
|
||||||
|
|
||||||
|
[resources]: #resources
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
*Applies the [bypass](#bypass) policy when the domain is `app.example.com` and the url is `/api`, or starts with either
|
*Applies the [bypass](#bypass) policy when the domain is `app.example.com` and the url is `/api`, or starts with either
|
||||||
|
@ -408,59 +427,176 @@ access_control:
|
||||||
- '^/api([/?].*)?$'
|
- '^/api([/?].*)?$'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### query
|
||||||
|
|
||||||
|
{{< confkey type="list(list(object))" required="no" >}}
|
||||||
|
|
||||||
|
The query criteria is an advanced criteria which can allow configuration of rules that match specific query argument
|
||||||
|
keys against various rules. It's recommended to use [resources](#resources) rules instead for basic needs.
|
||||||
|
|
||||||
|
The format of this rule is unique in as much as it is a list of lists. The logic behind this format is to allow for both
|
||||||
|
`OR` and `AND` logic. The first level of the list defines the `OR` logic, and the second level defines the `AND` logic.
|
||||||
|
Additionally each level of these lists does not have to be explicitly defined.
|
||||||
|
|
||||||
|
##### key
|
||||||
|
|
||||||
|
{{< confkey type="string" required="yes" >}}
|
||||||
|
|
||||||
|
The query argument key to check.
|
||||||
|
|
||||||
|
##### value
|
||||||
|
|
||||||
|
{{< confkey type="string" required="situational" >}}
|
||||||
|
|
||||||
|
The value to match against. This is required unless the operator is `absent` or `present`. It's recommended this value
|
||||||
|
is always quoted as per the examples.
|
||||||
|
|
||||||
|
##### operator
|
||||||
|
|
||||||
|
{{< confkey type="string" required="situational" >}}
|
||||||
|
|
||||||
|
The rule operator for this rule. Valid operators can be found in the
|
||||||
|
[Rule Operators](../../reference/guides/rule-operators.md#operators) reference guide.
|
||||||
|
|
||||||
|
If [key](#key) and [value](#value) are specified this defaults to `equal`, otherwise if [key](#key) is specified it
|
||||||
|
defaults to `present`.
|
||||||
|
|
||||||
|
|
||||||
|
##### Examples
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
access_control:
|
||||||
|
rules:
|
||||||
|
- domain: app.example.com
|
||||||
|
policy: bypass
|
||||||
|
query:
|
||||||
|
- - operator: 'present'
|
||||||
|
key: 'secure'
|
||||||
|
- operator: 'absent'
|
||||||
|
key: 'insecure'
|
||||||
|
- - operator: 'pattern'
|
||||||
|
key: 'token'
|
||||||
|
value: '^(abc123|zyx789)$'
|
||||||
|
- operator: 'not pattern'
|
||||||
|
key: 'random'
|
||||||
|
value: '^(1|2)$'
|
||||||
|
```
|
||||||
|
|
||||||
## Policies
|
## Policies
|
||||||
|
|
||||||
The policy of the first matching rule in the configured list decides the policy applied to the request, if no rule
|
The policy of the first matching rule in the configured list decides the policy applied to the request, if no rule
|
||||||
matches the request the [default_policy](#default_policy) is applied.
|
matches the request the [default_policy](#default_policy) is applied.
|
||||||
|
|
||||||
|
[policies]: #policies
|
||||||
|
|
||||||
### deny
|
### deny
|
||||||
|
|
||||||
This is the policy applied by default, and is what we recommend as the default policy for all installs. Its effect
|
This is the policy applied by default, and is what we recommend as the default policy for all installs. Its effect
|
||||||
is literally to deny the user access to the resource. Additionally you can use this policy to conditionally deny
|
is literally to deny the user access to the resource. Additionally you can use this policy to conditionally deny
|
||||||
access in desired situations. Examples include denying access to an API that has no authentication mechanism built in.
|
access in desired situations. Examples include denying access to an API that has no authentication mechanism built in.
|
||||||
|
|
||||||
|
[deny]: #deny
|
||||||
|
|
||||||
### bypass
|
### bypass
|
||||||
|
|
||||||
This policy skips all authentication and allows anyone to use the resource. This policy is not available with a rule
|
This policy skips all authentication and allows anyone to use the resource. This policy is not available with a rule
|
||||||
that includes a [subject](#subject) restriction because the minimum authentication level required to obtain information
|
that includes a [subject] restriction because the minimum authentication level required to obtain information
|
||||||
about the subject is [one_factor](#one_factor).
|
about the subject is [one_factor]. See [Rule Matching Concept 2] for more information.
|
||||||
|
|
||||||
#### bypass and user identity
|
[bypass]: #bypass
|
||||||
|
|
||||||
The [bypass](#bypass) policy cannot be used when the rule uses a criteria that requires we know the users identity. This
|
|
||||||
means:
|
|
||||||
|
|
||||||
* If the rule defines [subjects](#subject) criteria
|
|
||||||
* If the rule defines [domain regex](#domain_regex) criteria which contains either the user or group named match groups
|
|
||||||
|
|
||||||
This is because these criteria types require knowing who the user is in order to determine if their identity matches the
|
|
||||||
request. This information can only be known after 1FA, which means the minimum policy that can be used logically is
|
|
||||||
[one_factor](#one_factor).
|
|
||||||
|
|
||||||
### one_factor
|
### one_factor
|
||||||
|
|
||||||
This policy requires the user at minimum complete 1FA successfully (username and password). This means if they have
|
This policy requires the user at minimum complete 1FA successfully (username and password). This means if they have
|
||||||
performed 2FA then they will be allowed to access the resource.
|
performed 2FA then they will be allowed to access the resource.
|
||||||
|
|
||||||
|
[one_factor]: #one_factor
|
||||||
|
|
||||||
### two_factor
|
### two_factor
|
||||||
|
|
||||||
This policy requires the user to complete 2FA successfully. This is currently the highest level of authentication
|
This policy requires the user to complete 2FA successfully. This is currently the highest level of authentication
|
||||||
policy available.
|
policy available.
|
||||||
|
|
||||||
|
[two_factor]: #two_factor
|
||||||
|
|
||||||
|
## Rule Matching
|
||||||
|
|
||||||
|
There are two important concepts to understand when it comes to rule matching. This section covers these concepts.
|
||||||
|
|
||||||
|
You can easily evaluate if your access control rules section matches a given request, and why it doesn't match using the
|
||||||
|
[authelia access-control check-policy](../../reference/cli/authelia/authelia_access-control_check-policy.md) command.
|
||||||
|
|
||||||
|
### Rule Matching Concept 1: Sequential Order
|
||||||
|
|
||||||
|
Rules are matched in sequential order. The first entry in the list where all criteria match is the rule which is applied.
|
||||||
|
Some rule criteria additionally allow for a list of criteria, when one of these criteria in the list match a request that
|
||||||
|
criteria is considered a match for that specific rule.
|
||||||
|
|
||||||
|
This is particularly __important__ for bypass rules. Bypass rules should generally appear near the top of the rules
|
||||||
|
list. However you need to carefully evaluate your rule list __in order__ to see which rule matches a particular
|
||||||
|
scenario. A comprehensive understanding of how rules apply is also recommended.
|
||||||
|
|
||||||
|
For example the following rule will consider requests for either `example.com` or any subdomain of `example.com` a match
|
||||||
|
if they have a path of exactly `/api` or if they start with `/api/`. This means that the second rule for
|
||||||
|
`app.example.com` will not be considered if the request is to `https://app.example.com/api` because the first rule is
|
||||||
|
a match for that request.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- domains:
|
||||||
|
- 'example.com'
|
||||||
|
- '*.example.com'
|
||||||
|
policy: bypass
|
||||||
|
resources:
|
||||||
|
- '^/api$'
|
||||||
|
- '^/api/'
|
||||||
|
- domains:
|
||||||
|
- 'app.example.com'
|
||||||
|
policy: two_factor
|
||||||
|
```
|
||||||
|
|
||||||
|
[Rule Matching Concept 1]: #rule-matching-concept-1-sequential-order
|
||||||
|
|
||||||
|
### Rule Matching Concept 2: Subject Criteria Requires Authentication
|
||||||
|
|
||||||
|
Rules that have subject reliant elements require authentication to determine if they match. Due to this these rules
|
||||||
|
must not be used with the [bypass] policy. The criteria which have subject reliant elements are:
|
||||||
|
|
||||||
|
* The [subject] criteria itself
|
||||||
|
* The [domain_regex] criteria when it contains the [Named Regex Groups].
|
||||||
|
|
||||||
|
In addition if the rule has a subject criteria but all other criteria match then the user will be immediately forwarded
|
||||||
|
for authentication if no prior rules match the request per [Rule Matching Concept 1]. This means if you have two
|
||||||
|
identical rules, and one of them has a subject based reliant criteria, and the other one is a [bypass] rule then the
|
||||||
|
[bypass] rule should generally come first.
|
||||||
|
|
||||||
|
[Rule Matching Concept 2]: #rule-matching-concept-2-subject-criteria-requires-authentication
|
||||||
|
|
||||||
## Named Regex Groups
|
## Named Regex Groups
|
||||||
|
|
||||||
Some criteria allow matching named regex groups. These are the groups we accept:
|
Some criteria allow matching named regex groups. These are the groups we accept:
|
||||||
|
|
||||||
| Group Name | Match Value |
|
| Group Name | Match Value | Match Type |
|
||||||
|:----------:|:-----------------:|
|
|:----------:|:-----------:|:-----------:|
|
||||||
| User | username |
|
| User | username | Equals |
|
||||||
| Group | groups (contains) |
|
| Group | groups | Has (Equal) |
|
||||||
|
|
||||||
For the group name `Group` the regex pattern matches if the user has the specific group name matching the pattern. Both
|
Named regex groups are represented with the syntax `(?P<User>\w+)` where `User` is the group name from the table above,
|
||||||
regex groups are case-insensitive due to the fact that the regex groups are used in domain criteria and domain names
|
and `\w+` is the pattern for the area of the pattern that should be compared to the match value.
|
||||||
|
|
||||||
|
The match type `Equals` matches if the value extracted from the pattern is equal to the match value. The match type
|
||||||
|
`Has (Equal)` matches if the value extracted from the pattern is equal to one of the values in the match value (the
|
||||||
|
match value is a list/slice).
|
||||||
|
|
||||||
|
The regex groups are case-insensitive due to the fact that the regex groups are used in domain criteria and domain names
|
||||||
should not be compared in a case-sensitive way as per the [RFC4343](https://www.rfc-editor.org/rfc/rfc4343.html)
|
should not be compared in a case-sensitive way as per the [RFC4343](https://www.rfc-editor.org/rfc/rfc4343.html)
|
||||||
abstract and [RFC3986 Section 3.2.2](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2).
|
abstract and [RFC3986 Section 3.2.2](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2).
|
||||||
|
|
||||||
|
We do not currently apply any other normalization to usernames or groups when matching these groups. As such it's
|
||||||
|
generally *__not recommended__* to use these patterns with usernames or groups which contain characters that are not
|
||||||
|
alphanumeric (including spaces).
|
||||||
|
|
||||||
|
[Named Regex Groups]: #named-regex-groups
|
||||||
|
|
||||||
## Detailed example
|
## Detailed example
|
||||||
|
|
||||||
Here is a detailed example of an example access control section:
|
Here is a detailed example of an example access control section:
|
||||||
|
|
|
@ -88,7 +88,7 @@ especially for containerized deployments.*
|
||||||
The secret key used to encrypt session data in Redis.
|
The secret key used to encrypt session data in Redis.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters.
|
characters.
|
||||||
|
|
||||||
### expiration
|
### expiration
|
||||||
|
|
|
@ -34,6 +34,74 @@ session:
|
||||||
server_name: myredis.example.com
|
server_name: myredis.example.com
|
||||||
skip_verify: false
|
skip_verify: false
|
||||||
minimum_version: TLS1.2
|
minimum_version: TLS1.2
|
||||||
|
maximum_version: TLS1.3
|
||||||
|
certificate_chain: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC5jCCAc6gAwIBAgIRAK4Sj7FiN6PXo/urPfO4E7owDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAPKv3pSyP4ozGEiVLJ14dIWFCEGEgq7WUMI0SZZqQA2ID0L59U/Q
|
||||||
|
/Usyy7uC9gfMUzODTpANtkOjFQcQAsxlR1FOjVBrX5QgjSvXwbQn3DtwMA7XWSl6
|
||||||
|
LuYx2rBYSlMSN5UZQm/RxMtXfLK2b51WgEEYDFi+nECSqKzR4R54eOPkBEWRfvuY
|
||||||
|
91AMjlhpivg8e4JWkq4LVQUKbmiFYwIdK8XQiN4blY9WwXwJFYs5sQ/UYMwBFi0H
|
||||||
|
kWOh7GEjfxgoUOPauIueZSMSlQp7zqAH39N0ZSYb6cS0Npj57QoWZSY3ak87ebcR
|
||||||
|
Nf4rCvZLby7LoN7qYCKxmCaDD3x2+NYpWH8CAwEAAaM1MDMwDgYDVR0PAQH/BAQD
|
||||||
|
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHSITqIQSNzonFl3DzxHPEzr2hp6peo45buAAtu8FZHoA+U7Icfh
|
||||||
|
/ZXjPg7Xz+hgFwM/DTNGXkMWacQA/PaNWvZspgRJf2AXvNbMSs2UQODr7Tbv+Fb4
|
||||||
|
lyblmMUNYFMCFVAMU0eIxXAFq2qcwv8UMcQFT0Z/35s6PVOakYnAGGQjTfp5Ljuq
|
||||||
|
wsdc/xWmM0cHWube6sdRRUD7SY20KU/kWzl8iFO0VbSSrDf1AlEhnLEkp1SPaxXg
|
||||||
|
OdBnl98MeoramNiJ7NT6Jnyb3zZ578fjaWfThiBpagItI8GZmG4s4Ovh2JbheN8i
|
||||||
|
ZsjNr9jqHTjhyLVbDRlmJzcqoj4JhbKs6/I^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDBDCCAeygAwIBAgIRALJsPg21kA0zY4F1wUCIuoMwDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAMXHBvVxUzYk0u34/DINMSF+uiOekKOAjOrC6Mi9Ww8ytPVO7t2S
|
||||||
|
zfTvM+XnEJqkFQFgimERfG/eGhjF9XIEY6LtnXe8ATvOK4nTwdufzBaoeQu3Gd50
|
||||||
|
5VXr6OHRo//ErrGvFXwP3g8xLePABsi/fkH3oDN+ztewOBMDzpd+KgTrk8ysv2ou
|
||||||
|
kNRMKFZZqASvCgv0LD5KWvUCnL6wgf1oTXG7aztduA4oSkUP321GpOmBC5+5ElU7
|
||||||
|
ysoRzvD12o9QJ/IfEaulIX06w9yVMo60C/h6A3U6GdkT1SiyTIqR7v7KU/IWd/Qi
|
||||||
|
Lfftcj91VhCmJ73Meff2e2S2PrpjdXbG5FMCAwEAAaNTMFEwDgYDVR0PAQH/BAQD
|
||||||
|
AgKkMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
|
||||||
|
Z7AtA3mzFc0InSBA5fiMfeLXA3owDQYJKoZIhvcNAQELBQADggEBAEE5hm1mtlk/
|
||||||
|
kviCoHH4evbpw7rxPxDftIQlqYTtvMM4eWY/6icFoSZ4fUHEWYyps8SsPu/8f2tf
|
||||||
|
71LGgZn0FdHi1QU2H8m0HHK7TFw+5Q6RLrLdSyk0PItJ71s9en7r8pX820nAFEHZ
|
||||||
|
HkOSfJZ7B5hFgUDkMtVM6bardXAhoqcMk4YCU96e9d4PB4eI+xGc+mNuYvov3RbB
|
||||||
|
D0s8ICyojeyPVLerz4wHjZu68Z5frAzhZ68YbzNs8j2fIBKKHkHyLG1iQyF+LJVj
|
||||||
|
2PjCP+auJsj6fQQpMGoyGtpLcSDh+ptcTngUD8JsWipzTCjmaNqdPHAOYmcgtf4b
|
||||||
|
qocikt3WAdU^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
private_key: |
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEA8q/elLI/ijMYSJUsnXh0hYUIQYSCrtZQwjRJlmpADYgPQvn1
|
||||||
|
T9D9SzLLu4L2B8xTM4NOkA22Q6MVBxACzGVHUU6NUGtflCCNK9fBtCfcO3AwDtdZ
|
||||||
|
KXou5jHasFhKUxI3lRlCb9HEy1d8srZvnVaAQRgMWL6cQJKorNHhHnh44+QERZF+
|
||||||
|
+5j3UAyOWGmK+Dx7glaSrgtVBQpuaIVjAh0rxdCI3huVj1bBfAkVizmxD9RgzAEW
|
||||||
|
LQeRY6HsYSN/GChQ49q4i55lIxKVCnvOoAff03RlJhvpxLQ2mPntChZlJjdqTzt5
|
||||||
|
txE1/isK9ktvLsug3upgIrGYJoMPfHb41ilYfwIDAQABAoIBAQDTOdFf2JjHH1um
|
||||||
|
aPgRAvNf9v7Nj5jytaRKs5nM6iNf46ls4QPreXnMhqSeSwj6lpNgBYxOgzC9Q+cc
|
||||||
|
Y4ob/paJJPaIJTxmP8K/gyWcOQlNToL1l+eJ20eQoZm23NGr5fIsunSBwLEpTrdB
|
||||||
|
ENqqtcwhW937K8Pxy/Q1nuLyU2bc6Tn/ivLozc8n27dpQWWKh8537VY7ancIaACr
|
||||||
|
LJJLYxKqhQpjtBWAyCDvZQirnAOm9KnvIHaGXIswCZ4Xbsu0Y9NL+woARPyRVQvG
|
||||||
|
jfxy4EmO9s1s6y7OObSukwKDSNihAKHx/VIbvVWx8g2Lv5fGOa+J2Y7o9Qurs8t5
|
||||||
|
BQwMTt0BAoGBAPUw5Z32EszNepAeV3E2mPFUc5CLiqAxagZJuNDO2pKtyN29ETTR
|
||||||
|
Ma4O1cWtGb6RqcNNN/Iukfkdk27Q5nC9VJSUUPYelOLc1WYOoUf6oKRzE72dkMQV
|
||||||
|
R4bf6TkjD+OVR17fAfkswkGahZ5XA7j48KIQ+YC4jbnYKSxZTYyKPjH/AoGBAP1i
|
||||||
|
tqXt36OVlP+y84wWqZSjMelBIVa9phDVGJmmhz3i1cMni8eLpJzWecA3pfnG6Tm9
|
||||||
|
ze5M4whASleEt+M00gEvNaU9ND+z0wBfi+/DwJYIbv8PQdGrBiZFrPhTPjGQUldR
|
||||||
|
lXccV2meeLZv7TagVxSi3DO6dSJfSEHyemd5j9mBAoGAX8Hv+0gOQZQCSOTAq8Nx
|
||||||
|
6dZcp9gHlNaXnMsP9eTDckOSzh636JPGvj6m+GPJSSbkURUIQ3oyokMNwFqvlNos
|
||||||
|
fTaLhAOfjBZI9WnDTTQxpugWjphJ4HqbC67JC/qIiw5S6FdaEvGLEEoD4zoChywZ
|
||||||
|
9oGAn+fz2d/0/JAH/FpFPgsCgYEAp/ipZgPzziiZ9ov1wbdAQcWRj7RaWnssPFpX
|
||||||
|
jXwEiXT3CgEMO4MJ4+KWIWOChrti3qFBg6i6lDyyS6Qyls7sLFbUdC7HlTcrOEMe
|
||||||
|
rBoTcCI1GqZNlqWOVQ65ZIEiaI7o1vPBZo2GMQEZuq8mDKFsOMThvvTrM5cAep84
|
||||||
|
n6HJR4ECgYABWcbsSnr0MKvVth/inxjbKapbZnp2HUCuw87Ie5zK2Of/tbC20wwk
|
||||||
|
yKw3vrGoE3O1t1g2m2tn8UGGASeZ842jZWjIODdSi5+icysQGuULKt86h/woz2SQ
|
||||||
|
27GoE2i5mh6Yez6VAYbUuns3FcwIsMyWLq043Tu2DNkx9ijOOAuQzw^invalid..
|
||||||
|
DO NOT USE==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
high_availability:
|
high_availability:
|
||||||
sentinel_name: mysentinel
|
sentinel_name: mysentinel
|
||||||
# If `sentinel_username` is supplied, Authelia will connect using ACL-based
|
# If `sentinel_username` is supplied, Authelia will connect using ACL-based
|
||||||
|
@ -86,7 +154,7 @@ especially for containerized deployments.*
|
||||||
The password for [redis authentication](https://redis.io/commands/auth).
|
The password for [redis authentication](https://redis.io/commands/auth).
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters and the user password is changed to this value.
|
characters and the user password is changed to this value.
|
||||||
|
|
||||||
### database_index
|
### database_index
|
||||||
|
@ -145,7 +213,7 @@ authenticate to the Redis Sentinel with ACL-based authentication. Otherwise, thi
|
||||||
authentication.
|
authentication.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters and the user password is changed to this value.
|
characters and the user password is changed to this value.
|
||||||
|
|
||||||
#### nodes
|
#### nodes
|
||||||
|
|
|
@ -44,10 +44,10 @@ value, and use that to encrypt the data with the AES-GCM 256bit algorithm.
|
||||||
The minimum length of this key is 20 characters.
|
The minimum length of this key is 20 characters.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters.
|
characters.
|
||||||
|
|
||||||
See [securty measures](../../overview/security/measures.md#storage-security-measures) for more information.
|
See [security measures](../../overview/security/measures.md#storage-security-measures) for more information.
|
||||||
|
|
||||||
### postgres
|
### postgres
|
||||||
|
|
||||||
|
|
|
@ -34,3 +34,4 @@ this instance if you wanted to downgrade to pre1 you would need to use an Authel
|
||||||
| 3 | 4.34.2 | WebAuthn - fix V2 migration kid column length and provide migration path for anyone on V2 |
|
| 3 | 4.34.2 | WebAuthn - fix V2 migration kid column length and provide migration path for anyone on V2 |
|
||||||
| 4 | 4.35.0 | Added OpenID Connect storage tables and opaque user identifier tables |
|
| 4 | 4.35.0 | Added OpenID Connect storage tables and opaque user identifier tables |
|
||||||
| 5 | 4.35.1 | Fixed the oauth2_consent_session table to accept NULL subjects for users who are not yet signed in |
|
| 5 | 4.35.1 | Fixed the oauth2_consent_session table to accept NULL subjects for users who are not yet signed in |
|
||||||
|
| 6 | 4.37.0 | Adjusted the OpenID Connect tables to allow pre-configured consent improvements |
|
||||||
|
|
|
@ -17,12 +17,12 @@ aliases:
|
||||||
|
|
||||||
## Version support
|
## Version support
|
||||||
|
|
||||||
When using MySQL or MariaDB we recommend using the latest version that is officially supported by the MySQL or MariaDB
|
When using [MySQL] or [MariaDB] we recommend using the latest version that is officially supported by the [MySQL] or
|
||||||
developers. We also suggest checking out [PostgreSQL](postgres.md) as an alternative.
|
[MariaDB] developers. We also suggest checking out [PostgreSQL](postgres.md) as an alternative.
|
||||||
|
|
||||||
The oldest versions that have been tested are MySQL 5.7 and MariaDB 10.6.
|
The oldest versions that have been tested are [MySQL] 5.7 and [MariaDB] 10.6.
|
||||||
|
|
||||||
If using MySQL 5.7 or MariaDB 10.6 you may be required to adjust the `explicit_defaults_for_timestamp` setting. This
|
If using [MySQL] 5.7 or [MariaDB] 10.6 you may be required to adjust the `explicit_defaults_for_timestamp` setting. This
|
||||||
will be evident when the container starts with an error similar to `Error 1067: Invalid default value for 'exp'`. You
|
will be evident when the container starts with an error similar to `Error 1067: Invalid default value for 'exp'`. You
|
||||||
can adjust this setting in the mysql.cnf file like so:
|
can adjust this setting in the mysql.cnf file like so:
|
||||||
|
|
||||||
|
@ -43,6 +43,78 @@ storage:
|
||||||
username: authelia
|
username: authelia
|
||||||
password: mypassword
|
password: mypassword
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
|
tls:
|
||||||
|
server_name: mysql.example.com
|
||||||
|
skip_verify: false
|
||||||
|
minimum_version: TLS1.2
|
||||||
|
maximum_version: TLS1.3
|
||||||
|
certificate_chain: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC5jCCAc6gAwIBAgIRAK4Sj7FiN6PXo/urPfO4E7owDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAPKv3pSyP4ozGEiVLJ14dIWFCEGEgq7WUMI0SZZqQA2ID0L59U/Q
|
||||||
|
/Usyy7uC9gfMUzODTpANtkOjFQcQAsxlR1FOjVBrX5QgjSvXwbQn3DtwMA7XWSl6
|
||||||
|
LuYx2rBYSlMSN5UZQm/RxMtXfLK2b51WgEEYDFi+nECSqKzR4R54eOPkBEWRfvuY
|
||||||
|
91AMjlhpivg8e4JWkq4LVQUKbmiFYwIdK8XQiN4blY9WwXwJFYs5sQ/UYMwBFi0H
|
||||||
|
kWOh7GEjfxgoUOPauIueZSMSlQp7zqAH39N0ZSYb6cS0Npj57QoWZSY3ak87ebcR
|
||||||
|
Nf4rCvZLby7LoN7qYCKxmCaDD3x2+NYpWH8CAwEAAaM1MDMwDgYDVR0PAQH/BAQD
|
||||||
|
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHSITqIQSNzonFl3DzxHPEzr2hp6peo45buAAtu8FZHoA+U7Icfh
|
||||||
|
/ZXjPg7Xz+hgFwM/DTNGXkMWacQA/PaNWvZspgRJf2AXvNbMSs2UQODr7Tbv+Fb4
|
||||||
|
lyblmMUNYFMCFVAMU0eIxXAFq2qcwv8UMcQFT0Z/35s6PVOakYnAGGQjTfp5Ljuq
|
||||||
|
wsdc/xWmM0cHWube6sdRRUD7SY20KU/kWzl8iFO0VbSSrDf1AlEhnLEkp1SPaxXg
|
||||||
|
OdBnl98MeoramNiJ7NT6Jnyb3zZ578fjaWfThiBpagItI8GZmG4s4Ovh2JbheN8i
|
||||||
|
ZsjNr9jqHTjhyLVbDRlmJzcqoj4JhbKs6/I^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDBDCCAeygAwIBAgIRALJsPg21kA0zY4F1wUCIuoMwDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAMXHBvVxUzYk0u34/DINMSF+uiOekKOAjOrC6Mi9Ww8ytPVO7t2S
|
||||||
|
zfTvM+XnEJqkFQFgimERfG/eGhjF9XIEY6LtnXe8ATvOK4nTwdufzBaoeQu3Gd50
|
||||||
|
5VXr6OHRo//ErrGvFXwP3g8xLePABsi/fkH3oDN+ztewOBMDzpd+KgTrk8ysv2ou
|
||||||
|
kNRMKFZZqASvCgv0LD5KWvUCnL6wgf1oTXG7aztduA4oSkUP321GpOmBC5+5ElU7
|
||||||
|
ysoRzvD12o9QJ/IfEaulIX06w9yVMo60C/h6A3U6GdkT1SiyTIqR7v7KU/IWd/Qi
|
||||||
|
Lfftcj91VhCmJ73Meff2e2S2PrpjdXbG5FMCAwEAAaNTMFEwDgYDVR0PAQH/BAQD
|
||||||
|
AgKkMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
|
||||||
|
Z7AtA3mzFc0InSBA5fiMfeLXA3owDQYJKoZIhvcNAQELBQADggEBAEE5hm1mtlk/
|
||||||
|
kviCoHH4evbpw7rxPxDftIQlqYTtvMM4eWY/6icFoSZ4fUHEWYyps8SsPu/8f2tf
|
||||||
|
71LGgZn0FdHi1QU2H8m0HHK7TFw+5Q6RLrLdSyk0PItJ71s9en7r8pX820nAFEHZ
|
||||||
|
HkOSfJZ7B5hFgUDkMtVM6bardXAhoqcMk4YCU96e9d4PB4eI+xGc+mNuYvov3RbB
|
||||||
|
D0s8ICyojeyPVLerz4wHjZu68Z5frAzhZ68YbzNs8j2fIBKKHkHyLG1iQyF+LJVj
|
||||||
|
2PjCP+auJsj6fQQpMGoyGtpLcSDh+ptcTngUD8JsWipzTCjmaNqdPHAOYmcgtf4b
|
||||||
|
qocikt3WAdU^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
private_key: |
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEA8q/elLI/ijMYSJUsnXh0hYUIQYSCrtZQwjRJlmpADYgPQvn1
|
||||||
|
T9D9SzLLu4L2B8xTM4NOkA22Q6MVBxACzGVHUU6NUGtflCCNK9fBtCfcO3AwDtdZ
|
||||||
|
KXou5jHasFhKUxI3lRlCb9HEy1d8srZvnVaAQRgMWL6cQJKorNHhHnh44+QERZF+
|
||||||
|
+5j3UAyOWGmK+Dx7glaSrgtVBQpuaIVjAh0rxdCI3huVj1bBfAkVizmxD9RgzAEW
|
||||||
|
LQeRY6HsYSN/GChQ49q4i55lIxKVCnvOoAff03RlJhvpxLQ2mPntChZlJjdqTzt5
|
||||||
|
txE1/isK9ktvLsug3upgIrGYJoMPfHb41ilYfwIDAQABAoIBAQDTOdFf2JjHH1um
|
||||||
|
aPgRAvNf9v7Nj5jytaRKs5nM6iNf46ls4QPreXnMhqSeSwj6lpNgBYxOgzC9Q+cc
|
||||||
|
Y4ob/paJJPaIJTxmP8K/gyWcOQlNToL1l+eJ20eQoZm23NGr5fIsunSBwLEpTrdB
|
||||||
|
ENqqtcwhW937K8Pxy/Q1nuLyU2bc6Tn/ivLozc8n27dpQWWKh8537VY7ancIaACr
|
||||||
|
LJJLYxKqhQpjtBWAyCDvZQirnAOm9KnvIHaGXIswCZ4Xbsu0Y9NL+woARPyRVQvG
|
||||||
|
jfxy4EmO9s1s6y7OObSukwKDSNihAKHx/VIbvVWx8g2Lv5fGOa+J2Y7o9Qurs8t5
|
||||||
|
BQwMTt0BAoGBAPUw5Z32EszNepAeV3E2mPFUc5CLiqAxagZJuNDO2pKtyN29ETTR
|
||||||
|
Ma4O1cWtGb6RqcNNN/Iukfkdk27Q5nC9VJSUUPYelOLc1WYOoUf6oKRzE72dkMQV
|
||||||
|
R4bf6TkjD+OVR17fAfkswkGahZ5XA7j48KIQ+YC4jbnYKSxZTYyKPjH/AoGBAP1i
|
||||||
|
tqXt36OVlP+y84wWqZSjMelBIVa9phDVGJmmhz3i1cMni8eLpJzWecA3pfnG6Tm9
|
||||||
|
ze5M4whASleEt+M00gEvNaU9ND+z0wBfi+/DwJYIbv8PQdGrBiZFrPhTPjGQUldR
|
||||||
|
lXccV2meeLZv7TagVxSi3DO6dSJfSEHyemd5j9mBAoGAX8Hv+0gOQZQCSOTAq8Nx
|
||||||
|
6dZcp9gHlNaXnMsP9eTDckOSzh636JPGvj6m+GPJSSbkURUIQ3oyokMNwFqvlNos
|
||||||
|
fTaLhAOfjBZI9WnDTTQxpugWjphJ4HqbC67JC/qIiw5S6FdaEvGLEEoD4zoChywZ
|
||||||
|
9oGAn+fz2d/0/JAH/FpFPgsCgYEAp/ipZgPzziiZ9ov1wbdAQcWRj7RaWnssPFpX
|
||||||
|
jXwEiXT3CgEMO4MJ4+KWIWOChrti3qFBg6i6lDyyS6Qyls7sLFbUdC7HlTcrOEMe
|
||||||
|
rBoTcCI1GqZNlqWOVQ65ZIEiaI7o1vPBZo2GMQEZuq8mDKFsOMThvvTrM5cAep84
|
||||||
|
n6HJR4ECgYABWcbsSnr0MKvVth/inxjbKapbZnp2HUCuw87Ie5zK2Of/tbC20wwk
|
||||||
|
yKw3vrGoE3O1t1g2m2tn8UGGASeZ842jZWjIODdSi5+icysQGuULKt86h/woz2SQ
|
||||||
|
27GoE2i5mh6Yez6VAYbUuns3FcwIsMyWLq043Tu2DNkx9ijOOAuQzw^invalid..
|
||||||
|
DO NOT USE==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
@ -55,12 +127,22 @@ See the [encryption_key docs](introduction.md#encryption_key).
|
||||||
|
|
||||||
{{< confkey type="string" default="localhost" required="no" >}}
|
{{< confkey type="string" default="localhost" required="no" >}}
|
||||||
|
|
||||||
The database server host.
|
The database server host. This can also be a unix socket.
|
||||||
|
|
||||||
If utilising an IPv6 literal address it must be enclosed by square brackets and quoted:
|
If utilising an IPv6 literal address it must be enclosed by square brackets and quoted:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
host: "[fd00:1111:2222:3333::1]"
|
storage:
|
||||||
|
mysql:
|
||||||
|
host: "[fd00:1111:2222:3333::1]"
|
||||||
|
```
|
||||||
|
|
||||||
|
If utilizing a unix socket it must have the `/` prefix:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
storage:
|
||||||
|
mysql:
|
||||||
|
host: /var/run/mysqld.sock
|
||||||
```
|
```
|
||||||
|
|
||||||
### port
|
### port
|
||||||
|
@ -92,7 +174,7 @@ especially for containerized deployments.*
|
||||||
The password paired with the [username](#username) used to connect to the database.
|
The password paired with the [username](#username) used to connect to the database.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters and the user password is changed to this value.
|
characters and the user password is changed to this value.
|
||||||
|
|
||||||
### timeout
|
### timeout
|
||||||
|
@ -100,3 +182,11 @@ characters and the user password is changed to this value.
|
||||||
{{< confkey type="duration" default="5s" required="no" >}}
|
{{< confkey type="duration" default="5s" required="no" >}}
|
||||||
|
|
||||||
The SQL connection timeout.
|
The SQL connection timeout.
|
||||||
|
|
||||||
|
### tls
|
||||||
|
|
||||||
|
If defined enables connecting to [MySQL] or [MariaDB] over a TLS socket, and additionally controls the TLS connection
|
||||||
|
validation process. You can see how to configure the tls section [here](../prologue/common.md#tls-configuration).
|
||||||
|
|
||||||
|
[MySQL]: https://www.mysql.com/
|
||||||
|
[MariaDB]: https://mariadb.org/
|
||||||
|
|
|
@ -16,10 +16,10 @@ aliases:
|
||||||
|
|
||||||
## Version support
|
## Version support
|
||||||
|
|
||||||
See [PostgreSQL support](https://www.postgresql.org/support/versioning/) for the versions supported by PostgreSQL. We
|
See [PostgreSQL support](https://www.postgresql.org/support/versioning/) for the versions supported by [PostgreSQL]. We
|
||||||
recommend the *current minor* version of one of the versions supported by PostgreSQL.
|
recommend the *current minor* version of one of the versions supported by [PostgreSQL].
|
||||||
|
|
||||||
The versions of PostgreSQL that should be supported by Authelia are:
|
The versions of [PostgreSQL] that should be supported by Authelia are:
|
||||||
|
|
||||||
* 14
|
* 14
|
||||||
* 13
|
* 13
|
||||||
|
@ -40,11 +40,78 @@ storage:
|
||||||
schema: public
|
schema: public
|
||||||
username: authelia
|
username: authelia
|
||||||
password: mypassword
|
password: mypassword
|
||||||
ssl:
|
tls:
|
||||||
mode: disable
|
server_name: psotgres.example.com
|
||||||
root_certificate: /path/to/root_cert.pem
|
skip_verify: false
|
||||||
certificate: /path/to/cert.pem
|
minimum_version: TLS1.2
|
||||||
key: /path/to/key.pem
|
maximum_version: TLS1.3
|
||||||
|
certificate_chain: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC5jCCAc6gAwIBAgIRAK4Sj7FiN6PXo/urPfO4E7owDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAPKv3pSyP4ozGEiVLJ14dIWFCEGEgq7WUMI0SZZqQA2ID0L59U/Q
|
||||||
|
/Usyy7uC9gfMUzODTpANtkOjFQcQAsxlR1FOjVBrX5QgjSvXwbQn3DtwMA7XWSl6
|
||||||
|
LuYx2rBYSlMSN5UZQm/RxMtXfLK2b51WgEEYDFi+nECSqKzR4R54eOPkBEWRfvuY
|
||||||
|
91AMjlhpivg8e4JWkq4LVQUKbmiFYwIdK8XQiN4blY9WwXwJFYs5sQ/UYMwBFi0H
|
||||||
|
kWOh7GEjfxgoUOPauIueZSMSlQp7zqAH39N0ZSYb6cS0Npj57QoWZSY3ak87ebcR
|
||||||
|
Nf4rCvZLby7LoN7qYCKxmCaDD3x2+NYpWH8CAwEAAaM1MDMwDgYDVR0PAQH/BAQD
|
||||||
|
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHSITqIQSNzonFl3DzxHPEzr2hp6peo45buAAtu8FZHoA+U7Icfh
|
||||||
|
/ZXjPg7Xz+hgFwM/DTNGXkMWacQA/PaNWvZspgRJf2AXvNbMSs2UQODr7Tbv+Fb4
|
||||||
|
lyblmMUNYFMCFVAMU0eIxXAFq2qcwv8UMcQFT0Z/35s6PVOakYnAGGQjTfp5Ljuq
|
||||||
|
wsdc/xWmM0cHWube6sdRRUD7SY20KU/kWzl8iFO0VbSSrDf1AlEhnLEkp1SPaxXg
|
||||||
|
OdBnl98MeoramNiJ7NT6Jnyb3zZ578fjaWfThiBpagItI8GZmG4s4Ovh2JbheN8i
|
||||||
|
ZsjNr9jqHTjhyLVbDRlmJzcqoj4JhbKs6/I^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDBDCCAeygAwIBAgIRALJsPg21kA0zY4F1wUCIuoMwDQYJKoZIhvcNAQELBQAw
|
||||||
|
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNNzAwMTAxMDAwMDAwWhcNNzEwMTAxMDAw
|
||||||
|
MDAwWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAMXHBvVxUzYk0u34/DINMSF+uiOekKOAjOrC6Mi9Ww8ytPVO7t2S
|
||||||
|
zfTvM+XnEJqkFQFgimERfG/eGhjF9XIEY6LtnXe8ATvOK4nTwdufzBaoeQu3Gd50
|
||||||
|
5VXr6OHRo//ErrGvFXwP3g8xLePABsi/fkH3oDN+ztewOBMDzpd+KgTrk8ysv2ou
|
||||||
|
kNRMKFZZqASvCgv0LD5KWvUCnL6wgf1oTXG7aztduA4oSkUP321GpOmBC5+5ElU7
|
||||||
|
ysoRzvD12o9QJ/IfEaulIX06w9yVMo60C/h6A3U6GdkT1SiyTIqR7v7KU/IWd/Qi
|
||||||
|
Lfftcj91VhCmJ73Meff2e2S2PrpjdXbG5FMCAwEAAaNTMFEwDgYDVR0PAQH/BAQD
|
||||||
|
AgKkMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
|
||||||
|
Z7AtA3mzFc0InSBA5fiMfeLXA3owDQYJKoZIhvcNAQELBQADggEBAEE5hm1mtlk/
|
||||||
|
kviCoHH4evbpw7rxPxDftIQlqYTtvMM4eWY/6icFoSZ4fUHEWYyps8SsPu/8f2tf
|
||||||
|
71LGgZn0FdHi1QU2H8m0HHK7TFw+5Q6RLrLdSyk0PItJ71s9en7r8pX820nAFEHZ
|
||||||
|
HkOSfJZ7B5hFgUDkMtVM6bardXAhoqcMk4YCU96e9d4PB4eI+xGc+mNuYvov3RbB
|
||||||
|
D0s8ICyojeyPVLerz4wHjZu68Z5frAzhZ68YbzNs8j2fIBKKHkHyLG1iQyF+LJVj
|
||||||
|
2PjCP+auJsj6fQQpMGoyGtpLcSDh+ptcTngUD8JsWipzTCjmaNqdPHAOYmcgtf4b
|
||||||
|
qocikt3WAdU^invalid DO NOT USE=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
private_key: |
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEA8q/elLI/ijMYSJUsnXh0hYUIQYSCrtZQwjRJlmpADYgPQvn1
|
||||||
|
T9D9SzLLu4L2B8xTM4NOkA22Q6MVBxACzGVHUU6NUGtflCCNK9fBtCfcO3AwDtdZ
|
||||||
|
KXou5jHasFhKUxI3lRlCb9HEy1d8srZvnVaAQRgMWL6cQJKorNHhHnh44+QERZF+
|
||||||
|
+5j3UAyOWGmK+Dx7glaSrgtVBQpuaIVjAh0rxdCI3huVj1bBfAkVizmxD9RgzAEW
|
||||||
|
LQeRY6HsYSN/GChQ49q4i55lIxKVCnvOoAff03RlJhvpxLQ2mPntChZlJjdqTzt5
|
||||||
|
txE1/isK9ktvLsug3upgIrGYJoMPfHb41ilYfwIDAQABAoIBAQDTOdFf2JjHH1um
|
||||||
|
aPgRAvNf9v7Nj5jytaRKs5nM6iNf46ls4QPreXnMhqSeSwj6lpNgBYxOgzC9Q+cc
|
||||||
|
Y4ob/paJJPaIJTxmP8K/gyWcOQlNToL1l+eJ20eQoZm23NGr5fIsunSBwLEpTrdB
|
||||||
|
ENqqtcwhW937K8Pxy/Q1nuLyU2bc6Tn/ivLozc8n27dpQWWKh8537VY7ancIaACr
|
||||||
|
LJJLYxKqhQpjtBWAyCDvZQirnAOm9KnvIHaGXIswCZ4Xbsu0Y9NL+woARPyRVQvG
|
||||||
|
jfxy4EmO9s1s6y7OObSukwKDSNihAKHx/VIbvVWx8g2Lv5fGOa+J2Y7o9Qurs8t5
|
||||||
|
BQwMTt0BAoGBAPUw5Z32EszNepAeV3E2mPFUc5CLiqAxagZJuNDO2pKtyN29ETTR
|
||||||
|
Ma4O1cWtGb6RqcNNN/Iukfkdk27Q5nC9VJSUUPYelOLc1WYOoUf6oKRzE72dkMQV
|
||||||
|
R4bf6TkjD+OVR17fAfkswkGahZ5XA7j48KIQ+YC4jbnYKSxZTYyKPjH/AoGBAP1i
|
||||||
|
tqXt36OVlP+y84wWqZSjMelBIVa9phDVGJmmhz3i1cMni8eLpJzWecA3pfnG6Tm9
|
||||||
|
ze5M4whASleEt+M00gEvNaU9ND+z0wBfi+/DwJYIbv8PQdGrBiZFrPhTPjGQUldR
|
||||||
|
lXccV2meeLZv7TagVxSi3DO6dSJfSEHyemd5j9mBAoGAX8Hv+0gOQZQCSOTAq8Nx
|
||||||
|
6dZcp9gHlNaXnMsP9eTDckOSzh636JPGvj6m+GPJSSbkURUIQ3oyokMNwFqvlNos
|
||||||
|
fTaLhAOfjBZI9WnDTTQxpugWjphJ4HqbC67JC/qIiw5S6FdaEvGLEEoD4zoChywZ
|
||||||
|
9oGAn+fz2d/0/JAH/FpFPgsCgYEAp/ipZgPzziiZ9ov1wbdAQcWRj7RaWnssPFpX
|
||||||
|
jXwEiXT3CgEMO4MJ4+KWIWOChrti3qFBg6i6lDyyS6Qyls7sLFbUdC7HlTcrOEMe
|
||||||
|
rBoTcCI1GqZNlqWOVQ65ZIEiaI7o1vPBZo2GMQEZuq8mDKFsOMThvvTrM5cAep84
|
||||||
|
n6HJR4ECgYABWcbsSnr0MKvVth/inxjbKapbZnp2HUCuw87Ie5zK2Of/tbC20wwk
|
||||||
|
yKw3vrGoE3O1t1g2m2tn8UGGASeZ842jZWjIODdSi5+icysQGuULKt86h/woz2SQ
|
||||||
|
27GoE2i5mh6Yez6VAYbUuns3FcwIsMyWLq043Tu2DNkx9ijOOAuQzw^invalid..
|
||||||
|
DO NOT USE==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
@ -57,12 +124,22 @@ See the [encryption_key docs](introduction.md#encryption_key).
|
||||||
|
|
||||||
{{< confkey type="string" required="yes" >}}
|
{{< confkey type="string" required="yes" >}}
|
||||||
|
|
||||||
The database server host.
|
The database server host. This can also be a unix socket.
|
||||||
|
|
||||||
If utilising an IPv6 literal address it must be enclosed by square brackets and quoted:
|
If utilising an IPv6 literal address it must be enclosed by square brackets and quoted:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
host: "[fd00:1111:2222:3333::1]"
|
storage:
|
||||||
|
postgres:
|
||||||
|
host: "[fd00:1111:2222:3333::1]"
|
||||||
|
```
|
||||||
|
|
||||||
|
If utilizing a unix socket it must have the `/` prefix:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
storage:
|
||||||
|
postgres:
|
||||||
|
host: /var/run/postgres.sock
|
||||||
```
|
```
|
||||||
|
|
||||||
### port
|
### port
|
||||||
|
@ -101,7 +178,7 @@ especially for containerized deployments.*
|
||||||
The password paired with the [username](#username) used to connect to the database.
|
The password paired with the [username](#username) used to connect to the database.
|
||||||
|
|
||||||
It's __strongly recommended__ this is a
|
It's __strongly recommended__ this is a
|
||||||
[Random Alphanumeric String](../miscellaneous/guides.md#generating-a-random-alphanumeric-string) with 64 or more
|
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
|
||||||
characters and the user password is changed to this value.
|
characters and the user password is changed to this value.
|
||||||
|
|
||||||
### timeout
|
### timeout
|
||||||
|
@ -110,32 +187,9 @@ characters and the user password is changed to this value.
|
||||||
|
|
||||||
The SQL connection timeout.
|
The SQL connection timeout.
|
||||||
|
|
||||||
### ssl
|
### tls
|
||||||
|
|
||||||
#### mode
|
If defined enables connecting to [PostgreSQL] over a TLS socket, and additionally controls the TLS connection
|
||||||
|
validation process. You can see how to configure the tls section [here](../prologue/common.md#tls-configuration).
|
||||||
|
|
||||||
{{< confkey type="string" default="disable" required="no" >}}
|
[PostgreSQL]: https://www.postgresql.org/
|
||||||
|
|
||||||
SSL mode configures how to handle SSL connections with Postgres.
|
|
||||||
Valid options are 'disable', 'require', 'verify-ca', or 'verify-full'.
|
|
||||||
See the [PostgreSQL Documentation](https://www.postgresql.org/docs/12/libpq-ssl.html)
|
|
||||||
or [pgx - PostgreSQL Driver and Toolkit Documentation](https://pkg.go.dev/github.com/jackc/pgx?tab=doc)
|
|
||||||
for more information.
|
|
||||||
|
|
||||||
#### root_certificate
|
|
||||||
|
|
||||||
{{< confkey type="string" required="no" >}}
|
|
||||||
|
|
||||||
The optional location of the root certificate file encoded in the PEM format for validation purposes.
|
|
||||||
|
|
||||||
#### certificate
|
|
||||||
|
|
||||||
{{< confkey type="string" required="no" >}}
|
|
||||||
|
|
||||||
The optional location of the certificate file encoded in the PEM format for validation purposes.
|
|
||||||
|
|
||||||
#### key
|
|
||||||
|
|
||||||
{{< confkey type="string" required="no" >}}
|
|
||||||
|
|
||||||
The optional location of the key file encoded in the PEM format for authentication purposes.
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ telemetry:
|
||||||
read: 4096
|
read: 4096
|
||||||
write: 4096
|
write: 4096
|
||||||
timeouts:
|
timeouts:
|
||||||
read: 2s
|
read: 6s
|
||||||
write: 2s
|
write: 6s
|
||||||
idle: 30s
|
idle: 30s
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title: "Guidelines"
|
||||||
|
description: "Contributing Guidelines"
|
||||||
|
lead: ""
|
||||||
|
date: 2022-06-15T17:51:47+10:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
weight: 300
|
||||||
|
---
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: "Commit Message Guidelines"
|
title: "Commit Message"
|
||||||
description: "Authelia Development Commit Message Guidelines"
|
description: "Authelia Development Commit Message Guidelines"
|
||||||
lead: "This section covers the git commit message guidelines we use for development."
|
lead: "This section covers the git commit message guidelines we use for development."
|
||||||
date: 2021-01-30T19:29:07+11:00
|
date: 2021-01-30T19:29:07+11:00
|
||||||
|
@ -7,11 +7,12 @@ draft: false
|
||||||
images: []
|
images: []
|
||||||
menu:
|
menu:
|
||||||
contributing:
|
contributing:
|
||||||
parent: "development"
|
parent: "guidelines"
|
||||||
weight: 231
|
weight: 320
|
||||||
toc: true
|
toc: true
|
||||||
aliases:
|
aliases:
|
||||||
- /docs/contributing/commitmsg-guidelines.html
|
- /docs/contributing/commitmsg-guidelines.html
|
||||||
|
- /contributing/development/guidelines-commit-message/
|
||||||
---
|
---
|
||||||
|
|
||||||
The reasons for these conventions are as follows:
|
The reasons for these conventions are as follows:
|
||||||
|
@ -47,11 +48,13 @@ for, and the structure it must have.
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||||
│ │
|
│ │
|
||||||
│ └─⫸ Commit Scope: api|authentication|authorization|cmd|commands|configuration|duo|
|
│ └─⫸ Commit Scope: api|autheliabot|authentication|authorization|buildkite|bundler|cmd|
|
||||||
│ handlers|logging|middlewares|mocks|model|notification|ntp|oidc|
|
│ codecov|commands|configuration|deps|docker|duo|go|golangci-lint|
|
||||||
│ regulation|server|session|storage|suites|templates|utils|web
|
│ handlers|logging|metrics|middlewares|mocks|model|notification|npm|ntp|
|
||||||
|
│ oidc|regulation|renovate|reviewdog|server|session|storage|suites|
|
||||||
|
│ templates|totp|utils|web
|
||||||
│
|
│
|
||||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|release|test
|
└─⫸ Commit Type: build|ci|docs|feat|fix|i18n|perf|refactor|release|revert|test
|
||||||
```
|
```
|
||||||
|
|
||||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||||
|
@ -65,6 +68,7 @@ The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is opti
|
||||||
* __docs__ Documentation only changes
|
* __docs__ Documentation only changes
|
||||||
* __feat__ A new feature
|
* __feat__ A new feature
|
||||||
* __fix__ A bug fix
|
* __fix__ A bug fix
|
||||||
|
* __i18n__ Updating translations or internationalization settings
|
||||||
* __perf__ A code change that improves performance
|
* __perf__ A code change that improves performance
|
||||||
* __refactor__ A code change that neither fixes a bug nor adds a feature
|
* __refactor__ A code change that neither fixes a bug nor adds a feature
|
||||||
* __release__ Releasing a new version of Authelia
|
* __release__ Releasing a new version of Authelia
|
||||||
|
@ -101,7 +105,7 @@ commit messages).
|
||||||
There are currently a few exceptions to the "use package name" rule:
|
There are currently a few exceptions to the "use package name" rule:
|
||||||
|
|
||||||
* `api`: used for changes that change the openapi specification
|
* `api`: used for changes that change the openapi specification
|
||||||
* `cmd`: used for changes to the `authelia|authelia-scripts|authelia-suites` top level binaries
|
* `cmd`: used for changes to the `authelia|authelia-gen|authelia-scripts|authelia-suites` top level binaries
|
||||||
* `web`: used for changes to the React based frontend
|
* `web`: used for changes to the React based frontend
|
||||||
* none/empty string: useful for `test`, `refactor` and changes that are done across multiple packages
|
* none/empty string: useful for `test`, `refactor` and changes that are done across multiple packages
|
||||||
(e.g. `test: add missing unit tests`) and for docs changes that are not related to a specific package
|
(e.g. `test: add missing unit tests`) and for docs changes that are not related to a specific package
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
title: "Documentation"
|
||||||
|
description: "Authelia Development Documentation Guidelines"
|
||||||
|
lead: "This section covers the guidelines we use when writing documentation."
|
||||||
|
date: 2022-10-02T14:32:16+11:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
contributing:
|
||||||
|
parent: "guidelines"
|
||||||
|
weight: 320
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
## Domains
|
||||||
|
|
||||||
|
Always use the generic domain (or subdomain of) `example.com` in documentation.
|
||||||
|
|
||||||
|
If it's necessary to utilize more than one domain please ask for specific feedback in any PR.
|
||||||
|
|
||||||
|
## Certificates
|
||||||
|
|
||||||
|
When including certificates in documentation always ensure they are valid for 1 year starting at `Jan 1 00:00:00 1970`.
|
||||||
|
This ensures the certificate is not valid for multiple reasons.
|
||||||
|
|
||||||
|
In addition the guidance for [Private Keys](#private-keys) should be followed.
|
||||||
|
|
||||||
|
## Private Keys
|
||||||
|
|
||||||
|
Always append invalid data to the END of the PEM block before the base64 padding `=` (if present). The suggested
|
||||||
|
text is `^invalid DO NOT USE`. This both has an invalid base64 character `^` and has information to communicate that
|
||||||
|
users should not use the PEM block.
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
title: "Guidelines"
|
||||||
|
description: "An introduction into guidelines for contributing to the Authelia project."
|
||||||
|
lead: "An introduction into guidelines for contributing to the Authelia project."
|
||||||
|
date: 2022-10-02T14:32:16+11:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
contributing:
|
||||||
|
parent: "guidelines"
|
||||||
|
weight: 310
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
The guidelines section contains various guidelines for contributing to Authelia. We implement various guidelines via
|
||||||
|
automatic processes that will provide feedback in the PR, but this does not cover every situation. You will find both
|
||||||
|
those which are automated and those which are not in this section.
|
||||||
|
|
||||||
|
While it's expected that people aim to follow all of these guidelines we understand that there are logical exceptions to
|
||||||
|
all guidelines and if it makes sense we're likely to agree with you. So if you find a situation where it doesn't make
|
||||||
|
sense to follow one just let us know your reasoning when you make a PR if it's not obvious.
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: "Pull Request Guidelines"
|
title: "Pull Request"
|
||||||
description: "Authelia Development Pull Request Guidelines"
|
description: "Authelia Development Pull Request Guidelines"
|
||||||
lead: "This section covers the pull request guidelines."
|
lead: "This section covers the pull request guidelines."
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2022-06-15T17:51:47+10:00
|
||||||
|
@ -7,9 +7,11 @@ draft: false
|
||||||
images: []
|
images: []
|
||||||
menu:
|
menu:
|
||||||
contributing:
|
contributing:
|
||||||
parent: "development"
|
parent: "guidelines"
|
||||||
weight: 232
|
weight: 320
|
||||||
toc: true
|
toc: true
|
||||||
|
aliases:
|
||||||
|
- /contributing/development/guidelines-pull-request/
|
||||||
---
|
---
|
||||||
|
|
||||||
[Pull Request] guidelines are in place in order to maintain consistency and clearly communicate our process for
|
[Pull Request] guidelines are in place in order to maintain consistency and clearly communicate our process for
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: "Style Guidelines"
|
title: "Style"
|
||||||
description: "Authelia Development Style Guidelines"
|
description: "Authelia Development Style Guidelines"
|
||||||
lead: "This section covers the style guidelines we use for development."
|
lead: "This section covers the style guidelines we use for development."
|
||||||
date: 2021-04-11T21:25:03+10:00
|
date: 2021-04-11T21:25:03+10:00
|
||||||
|
@ -7,17 +7,18 @@ draft: false
|
||||||
images: []
|
images: []
|
||||||
menu:
|
menu:
|
||||||
contributing:
|
contributing:
|
||||||
parent: "development"
|
parent: "guidelines"
|
||||||
weight: 230
|
weight: 320
|
||||||
toc: true
|
toc: true
|
||||||
aliases:
|
aliases:
|
||||||
- /docs/contributing/style-guide.html
|
- /docs/contributing/style-guide.html
|
||||||
|
- /contributing/development/guidelines-style/
|
||||||
---
|
---
|
||||||
|
|
||||||
This is a general guide to the code style we aim to abide by. This is by no means an exhaustive list and we're
|
This is a general guide to the code style we aim to abide by. This is by no means an exhaustive list and we're
|
||||||
constantly changing and improving it. This is also a work in progress document.
|
constantly changing and improving it. This is also a work in progress document.
|
||||||
|
|
||||||
For our commit messages please see our [Commit Message Guidelines](guidelines-commit-message.md).
|
For our commit messages please see our [Commit Message Guidelines](../guidelines/commit-message.md).
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: "Documentation"
|
title: "Documentation Contributions"
|
||||||
description: "Information on contributing documentation to the Authelia project."
|
description: "Information on contributing documentation to the Authelia project."
|
||||||
lead: "Authelia has great documentation however there are always things that can be added. This section describes the contribution process for the documentation even though it's incredibly easy."
|
lead: "Authelia has great documentation however there are always things that can be added. This section describes the contribution process for the documentation even though it's incredibly easy."
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2022-06-15T17:51:47+10:00
|
||||||
|
@ -10,6 +10,8 @@ menu:
|
||||||
parent: "prologue"
|
parent: "prologue"
|
||||||
weight: 130
|
weight: 130
|
||||||
toc: true
|
toc: true
|
||||||
|
alias:
|
||||||
|
- /contributing/prologue/documentation
|
||||||
---
|
---
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
@ -38,14 +40,12 @@ It's relatively easy to run the __Authelia__ website locally to test out the cha
|
||||||
The following steps will allow you to run the website on the localhost and view it live in your browser:
|
The following steps will allow you to run the website on the localhost and view it live in your browser:
|
||||||
|
|
||||||
1. Run the following commands:
|
1. Run the following commands:
|
||||||
|
```bash
|
||||||
```bash
|
git clone https://github.com/authelia/authelia.git
|
||||||
git clone https://github.com/authelia/authelia.git
|
cd authelia/docs
|
||||||
cd authelia/docs
|
npm run install
|
||||||
npm run install
|
npm run start
|
||||||
npm run start
|
```
|
||||||
```
|
|
||||||
|
|
||||||
2. Visit [http://localhost:1313/](http://localhost:1313/) in your browser.
|
2. Visit [http://localhost:1313/](http://localhost:1313/) in your browser.
|
||||||
3. Modify pages to see the effects live in your browser.
|
3. Modify pages to see the effects live in your browser.
|
||||||
|
|
|
@ -18,7 +18,7 @@ Contributions to __Authelia__ have four main forms:
|
||||||
|
|
||||||
* Utilizing GitHub [Issues] or [Discussions] to make commentary about bugs, ideas, etc.
|
* Utilizing GitHub [Issues] or [Discussions] to make commentary about bugs, ideas, etc.
|
||||||
* [Development](../development/introduction.md)
|
* [Development](../development/introduction.md)
|
||||||
* [Documentation](../documentation/#introduction)
|
* [Documentation](documentation-contributions.md)
|
||||||
* [Financial](financial.md)
|
* [Financial](financial.md)
|
||||||
|
|
||||||
We encourage our community to be part of __Authelia__ by contributing in these ways. We encourage anyone who wishes to
|
We encourage our community to be part of __Authelia__ by contributing in these ways. We encourage anyone who wishes to
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
title: "Istio"
|
||||||
|
description: "A guide to integrating Authelia with the Istio Kubernetes Ingress."
|
||||||
|
lead: "A guide to integrating Authelia with the Istio Kubernetes Ingress."
|
||||||
|
date: 2022-10-02T13:59:09+11:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
integration:
|
||||||
|
parent: "kubernetes"
|
||||||
|
weight: 551
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Istio uses [Envoy](../proxies/envoy.md) as an Ingress. This means it has a relatively comprehensive integration option.
|
||||||
|
Istio is supported with Authelia v4.37.0 and higher via [Envoy]'s [external authorization] filter.
|
||||||
|
|
||||||
|
[external authorization]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
This example assumes that you have deployed an Authelia pod and you have configured it to be served on the URL
|
||||||
|
`https://auth.example.com` and there is a Kubernetes Service with the name `authelia` in the `default` namespace with
|
||||||
|
TCP port `80` configured to route to the Authelia pod's HTTP port and that your cluster is configured with the default
|
||||||
|
DNS domain name of `cluster.local`.
|
||||||
|
|
||||||
|
### Operator
|
||||||
|
|
||||||
|
This is an example IstioOperator manifest adjusted to authenticate with Authelia. This example only shows the necessary
|
||||||
|
portions of the resource that you add as well as context. You will need to adapt it to your needs.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: install.istio.io/v1alpha1
|
||||||
|
kind: IstioOperator
|
||||||
|
spec:
|
||||||
|
meshConfig:
|
||||||
|
extensionProviders:
|
||||||
|
- name: 'authelia'
|
||||||
|
envoyExtAuthzHttp:
|
||||||
|
service: 'authelia.default.svc.cluster.local'
|
||||||
|
port: 80
|
||||||
|
pathPrefix: '/api/verify/'
|
||||||
|
includeRequestHeadersInCheck:
|
||||||
|
- accept
|
||||||
|
- cookie
|
||||||
|
- proxy-authorization
|
||||||
|
headersToUpstreamOnAllow:
|
||||||
|
- 'authorization'
|
||||||
|
- 'proxy-authorization'
|
||||||
|
- 'remote-*'
|
||||||
|
- 'authelia-*'
|
||||||
|
includeAdditionalHeadersInCheck:
|
||||||
|
X-Authelia-URL: 'https://auth.example.com/'
|
||||||
|
X-Forwarded-Method: '%REQ(:METHOD)%'
|
||||||
|
X-Forwarded-Proto: '%REQ(:SCHEME)%'
|
||||||
|
X-Forwarded-Host: '%REQ(:AUTHORITY)%'
|
||||||
|
X-Forwarded-URI: '%REQ(:PATH)%'
|
||||||
|
X-Forwarded-For: '%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%'
|
||||||
|
headersToDownstreamOnDeny:
|
||||||
|
- set-cookie
|
||||||
|
headersToDownstreamOnAllow:
|
||||||
|
- set-cookie
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authorization Policy
|
||||||
|
|
||||||
|
The following [Authorization Policy] applies the above filter extension provider to the `nextcloud.example.com` domain:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: security.istio.io/v1beta1
|
||||||
|
kind: AuthorizationPolicy
|
||||||
|
metadata:
|
||||||
|
name: nextcloud
|
||||||
|
namespace: apps
|
||||||
|
spec:
|
||||||
|
action: CUSTOM
|
||||||
|
provider:
|
||||||
|
name: 'authelia'
|
||||||
|
rules:
|
||||||
|
- to:
|
||||||
|
- operation:
|
||||||
|
hosts:
|
||||||
|
- 'nextcloud.example.com'
|
||||||
|
```
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- Istio [External Authentication](https://istio.io/latest/docs/tasks/security/authorization/authz-custom/) Documentation
|
||||||
|
- Istio [Authorization Policy] Documentation
|
||||||
|
- Istio [IstioOperator Options](https://istio.io/latest/docs/reference/config/istio.operator.v1alpha1/) Documentation
|
||||||
|
- Istio [MeshConfig Extension Provider EnvoyExtAuthz HTTP Provider](https://istio.io/latest/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig-ExtensionProvider-EnvoyExternalAuthorizationHttpProvider) Documentation
|
||||||
|
|
||||||
|
[Authorization Policy]: https://istio.io/latest/docs/reference/config/security/authorization-policy/
|
|
@ -8,7 +8,7 @@ images: []
|
||||||
menu:
|
menu:
|
||||||
integration:
|
integration:
|
||||||
parent: "kubernetes"
|
parent: "kubernetes"
|
||||||
weight: 551
|
weight: 552
|
||||||
toc: true
|
toc: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,151 @@ toc: true
|
||||||
|
|
||||||
## UNDER CONSTRUCTION
|
## UNDER CONSTRUCTION
|
||||||
|
|
||||||
This section of the documentation is under construction.
|
This section is still a work in progress.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### OpenLDAP
|
||||||
|
|
||||||
|
**Tested:**
|
||||||
|
* Version: [v2.5.13](https://www.openldap.org/software/release/announce_lts.html)
|
||||||
|
* Container `bitnami/openldap:2.5.13-debian-11-r7`
|
||||||
|
|
||||||
|
Create within OpenLDAP, either via CLI or with a GUI management application like
|
||||||
|
[phpLDAPadmin](http://phpldapadmin.sourceforge.net/wiki/index.php/Main_Page) or [LDAP Admin](http://www.ldapadmin.org/)
|
||||||
|
a basic user with a complex password.
|
||||||
|
|
||||||
|
*Make note of its CN.* You can also create a group to use within Authelia if you would like granular control of who can
|
||||||
|
login, and reference it within the filters below.
|
||||||
|
|
||||||
|
### Authelia
|
||||||
|
|
||||||
|
In your Authelia configuration you will need to enter and update the following variables -
|
||||||
|
* url `ldap://OpenLDAP:1389` - servers dns name & port.
|
||||||
|
*tip: if you have Authelia on a container network that is routable, you can just use the container name*
|
||||||
|
* server_name `ldap01.example.com` - servers name
|
||||||
|
* base_dn `DC=example,DC=com` - common name of domain root.
|
||||||
|
* groups_filter `DC=example,DC=com` - replace relevant section with your own domain in common name format, same as base_dn.
|
||||||
|
* user `authelia` - username for Authelia service account
|
||||||
|
* password `SUPER_COMPLEX_PASSWORD` - password for Authelia service account
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ldap:
|
||||||
|
implementation: custom
|
||||||
|
url: ldap://OpenLDAP:1389
|
||||||
|
timeout: 5s
|
||||||
|
start_tls: false
|
||||||
|
tls:
|
||||||
|
server_name: ldap01.example.com
|
||||||
|
skip_verify: true
|
||||||
|
minimum_version: TLS1.2
|
||||||
|
base_dn: DC=example,DC=com
|
||||||
|
additional_users_dn: OU=users
|
||||||
|
users_filter: (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person))
|
||||||
|
username_attribute: uid
|
||||||
|
mail_attribute: mail
|
||||||
|
display_name_attribute: displayName
|
||||||
|
additional_groups_dn: OU=groups
|
||||||
|
groups_filter: (&(member=UID={input},OU=users,DC=example,DC=com)(objectClass=groupOfNames))
|
||||||
|
group_name_attribute: cn
|
||||||
|
user: UID=authelia,OU=service accounts,DC=example,DC=com
|
||||||
|
password: "SUPER_COMPLEX_PASSWORD"
|
||||||
|
```
|
||||||
|
Following this, restart Authelia, and you should be able to begin using LDAP integration for your user logins, with
|
||||||
|
Authelia taking the email attribute for users straight from the 'mail' attribute within the LDAP object.
|
||||||
|
|
||||||
|
### FreeIPA
|
||||||
|
|
||||||
|
**Tested:**
|
||||||
|
* Version: [v4.9.9](https://www.freeipa.org/page/Releases/4.9.9)
|
||||||
|
* Container: `freeipa/freeipa-server:fedora-36-4.9.9`
|
||||||
|
|
||||||
|
Create within FreeIPA, either via CLI or within its GUI management application `https://server_ip` a basic user with a
|
||||||
|
complex password.
|
||||||
|
|
||||||
|
*Make note of its CN.* You can also create a group to use within Authelia if you would like granular control of who can
|
||||||
|
login, and reference it within the filters below.
|
||||||
|
|
||||||
|
### Authelia
|
||||||
|
|
||||||
|
In your Authelia configuration you will need to enter and update the following variables -
|
||||||
|
* url `ldap://ldap` - servers dns name. Port will assume 389 as standard. Specify custom port with `:port` if needed.
|
||||||
|
* server_name `ldap01.example.com` - servers name
|
||||||
|
* base_dn `DC=example,DC=com` - common name of domain root.
|
||||||
|
* groups_filter `DC=example,DC=com` - replace relevant section with your own domain in common name format, same as base_dn.
|
||||||
|
* user `authelia` - username for Authelia service account
|
||||||
|
* password `SUPER_COMPLEX_PASSWORD` - password for Authelia service account
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ldap:
|
||||||
|
implementation: custom
|
||||||
|
url: ldaps://ldap.example.com
|
||||||
|
timeout: 5s
|
||||||
|
start_tls: false
|
||||||
|
tls:
|
||||||
|
server_name: ldap.example.com
|
||||||
|
skip_verify: true
|
||||||
|
minimum_version: TLS1.2
|
||||||
|
base_dn: dc=example,DC=com
|
||||||
|
username_attribute: uid
|
||||||
|
additional_users_dn: CN=users,CN=accounts
|
||||||
|
users_filter: (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person))
|
||||||
|
additional_groups_dn: OU=groups
|
||||||
|
groups_filter: (&(member=UID={input},CN=users,CN=accounts,DC=example,DC=com)(objectClass=groupOfNames))
|
||||||
|
group_name_attribute: cn
|
||||||
|
mail_attribute: mail
|
||||||
|
display_name_attribute: displayName
|
||||||
|
user: UID=authelia,CN=users,CN=accounts,DC=example,DC=com
|
||||||
|
password: "SUPER_COMPLEX_PASSWORD"
|
||||||
|
```
|
||||||
|
Following this, restart Authelia, and you should be able to begin using LDAP integration for your user logins, with
|
||||||
|
Authelia taking the email attribute for users straight from the 'mail' attribute within the LDAP object.
|
||||||
|
|
||||||
|
### lldap
|
||||||
|
|
||||||
|
**Tested:**
|
||||||
|
* Version: [v0.4.0](https://github.com/nitnelave/lldap/releases/tag/v0.4.07)
|
||||||
|
|
||||||
|
Create within lldap, a basic user with a complex password, and add to the group "lldap_password_manager"
|
||||||
|
You can also create a group to use within Authelia if you would like granular control of who can login, and reference it
|
||||||
|
within the filters below.
|
||||||
|
|
||||||
|
### Authelia
|
||||||
|
|
||||||
|
In your Authelia configuration you will need to enter and update the following variables -
|
||||||
|
* url `ldap://OpenLDAP:1389` - servers dns name & port.
|
||||||
|
*tip: if you have Authelia on a container network that is routable, you can just use the container name*
|
||||||
|
* base_dn `DC=example,DC=com` - common name of domain root.
|
||||||
|
* user `authelia` - username for Authelia service account.
|
||||||
|
* password `SUPER_COMPLEX_PASSWORD` - password for Authelia service account,
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ldap:
|
||||||
|
implementation: custom
|
||||||
|
url: ldap://lldap:3890
|
||||||
|
timeout: 5s
|
||||||
|
start_tls: false
|
||||||
|
base_dn: dc=example,DC=com
|
||||||
|
username_attribute: uid
|
||||||
|
additional_users_dn: OU=people
|
||||||
|
# To allow sign in both with username and email, one can use a filter like
|
||||||
|
# (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person))
|
||||||
|
users_filter: (&({username_attribute}={input})(objectClass=person))
|
||||||
|
additional_groups_dn: OU=groups
|
||||||
|
groups_filter: (member={dn})
|
||||||
|
group_name_attribute: cn
|
||||||
|
mail_attribute: mail
|
||||||
|
display_name_attribute: displayName
|
||||||
|
# The username and password of the admin or service user.
|
||||||
|
user: UID=authelia,OU=people,DC=example,DC=com
|
||||||
|
password: "SUPER_COMPLEX_PASSWORD"
|
||||||
|
```
|
||||||
|
Following this, restart Authelia, and you should be able to begin using lldap integration for your user logins, with
|
||||||
|
Authelia taking the email attribute for users straight from the 'mail' attribute within the LDAP object.
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
[Authelia]: https://www.authelia.com
|
||||||
|
[Bitnami OpenLDAP]: https://hub.docker.com/r/bitnami/openldap/
|
||||||
|
[FreeIPA]: https://www.freeipa.org/page/Main_Page
|
||||||
|
[lldap]: https://github.com/nitnelave/lldap
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -59,7 +66,7 @@ The following YAML configuration is an example __Authelia__
|
||||||
```yaml
|
```yaml
|
||||||
- id: guacamole
|
- id: guacamole
|
||||||
description: Apache Guacamole
|
description: Apache Guacamole
|
||||||
secret: guacamole_client_secret
|
secret: '$plaintext$guacamole_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -62,7 +69,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: argocd
|
- id: argocd
|
||||||
description: Argo CD
|
description: Argo CD
|
||||||
secret: argocd_client_secret
|
secret: '$plaintext$argocd_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -33,6 +40,12 @@ This example makes the following assumptions:
|
||||||
* __Client ID:__ `bookstack`
|
* __Client ID:__ `bookstack`
|
||||||
* __Client Secret:__ `bookstack_client_secret`
|
* __Client Secret:__ `bookstack_client_secret`
|
||||||
|
|
||||||
|
*__Important Note:__ [BookStack] does not properly URL encode the secret per [RFC6749 Appendix B] at the time this
|
||||||
|
article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric characters for
|
||||||
|
the secret or URL encode the secret yourself.*
|
||||||
|
|
||||||
|
[RFC6749 Appendix B]: https://www.rfc-editor.org/rfc/rfc6749#appendix-B
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### Application
|
### Application
|
||||||
|
@ -58,7 +71,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: bookstack
|
- id: bookstack
|
||||||
description: BookStack
|
description: BookStack
|
||||||
secret: bookstack_client_secret
|
secret: '$plaintext$bookstack_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -20,9 +20,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -31,8 +38,11 @@ This example makes the following assumptions:
|
||||||
* __Client ID:__ `cloudflare`
|
* __Client ID:__ `cloudflare`
|
||||||
* __Client Secret:__ `cloudflare_client_secret`
|
* __Client Secret:__ `cloudflare_client_secret`
|
||||||
|
|
||||||
*__Important Note:__ Cloudflare does not properly URL encode the secret. This means you'll either have to use
|
*__Important Note:__ [Cloudflare Zero Trust] does not properly URL encode the secret per [RFC6749 Appendix B] at the
|
||||||
only alphanumeric characters for the secret or URL encode it yourself.*
|
time this article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric
|
||||||
|
characters for the secret or URL encode the secret yourself.*
|
||||||
|
|
||||||
|
[RFC6749 Appendix B]: https://www.rfc-editor.org/rfc/rfc6749#appendix-B
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -69,7 +79,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: cloudflare
|
- id: cloudflare
|
||||||
description: Cloudflare ZeroTrust
|
description: Cloudflare ZeroTrust
|
||||||
secret: cloudflare_client_secret
|
secret: '$plaintext$cloudflare_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -79,7 +86,7 @@ will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: gitea
|
- id: gitea
|
||||||
description: Gitea
|
description: Gitea
|
||||||
secret: gitea_client_secret
|
secret: '$plaintext$gitea_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -75,7 +82,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: gitlab
|
- id: gitlab
|
||||||
description: GitLab
|
description: GitLab
|
||||||
secret: gitlab_client_secret
|
secret: '$plaintext$gitlab_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -93,7 +100,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: grafana
|
- id: grafana
|
||||||
description: Grafana
|
description: Grafana
|
||||||
secret: grafana_client_secret
|
secret: '$plaintext$grafana_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -66,7 +73,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: harbor
|
- id: harbor
|
||||||
description: Harbor
|
description: Harbor
|
||||||
secret: harbor_client_secret
|
secret: '$plaintext$harbor_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -49,7 +56,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: vault
|
- id: vault
|
||||||
description: HashiCorp Vault
|
description: HashiCorp Vault
|
||||||
secret: vault_client_secret
|
secret: '$plaintext$vault_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -71,14 +78,14 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: komga
|
- id: komga
|
||||||
description: Komga
|
description: Komga
|
||||||
secret: komga_client_secret
|
secret: '$plaintext$komga_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
- https://komga.example.com/login/oauth2/code/authelia
|
- https://komga.example.com/login/oauth2/code/authelia
|
||||||
scopes:
|
scopes:
|
||||||
- openid
|
- openid
|
||||||
- preferred_username
|
- profile
|
||||||
- email
|
- email
|
||||||
grant_types:
|
grant_types:
|
||||||
- authorization_code
|
- authorization_code
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -87,7 +94,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: nextcloud
|
- id: nextcloud
|
||||||
description: NextCloud
|
description: NextCloud
|
||||||
secret: nextcloud_client_secret
|
secret: '$plaintext$nextcloud_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,9 +22,16 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -66,7 +73,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: outline
|
- id: outline
|
||||||
description: Outline
|
description: Outline
|
||||||
secret: outline_client_secret
|
secret: '$plaintext$outline_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -24,9 +24,16 @@ aliases:
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -67,7 +74,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: portainer
|
- id: portainer
|
||||||
description: Portainer
|
description: Portainer
|
||||||
secret: portainer_client_secret
|
secret: '$plaintext$portainer_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,11 +22,21 @@ aliases:
|
||||||
* [Proxmox]
|
* [Proxmox]
|
||||||
* 7.1-10
|
* 7.1-10
|
||||||
|
|
||||||
## Before You Begin
|
### Common Notes
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
choose to utilize a different client id, it's completely up to you.
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Specific Notes
|
||||||
|
|
||||||
|
*__Important Note:__ [Proxmox] requires you create the Realm prior to adding the provider. This is not covered in this
|
||||||
|
guide.*
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -34,6 +44,7 @@ This example makes the following assumptions:
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `proxmox`
|
* __Client ID:__ `proxmox`
|
||||||
* __Client Secret:__ `proxmox_client_secret`
|
* __Client Secret:__ `proxmox_client_secret`
|
||||||
|
* __Realm__ `authelia`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -47,14 +58,14 @@ To configure [Proxmox] to utilize Authelia as an [OpenID Connect] Provider:
|
||||||
4. Add an OpenID Connect Server
|
4. Add an OpenID Connect Server
|
||||||
5. Set the following values:
|
5. Set the following values:
|
||||||
1. Issuer URL: `https://auth.example.com`
|
1. Issuer URL: `https://auth.example.com`
|
||||||
2. Realm: anything you wish
|
2. Realm: `authelia`
|
||||||
3. Client ID: `proxmox`
|
3. Client ID: `proxmox`
|
||||||
4. Client Key: `proxmox_client_secret`
|
4. Client Key: `proxmox_client_secret`
|
||||||
5. Username Claim `preferred_username`
|
5. Username Claim `preferred_username`
|
||||||
6. Scopes: `openid profile email`
|
6. Scopes: `openid profile email`
|
||||||
7. Enable *Autocreate Users* if you want users to automatically be created in [Proxmox].
|
7. Enable *Autocreate Users* if you want users to automatically be created in [Proxmox].
|
||||||
|
|
||||||
{{< figure src="proxmox.gif" alt="Proxmox" width="736" style="padding-right: 10px" >}}
|
{{< figure src="proxmox.png" alt="Proxmox" width="736" style="padding-right: 10px" >}}
|
||||||
|
|
||||||
### Authelia
|
### Authelia
|
||||||
|
|
||||||
|
@ -65,7 +76,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: proxmox
|
- id: proxmox
|
||||||
description: Proxmox
|
description: Proxmox
|
||||||
secret: proxmox_client_secret
|
secret: '$plaintext$proxmox_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 96 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -16,15 +16,22 @@ community: true
|
||||||
## Tested Versions
|
## Tested Versions
|
||||||
|
|
||||||
* [Authelia]
|
* [Authelia]
|
||||||
* [v4.35.5](https://github.com/authelia/authelia/releases/tag/v4.35.5)
|
* [v4.36.9](https://github.com/authelia/authelia/releases/tag/v4.36.9)
|
||||||
* [Seafile] Server
|
* [Seafile] Server
|
||||||
* 9.0.4
|
* [9.0.9](https://manual.seafile.com/changelog/server-changelog/#909-2022-09-22)
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
You are required to utilize a unique client id and a unique and random client secret for all [OpenID Connect] relying
|
### Common Notes
|
||||||
parties. You should not use the client secret in this example, you should randomly generate one yourself. You may also
|
|
||||||
choose to utilize a different client id, it's completely up to you.
|
1. You are *__required__* to utilize a unique client id for every client.
|
||||||
|
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
||||||
|
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
||||||
|
[Generating Client Secrets] guide instead.
|
||||||
|
|
||||||
|
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
This example makes the following assumptions:
|
This example makes the following assumptions:
|
||||||
|
|
||||||
|
@ -39,7 +46,10 @@ This example makes the following assumptions:
|
||||||
|
|
||||||
To configure [Seafile] to utilize Authelia as an [OpenID Connect] Provider:
|
To configure [Seafile] to utilize Authelia as an [OpenID Connect] Provider:
|
||||||
|
|
||||||
1. Edit your [Seafile] `seahub_settings.py` configuration file and add configure the following:
|
1. [Seafile] may require some dependencies such as `requests_oauthlib` to be manually installed.
|
||||||
|
See the [Seafile] documentation in the [see also](#see-also) section for more information.
|
||||||
|
|
||||||
|
2. Edit your [Seafile] `seahub_settings.py` configuration file and add configure the following:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
ENABLE_OAUTH = True
|
ENABLE_OAUTH = True
|
||||||
|
@ -52,15 +62,14 @@ OAUTH_AUTHORIZATION_URL = 'https://auth.example.com/api/oidc/authorization'
|
||||||
OAUTH_TOKEN_URL = 'https://auth.example.com/api/oidc/token'
|
OAUTH_TOKEN_URL = 'https://auth.example.com/api/oidc/token'
|
||||||
OAUTH_USER_INFO_URL = 'https://auth.example.com/api/oidc/userinfo'
|
OAUTH_USER_INFO_URL = 'https://auth.example.com/api/oidc/userinfo'
|
||||||
OAUTH_SCOPE = [
|
OAUTH_SCOPE = [
|
||||||
"openid",
|
"openid",
|
||||||
"profile",
|
"profile",
|
||||||
"email",
|
"email",
|
||||||
"groups",
|
|
||||||
]
|
]
|
||||||
OAUTH_ATTRIBUTE_MAP = {
|
OAUTH_ATTRIBUTE_MAP = {
|
||||||
"id": (True, "preferred_username"),
|
"email": (True, "email"),
|
||||||
"name": (False, "name"),
|
"name": (False, "name"),
|
||||||
"email": (False, "email"),
|
"id": (False, "not used"),
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -73,7 +82,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: seafile
|
- id: seafile
|
||||||
description: Seafile
|
description: Seafile
|
||||||
secret: seafile_client_secret
|
secret: '$plaintext$seafile_client_secret'
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
title: "Specific Information"
|
||||||
|
description: "Specific information regarding integrating the Authelia OpenID Connect Provider with an OpenID Connect relying party"
|
||||||
|
lead: "Specific information regarding integrating the Authelia OpenID Connect Provider with an OpenID Connect relying party."
|
||||||
|
date: 2022-10-20T15:27:09+11:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
integration:
|
||||||
|
parent: "openid-connect"
|
||||||
|
weight: 615
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
## Generating Client Secrets
|
||||||
|
|
||||||
|
We strongly recommend the following guidelines for generating client secrets:
|
||||||
|
|
||||||
|
1. Each client should have a unique secret.
|
||||||
|
2. Each secret should be randomly generated.
|
||||||
|
3. Each secret should have a length above 40 characters.
|
||||||
|
4. The secrets should be stored in the configuration in a supported hash format. *__Note:__ This does not mean you
|
||||||
|
configure the relying party / client application with the hashed version, just the secret value in the Authelia
|
||||||
|
configuration.*
|
||||||
|
5. Secrets should only have alphanumeric characters as some implementations do not appropriately encode the secret
|
||||||
|
when using it to access the token endpoint.
|
||||||
|
|
||||||
|
Authelia provides an easy way to perform such actions via the [Generating a Random Password Hash] guide. Users can
|
||||||
|
perform a command such as `authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72` command to
|
||||||
|
both generate a client secret with 72 characters which is printed and is to be used with the relying party and hash it
|
||||||
|
using PBKDF2 which can be stored in the Authelia configuration.
|
||||||
|
|
||||||
|
[Generating a Random Password Hash]: ../../reference/guides/generating-secure-values.md#generating-a-random-password-hash
|
||||||
|
|
||||||
|
### Plaintext
|
||||||
|
|
||||||
|
Authelia supports storing the plaintext secret in the configuration. This may be discontinued in the future. Plaintext
|
||||||
|
is either denoted by the `$plaintext$` prefix where everything after the prefix is the secret. In addition if the secret
|
||||||
|
does not start with the `$` character it's considered as a plaintext secret for the time being but is deprecated.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue