diff --git a/.github/codespell-words.txt b/.github/codespell-words.txt index 7a7f5ef317..603dbb3c1b 100644 --- a/.github/codespell-words.txt +++ b/.github/codespell-words.txt @@ -1,7 +1,32 @@ +akadmin +asgi +assertIn +authentik +authn +crate +docstrings +entra +goauthentik +gunicorn +hass +jwe +jwks keypair keypairs -hass -warmup +kubernetes +oidc ontext +openid +passwordless +plex +saml +scim singed -assertIn +slo +sso +totp +traefik +# https://github.com/codespell-project/codespell/issues/1224 +upToDate +warmup +webauthn diff --git a/.vscode/settings.json b/.vscode/settings.json index 699d566efb..ea2be46bbd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,26 +1,4 @@ { - "cSpell.words": [ - "akadmin", - "asgi", - "authentik", - "authn", - "entra", - "goauthentik", - "jwe", - "jwks", - "kubernetes", - "oidc", - "openid", - "passwordless", - "plex", - "saml", - "scim", - "slo", - "sso", - "totp", - "traefik", - "webauthn" - ], "todo-tree.tree.showCountsInTree": true, "todo-tree.tree.showBadges": true, "yaml.customTags": [ diff --git a/Makefile b/Makefile index d89e01b199..42a23d561b 100644 --- a/Makefile +++ b/Makefile @@ -4,34 +4,17 @@ PWD = $(shell pwd) UID = $(shell id -u) GID = $(shell id -g) -NPM_VERSION = $(shell python -m scripts.npm_version) +NPM_VERSION = $(shell poetry run python -m scripts.generate_semver) PY_SOURCES = authentik tests scripts lifecycle .github -GO_SOURCES = cmd internal -WEB_SOURCES = web/src web/packages DOCKER_IMAGE ?= "authentik:test" GEN_API_TS = "gen-ts-api" GEN_API_PY = "gen-py-api" GEN_API_GO = "gen-go-api" -pg_user := $(shell python -m authentik.lib.config postgresql.user 2>/dev/null) -pg_host := $(shell python -m authentik.lib.config postgresql.host 2>/dev/null) -pg_name := $(shell python -m authentik.lib.config postgresql.name 2>/dev/null) - -CODESPELL_ARGS = -D - -D .github/codespell-dictionary.txt \ - -I .github/codespell-words.txt \ - -S 'web/src/locales/**' \ - -S 'website/docs/developer-docs/api/reference/**' \ - -S '**/node_modules/**' \ - -S '**/dist/**' \ - $(PY_SOURCES) \ - $(GO_SOURCES) \ - $(WEB_SOURCES) \ - website/src \ - website/blog \ - website/docs \ - website/integrations \ - website/src +pg_user := $(shell poetry run python -m authentik.lib.config postgresql.user 2>/dev/null) +pg_host := $(shell poetry run python -m authentik.lib.config postgresql.host 2>/dev/null) +pg_name := $(shell poetry run python -m authentik.lib.config postgresql.name 2>/dev/null) all: lint-fix lint test gen web ## Lint, build, and test everything @@ -49,26 +32,26 @@ go-test: go test -timeout 0 -v -race -cover ./... test: ## Run the server tests and produce a coverage report (locally) - coverage run manage.py test --keepdb authentik - coverage html - coverage report + poetry run coverage run manage.py test --keepdb authentik + poetry run coverage html + poetry run coverage report lint-fix: lint-codespell ## Lint and automatically fix errors in the python source code. Reports spelling errors. - black $(PY_SOURCES) - ruff check --fix $(PY_SOURCES) + poetry run black $(PY_SOURCES) + poetry run ruff check --fix $(PY_SOURCES) lint-codespell: ## Reports spelling errors. - codespell -w $(CODESPELL_ARGS) + poetry run codespell -w lint: ## Lint the python and golang sources - bandit -r $(PY_SOURCES) -x web/node_modules -x tests/wdio/node_modules -x website/node_modules + poetry run bandit -c pyproject.toml -r $(PY_SOURCES) golangci-lint run -v core-install: poetry install migrate: ## Run the Authentik Django server's migrations - python -m lifecycle.migrate + poetry run python -m lifecycle.migrate i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service @@ -76,7 +59,7 @@ aws-cfn: cd lifecycle/aws && npm run aws-cfn core-i18n-extract: - ak makemessages \ + poetry run ak makemessages \ --add-location file \ --no-obsolete \ --ignore web \ @@ -107,11 +90,11 @@ gen-build: ## Extract the schema from the database AUTHENTIK_DEBUG=true \ AUTHENTIK_TENANTS__ENABLED=true \ AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \ - ak make_blueprint_schema > blueprints/schema.json + poetry run ak make_blueprint_schema > blueprints/schema.json AUTHENTIK_DEBUG=true \ AUTHENTIK_TENANTS__ENABLED=true \ AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \ - ak spectacular --file schema.yml + poetry run ak spectacular --file schema.yml gen-changelog: ## (Release) generate the changelog based from the commits since the last tag git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md @@ -190,7 +173,7 @@ gen-client-go: gen-clean-go ## Build and install the authentik API for Golang rm -rf ./${GEN_API_GO}/config.yaml ./${GEN_API_GO}/templates/ gen-dev-config: ## Generate a local development config file - python -m scripts.generate_config + poetry run scripts/generate_config.py gen: gen-build gen-client-ts @@ -271,21 +254,21 @@ ci--meta-debug: node --version ci-black: ci--meta-debug - black --check $(PY_SOURCES) + poetry run black --check $(PY_SOURCES) ci-ruff: ci--meta-debug - ruff check $(PY_SOURCES) + poetry run ruff check $(PY_SOURCES) ci-codespell: ci--meta-debug - codespell $(CODESPELL_ARGS) -s + poetry run codespell -s ci-bandit: ci--meta-debug - bandit -r $(PY_SOURCES) + poetry run bandit -r $(PY_SOURCES) ci-pending-migrations: ci--meta-debug - ak makemigrations --check + poetry run ak makemigrations --check ci-test: ci--meta-debug - coverage run manage.py test --keepdb --randomly-seed ${CI_TEST_SEED} authentik - coverage report - coverage xml + poetry run coverage run manage.py test --keepdb --randomly-seed ${CI_TEST_SEED} authentik + poetry run coverage report + poetry run coverage xml diff --git a/SECURITY.md b/SECURITY.md index 1f25e5cde7..15b6b9c0ff 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,7 +2,7 @@ authentik takes security very seriously. We follow the rules of [responsible di ## Independent audits and pentests -We are committed to engaging in regular pentesting and security audits of authentik. Defining and adhering to a cadence of external testing ensures a stronger probability that our code base, our features, and our architecture is as secure and non-exploitable as possible. For more details about specfic audits and pentests, refer to "Audits and Certificates" in our [Security documentation](https://docs.goauthentik.io/docs/security). +We are committed to engaging in regular pentesting and security audits of authentik. Defining and adhering to a cadence of external testing ensures a stronger probability that our code base, our features, and our architecture is as secure and non-exploitable as possible. For more details about specific audits and pentests, refer to "Audits and Certificates" in our [Security documentation](https://docs.goauthentik.io/docs/security). ## What authentik classifies as a CVE diff --git a/lifecycle/wait_for_db.py b/lifecycle/wait_for_db.py index c561ba76ba..2c193c24c4 100755 --- a/lifecycle/wait_for_db.py +++ b/lifecycle/wait_for_db.py @@ -63,7 +63,9 @@ def wait_for_db(): # Sanity check, ensure SECRET_KEY is set before we even check for database connectivity if CONFIG.get("secret_key") is None or len(CONFIG.get("secret_key")) == 0: CONFIG.log("info", "----------------------------------------------------------------------") - CONFIG.log("info", "Secret key missing, check https://goauthentik.io/docs/installation/.") + CONFIG.log( + "info", "Secret key missing, check https://docs.goauthentik.io/docs/install-config/" + ) CONFIG.log("info", "----------------------------------------------------------------------") sysexit(1) check_postgres() diff --git a/pyproject.toml b/pyproject.toml index 4d6ea193f1..341a531568 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,27 @@ version = "2025.2.1" description = "" authors = ["authentik Team "] +[tool.bandit] +exclude_dirs = ["**/node_modules/**"] + +[tool.codespell] +skip = [ + "**/node_modules", + "**/package-lock.json", + "schema.yml", + "unittest.xml", + "./blueprints/schema.json", + "go.sum", + "locale", + "**/dist", + "**/web/src/locales", + "**/web/xliff", + "./website/build", + "./gen-ts-api", + "*.api.mdx", +] +dictionary = ".github/codespell-dictionary.txt,-" +ignore-words = ".github/codespell-words.txt" [tool.black] line-length = 100 target-version = ['py312'] @@ -123,7 +144,9 @@ kubernetes = "*" ldap3 = "*" lxml = "*" msgraph-sdk = "*" -opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf", extras = ["reggie"] } +opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf", extras = [ + "reggie", +] } packaging = "*" paramiko = "*" psycopg = { extras = ["c"], version = "*" } diff --git a/scripts/generate_config.py b/scripts/generate_config.py old mode 100644 new mode 100755 index 1f81aa224d..ae8dcc69be --- a/scripts/generate_config.py +++ b/scripts/generate_config.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """Generate config for development""" from yaml import safe_dump diff --git a/scripts/generate_semver.py b/scripts/generate_semver.py new file mode 100755 index 0000000000..7156662b2a --- /dev/null +++ b/scripts/generate_semver.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +""" +Generates a Semantic Versioning identifier, suffixed with a timestamp. +""" + +from time import time + +from authentik import __version__ as package_version + +""" +See: https://semver.org/#spec-item-9 (Pre-release spec) +""" +pre_release_timestamp = int(time()) + +print(f"{package_version}-{pre_release_timestamp}") diff --git a/scripts/npm_version.py b/scripts/npm_version.py deleted file mode 100644 index 5c7df4adcf..0000000000 --- a/scripts/npm_version.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Helper script to generate an NPM Version""" - -from time import time - -from authentik import __version__ - -print(f"{__version__}-{int(time())}") diff --git a/web/src/admin/applications/wizard/steps/ak-application-wizard-submit-step.ts b/web/src/admin/applications/wizard/steps/ak-application-wizard-submit-step.ts index b02f49d1d7..d2e2786971 100644 --- a/web/src/admin/applications/wizard/steps/ak-application-wizard-submit-step.ts +++ b/web/src/admin/applications/wizard/steps/ak-application-wizard-submit-step.ts @@ -328,7 +328,7 @@ export class ApplicationWizardSubmitStep extends CustomEmitterElement(Applicatio if (!(this.wizard && app && provider)) { throw new Error("Submit step received uninitialized wizard context"); } - // An empty object is truthy, an empty array is falsey. *WAT Javascript*. + // An empty object is truthy, an empty array is falsey. *WAT JavaScript*. const keys = Object.keys(this.wizard.errors); return match([this.state, keys]) .with(["submitted", P._], () => diff --git a/website/.gitignore b/website/.gitignore index df1c20be44..848aa3be66 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -24,5 +24,5 @@ yarn-debug.log* yarn-error.log* static/docker-compose.yml -static/schema.yaml +static/schema.yml docs/developer-docs/api/reference/** diff --git a/website/docs/developer-docs/setup/full-dev-environment.mdx b/website/docs/developer-docs/setup/full-dev-environment.mdx index f18319b58a..968be7a956 100644 --- a/website/docs/developer-docs/setup/full-dev-environment.mdx +++ b/website/docs/developer-docs/setup/full-dev-environment.mdx @@ -132,7 +132,7 @@ make web # Formats the frontend code Now that the backend and frontend have been setup and built, you can start authentik by running the following command in the same directory as your local authentik git repository: ```shell -ak server # Starts authentik server +poetry run ak server # Starts authentik server ``` And now, authentik should now be accessible at `http://localhost:9000`. diff --git a/website/docs/troubleshooting/login.md b/website/docs/troubleshooting/login.md index 90a243b8ea..e28065d8f4 100644 --- a/website/docs/troubleshooting/login.md +++ b/website/docs/troubleshooting/login.md @@ -23,7 +23,7 @@ kubectl exec -it deployment/authentik-worker -c worker -- ak create_recovery_key or, for CLI, run ```shell -ak create_recovery_key 10 akadmin +poetry run ak create_recovery_key 10 akadmin ``` This will output a link, that can be used to instantly gain access to authentik as the user specified above. The link is valid for amount of years specified above, in this case, 10 years. diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index b43e3e2774..9b899d529a 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -152,7 +152,7 @@ const createConfig = (): Config => { docsPluginId: "docs", config: { authentik: { - specPath: "static/schema.yaml", + specPath: "static/schema.yml", outputDir: "docs/developer-docs/api/reference/", hideSendButton: true, sidebarOptions: { diff --git a/website/integrations/services/frappe/index.md b/website/integrations/services/frappe/index.md index d8a6304b21..541b97ab51 100644 --- a/website/integrations/services/frappe/index.md +++ b/website/integrations/services/frappe/index.md @@ -10,7 +10,7 @@ These instructions apply to all projects in the Frappe Family. ## What is Frappe -> Frappe is a full stack, batteries-included, web framework written in Python and Javascript. +> Frappe is a full stack, batteries-included, web framework written in Python and JavaScript. > > -- https://frappe.io/ diff --git a/website/netlify.toml b/website/netlify.toml index 880bb3529d..81b2b4d636 100644 --- a/website/netlify.toml +++ b/website/netlify.toml @@ -1002,6 +1002,12 @@ status = 302 force = true +[[redirects]] + from = "/schema.yaml" + to = "/schema.yml" + status = 302 + force = true + [[redirects]] from = "/developer-docs/api/api" to = "/docs/developer-docs/api/api" diff --git a/website/package.json b/website/package.json index 54014afd72..8dde45359c 100644 --- a/website/package.json +++ b/website/package.json @@ -4,8 +4,8 @@ "private": true, "license": "MIT", "scripts": { - "build": "cp ../docker-compose.yml static/docker-compose.yml && cp ../schema.yml static/schema.yaml && docusaurus gen-api-docs all && cross-env NODE_OPTIONS='--max_old_space_size=65536' docusaurus build", - "build-bundled": "cp ../schema.yml static/schema.yaml && docusaurus gen-api-docs all && cross-env NODE_OPTIONS='--max_old_space_size=65536' docusaurus build", + "build": "cp ../docker-compose.yml static/docker-compose.yml && cp ../schema.yml static/schema.yml && docusaurus gen-api-docs all && cross-env NODE_OPTIONS='--max_old_space_size=65536' docusaurus build", + "build-bundled": "cp ../schema.yml static/schema.yml && docusaurus gen-api-docs all && cross-env NODE_OPTIONS='--max_old_space_size=65536' docusaurus build", "deploy": "docusaurus deploy", "docusaurus": "docusaurus", "lint:lockfile": "wireit", diff --git a/website/scripts/docsmg/src/migrate.rs b/website/scripts/docsmg/src/migrate.rs index 6859299025..459c0d66e5 100644 --- a/website/scripts/docsmg/src/migrate.rs +++ b/website/scripts/docsmg/src/migrate.rs @@ -124,7 +124,7 @@ fn replace_links(migrate_path: PathBuf, moves: Vec<(PathBuf, PathBuf)>) { r#move.1.display(), tmp_file )); - // delete file if it didnt already exist + // delete file if it didn't already exist if let Ok(_) = tmp_file { let _ = remove_file(&r#move.1); }; @@ -223,7 +223,7 @@ fn replace_links(migrate_path: PathBuf, moves: Vec<(PathBuf, PathBuf)>) { ); continue; }; - // delete file if it didnt already exist + // delete file if it didn't already exist //if let Ok(_) = tmp_file { // let _ = remove_file(&absolute_link); //}; @@ -275,7 +275,7 @@ fn replace_links(migrate_path: PathBuf, moves: Vec<(PathBuf, PathBuf)>) { .collect::(); let new_link = escapes.join(tmp_absolute_link.iter().collect::()); - // add a . to the begining if it doesnt already start with . or .. + // add a . to the beginning if it doesn't already start with . or .. let new_link = match new_link .components() .collect::>()