diff --git a/astro.config.mjs b/astro.config.mjs index 1eab5a5..754035e 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -120,6 +120,10 @@ export default defineConfig({ label: "Tailscale", slug: "docs/guides/tailscale", }, + { + label: "Kubernetes", + slug: "docs/guides/kubernetes", + }, { label: "Using the Binary", slug: "docs/guides/using-the-binary", diff --git a/src/content/docs/docs/community/kubernetes.mdx b/src/content/docs/docs/community/kubernetes.mdx index 0046305..4547d43 100644 --- a/src/content/docs/docs/community/kubernetes.mdx +++ b/src/content/docs/docs/community/kubernetes.mdx @@ -1,106 +1,20 @@ --- -title: Kubernetes -description: Learn how to set up Tinyauth with Kubernetes resources. +title: Other proxies with Kubernetes +description: Use a Tinyauth deployment as a forward-auth middleware with different proxies. --- _Contributors: [@kdwils](https://github.com/kdwils), [@pushpinderbal](https://github.com/pushpinderbal)_ -## Use Case - -Kubernetes-hosted applications are commonly exposed externally using [Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) or the newer [Gateway API](https://kubernetes.io/docs/concepts/services-networking/gateway/). These can act as a gateway to enforce authentication and authorization policies before traffic reaches your self-hosted applications. This is useful for protecting internal tools, admin interfaces, or services exposed to the internet - without needing to modify the applications themselves, especially those that do not have built-in authentication mechanisms. - -Popular reverse proxies like Nginx, Traefik, and Envoy provide Ingress controller and Gateway API implementations for Kubernetes that can be integrated with Tinyauth. - -## Prerequisites - -This guide assumes the following prerequisites: - -- An operational Kubernetes cluster -- An operational Ingress controller or Gateway API implementation (this guide demonstrates `ingress-nginx` and `Istio`, but `traefik` can be used as well). -- Experience with Kubernetes - -## Create a Namespace - -Firstly, create a namespace for Tinyauth: - -```yaml -apiVersion: v1 -kind: Namespace -metadata: - name: tinyauth -``` - -## Create a Deployment - -Create the Tinyauth deployment: - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: tinyauth - labels: - app: tinyauth -spec: - replicas: 1 - selector: - matchLabels: - app: tinyauth - template: - metadata: - labels: - app: tinyauth - spec: - containers: - - name: tinyauth - image: ghcr.io/tinyauthapp/tinyauth:v5 - ports: - - containerPort: 3000 - env: - - name: TINYAUTH_APPURL - value: http://auth.example.com - - name: TINYAUTH_AUTH_USERS - value: user:$$2a$$10$$UdLYoJ5lgPsC0RKqYH/jMua7zIn0g9kPqWmhYayJYLaZQ/FTmH2/u # Username is user and password is password - livenessProbe: - exec: - command: - - tinyauth - - healthcheck - initialDelaySeconds: 10 - periodSeconds: 30 - readinessProbe: - exec: - command: - - tinyauth - - healthcheck - initialDelaySeconds: 5 - periodSeconds: 10 -``` - -It is recommended (and required for IP address ACLs) that you also set the `TINYAUTH_AUTH_TRUSTEDPROXIES` environment variable to the IP address of your Nginx/Istio instance so Tinyauth can trust the `X-Real-IP` and `X-Forwarded-For`headers and get the correct client IP. - -## Create a Service - -Create the service: - -```yaml -apiVersion: v1 -kind: Service -metadata: - name: tinyauth -spec: - selector: - app: tinyauth - ports: - - port: 3000 - targetPort: 3000 - type: ClusterIP -``` +:::note +This guide only contains additional proxy setups for using Tinyauth +as a forward-auth middleware. For deployment instructions see the +Kubernetes [guide](/docs/guides/kubernetes). +::: ## Using with ingress-nginx :::caution -`ingress-nginx` is set to be [retired in March 2026](https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/). Consider migrating to a supported ingress component. +`ingress-nginx` is [deprecated](https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement). Consider migrating to a supported ingress component. ::: This ingress resource configures `ingress-nginx` to forward authentication checks for the host `my-host.domain.com` to a specific URL (`auth-url`). If the user is not authenticated, they will be redirected to a login page (`auth-signin`). @@ -112,10 +26,11 @@ Documentation for these annotations can be found in the ingress-nginx repository - `nginx.ingress.kubernetes.io/auth-signin-redirect-param` specifies the key of the query parameter used to set the redirect URI. :::note -This example uses the `..svc.cluster.local` in-cluster URI based on the above example for the `auth-url`. The `auth-signin` annotation should be a reference to a URI that is accessible to the user. +This example uses the `..svc.cluster.local` in-cluster URI based on the above example for the `auth-url`. +The `auth-signin` annotation should be a reference to a URI that is accessible to the user. ::: -```yaml +```yaml title="ingress.yaml" apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -142,14 +57,19 @@ spec: ## Using with Istio -External authorization in Istio is configured using the `AuthorizationPolicy` CRD and can be set up to use Tinyauth as the external authorization provider for both Ingress and Gateway API resources. Istio uses Envoy proxy under the hood, so this configuration can also be adapted for standalone [Envoy filters](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_authz_filter). +External authorization in Istio is configured using the `AuthorizationPolicy` CRD and can be +set up to use Tinyauth as the external authorization provider for both Ingress and Gateway API resources. +Istio uses Envoy proxy under the hood, so this configuration can also be adapted +for standalone [Envoy filters](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_authz_filter). ### Define the External Authorizer Add Tinyauth as an external authorization provider in your Istio mesh configuration. :::note -This example uses the `..svc.cluster.local` in-cluster URI with the assumption that Istio and Tinyauth exist in the same Kubernetes cluster and the Tinyauth service is accessible from the Istio ingress pods. The URL accessible to end users (e.g., `http://auth.example.com`) is configured with `TINYAUTH_APPURL`. +This example uses the `..svc.cluster.local` in-cluster URI with the assumption that Istio and +Tinyauth exist in the same Kubernetes cluster and the Tinyauth service is accessible from the Istio ingress pods. +The URL accessible to end users (e.g., `http://auth.example.com`) is configured with `TINYAUTH_APPURL`. ::: ```yaml @@ -172,8 +92,13 @@ extensionProviders: ``` :::note -- Envoy forwards requests to the external authorizer with the original path from the client request. The `pathPrefix` configuration above prefixes the path with an endpoint that Tinyauth recognizes, while Tinyauth ignores the original request path. -- Unlike other proxy implementations, Envoy connects to the external authorization backend using the original HTTP method from the client request and cannot be configured to use a static method. Tinyauth handles this by allowing all standard HTTP methods on the `/api/auth/envoy` endpoint. See [envoyproxy/envoy#5357](https://github.com/envoyproxy/envoy/issues/5357) for more information related to this behavior. +- Envoy forwards requests to the external authorizer with the original path from the client request. + The `pathPrefix` configuration above prefixes the path with an endpoint that Tinyauth recognizes, + while Tinyauth ignores the original request path. +- Unlike other proxy implementations, Envoy connects to the external authorization backend using the + original HTTP method from the client request and cannot be configured to use a static method. + Tinyauth handles this by allowing all standard HTTP methods on the `/api/auth/envoy` endpoint. + See [envoyproxy/envoy#5357](https://github.com/envoyproxy/envoy/issues/5357) for more information related to this behavior. ::: If you install Istio using helm, you can supply `extensionProviders` configuration in the `values.yaml` files as follows: @@ -182,14 +107,28 @@ If you install Istio using helm, you can supply `extensionProviders` configurati meshConfig: extensionProviders: - name: "tinyauth" - ........ + envoyExtAuthzHttp: + service: "tinyauth.tinyauth.svc.cluster.local" + port: "3000" + pathPrefix: "/api/auth/envoy?path=" + includeRequestHeadersInCheck: ["cookie", "x-forwarded-for", "x-forwarded-proto", "x-forwarded-host", "accept", "user-agent"] + includeAdditionalHeadersInCheck: + "x-forwarded-for": "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%" + "x-real-ip": "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%" + "x-forwarded-proto": "%REQ(:SCHEME)%" + "x-forwarded-host": "%REQ(:AUTHORITY)%" + "x-forwarded-uri": "%REQ(:PATH)%" + "x-forwarded-method": "%REQ(:METHOD)%" + headersToDownstreamOnAllow: ["set-cookie"] + headersToDownstreamOnDeny: ["content-type", "set-cookie"] ``` ### Create Authorization Policy -Given that you have a `HTTPRoute` under a Gateway that exposes your application, you can now create an `AuthorizationPolicy` to protect it using Tinyauth. +Given that you have a `HTTPRoute` under a Gateway that exposes your application, you can now create +an `AuthorizationPolicy` to protect it using Tinyauth. -```yaml +```yaml title="http-route.yaml" apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: @@ -209,7 +148,7 @@ spec: port: 80 ``` -```yaml +```yaml title="authorization-policy.yaml" apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: diff --git a/src/content/docs/docs/guides/kubernetes.mdx b/src/content/docs/docs/guides/kubernetes.mdx new file mode 100644 index 0000000..60f4e66 --- /dev/null +++ b/src/content/docs/docs/guides/kubernetes.mdx @@ -0,0 +1,270 @@ +--- +title: Kubernetes +description: Use Tinyauth in a Kubernetes environment. +--- + +Tinyauth supports Kubernetes based deployments making it easy to add an IdP or an authentication middleware +to your Kubernetes cluster. + +## Requirements + +- A Kubernetes cluster + +We will use [k3s](https://k3s.io) and [Traefik](https://traefik.io) in this tutorial so, ingress +instructions may differ for your setup. + +:::caution +This guide assumes familiarity with Kubernetes. In-depth instructions will not be given, and it is +expected that you understand how to use each manifest. +::: + +## Installation + +Before installing Tinyauth, we need to give it access to the Kubernetes API in order to be +able to discover ACLs from ingresses. To achieve this, we firstly need to create the Tinyauth +namespace: + +```yaml title="namespace.yaml" +apiVersion: v1 +kind: Namespace +metadata: + name: tinyauth + labels: + app: tinyauth +``` + +Then, we need a Cluster Role to give Tinyauth permissions to see the ingresses: + +```yaml title="cluster-role.yaml" +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: tinyauth-ingress +rules: + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] +``` + +Finally, we need to create a Cluster Role Binding to give the Tinyauth service account +access to the Cluster Role. + +```yaml title="cluster-role-binding.yaml" +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tinyauth-ingress +subjects: + - kind: ServiceAccount + name: tinyauth-sa + namespace: tinyauth +roleRef: + kind: ClusterRole + name: tinyauth-ingress + apiGroup: rbac.authorization.k8s.io +``` + +Let's also create the Tinyauth service account while we are here: + +```yaml title="tinyauth-service-account.yaml" +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tinyauth-sa + namespace: tinyauth +``` + +:::note +In case you are planning to install Tinyauth with helm, you can skip the creation of the +service account as the chart will do it for you. +::: + +### helm + +To install Tinyauth with helm, firstly add the repository: + +```sh +helm repo add tinyauth https://helm.tinyauth.app +helm repo update +``` + +Create your `values.yaml` file, default file with all options can be found +in the [repository](https://github.com/tinyauthapp/helm/blob/main/charts/tinyauth/values.yaml). +Check the [configuration](/docs/reference/configuration) for the required values. + +It is recommended (and required for IP address ACLs) that you also set the `tinyauth.auth.trustedProxies` +environment variable to the IP address of your Traefik instance so Tinyauth can trust the +`X-Real-IP` and `X-Forwarded-For`headers and get the correct client IP. + +Then install the Tinyauth chart: + +```sh +helm install tinyauth tinyauth/tinyauth -f values.yaml -n tinyauth +``` + +If everything goes well, you should see the Tinyauth pod running in the `tinyauth` namespace. + +### manual + +To install Tinyauth manually, we firstly need a secret containing our configuration: + +```yaml title="tinyauth-secret.yaml" +apiVersion: v1 +kind: Secret +metadata: + name: tinyauth-secret + namespace: tinyauth +type: Opaque +stringData: + TINYAUTH_APPURL: http://tinyauth.example.com + TINYAUTH_AUTH_USERS: your-username-password-hash +``` + +It is recommended (and required for IP address ACLs) that you also set the `TINYAUTH_AUTH_TRUSTEDPROXIES` +environment variable to the IP address of your Traefik instance so Tinyauth can trust the +`X-Real-IP` and `X-Forwarded-For`headers and get the correct client IP. + +Now, we can safely deploy Tinyauth: + +```yaml title="tinyauth-deployment.yaml" +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tinyauth-dp + namespace: tinyauth + labels: + app: tinyauth +spec: + replicas: 1 + selector: + matchLabels: + app: tinyauth + template: + metadata: + labels: + app: tinyauth + spec: + serviceAccountName: tinyauth-sa + containers: + - name: tinyauth + image: ghcr.io/tinyauthapp/tinyauth:v5 + ports: + - containerPort: 3000 + name: web + envFrom: + - secretRef: + name: tinyauth-secret +``` + +:::note +It's recommended you add a persistent volume for the `/data` path to preserve Tinyauth sessions and to use +as storage for the OpenID Connect provider in case you are planning to utilize it. +::: + +Then create a simple Cluster IP to expose Tinyauth: + +```yaml title="tinyauth-cluster-ip.yaml" +apiVersion: v1 +kind: Service +metadata: + name: tinyauth-svc-cip + namespace: tinyauth +spec: + selector: + app: tinyauth + ports: + - name: web + protocol: TCP + port: 3000 + targetPort: web + type: ClusterIP +``` + +And finally an ingress exposing Tinyauth: + +```yaml title="tinyauth-ingress.yaml" +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: tinyauth-ingress + namespace: tinyauth +spec: + rules: + - host: tinyauth.example.com + http: + paths: + - pathType: Prefix + path: / + backend: + service: + name: tinyauth-svc-cip + port: + number: 3000 +``` + +If everything deploys correctly, Tinyauth should start up with no errors and be accessible under +`http://tinyauth.example.com`. + +## Using forward-auth + +Tinyauth officially supports only the Traefik proxy for forward-auth. However, it works with other proxies +like Istio. Instructions on these proxies can be found in the [community guide](/docs/community/kubernetes.mdx). + +To use Tinyauth as a forward-auth middleware in Traefik, just create a middleware using Traefik's CRD: + +```yaml title="middleware.yaml" +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: tinyauth + namespace: tinyauth +spec: + forwardAuth: + address: http://tinyauth-svc-cip.tinyauth.svc.cluster.local:3000/api/auth/traefik + authResponseHeaders: + - remote-user + - remote-name + - remote-email + - remote-groups + - remote-sub + - authorization +``` + +Now, in your Ingresses you can just define the Tinyauth middleware and use your ACLs as you would +in Docker. For example: + +```yaml title="example-ingress.yaml" +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + tinyauth.apps.myapp.config.domain: myapp.example.com + tinyauth.apps.myapp.path.allow: /foo + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.middlewares: tinyauth-tinyauth@kubernetescrd + name: myapp-ingress +spec: + rules: + - host: myapp.example.com + http: + paths: + - pathType: Prefix + path: / + backend: + service: + name: myapp-svc-cip + port: + number: 80 +``` + +:::note +Traefik middlewares work in the form of `namespace-middlware@kubernetescrd`. +::: + +After deploying the ingress and trying to access the app at the configured domain, you should be redirected +to Tinyauth for authentication. + +:::caution +Tinyauth only supports a single domain per ACL so, if you have multiple rules, you will need multiple +ACLs. +::: \ No newline at end of file diff --git a/src/content/docs/docs/reference/changelog.mdx b/src/content/docs/docs/reference/changelog.mdx index e45877b..b702a09 100644 --- a/src/content/docs/docs/reference/changelog.mdx +++ b/src/content/docs/docs/reference/changelog.mdx @@ -3,6 +3,26 @@ title: Changelog description: Overview of changes and updates in Tinyauth versions. --- +## v5.1.2 + +> [!WARNING] +> This release contains security fixes, please update as soon as possible. + +### Improvements + +- Parent domain is now considered a trusted domain +- Allow for OAuth auto-redirect in OIDC flow + +### Fixes + +- Make `login_for` parameter optional +- Fix redirection issues in HTTPS to HTTP downgrade redirect +- Fix ACLs normalization in Docker and Kubernetes ACL providers + +### Technical + + - Update dependencies + ## v5.1.1 ### Fixes