Traefik: Реализация промежуточного сервера для авторизации в Azure AD.

Traefik azure ad dotnet forwardauth

День добрый, уважаемые.

Сегодня я расскажу о том, как открыть тот или иной внутренний сайт в интернет, но не для всех, а только для избранных. Так сказать: добавим авторизацию туда, где ее не было и как будто не надо было.

Где я это использую? Зачем это всё?

Есть у меня Kubernetes кластер, где хостятся какие-то проекты. И всё это с помощью traefik (ingress controller) смотрит в интернет. Точнее из интернета с помощью traefik можно посмотреть на проекты. Но в данный момент не столько важно кто куда смотрит, как то, что у traefik есть dashboard и он тоже доступен из интернета. Но родной авторизации в этом dashboard'е нет. А показывать внутренности маршрутизации кому попало не стоит.

Проблему я сам создал и сам решил. Теперь вот вам хочу рассказать.

Где брать пользователей?

Поскольку я являюсь адептом церкви Microsoft, то у меня есть Azure Active Directory. Пользователей будем брать здесь. Но не всех - создадим отдельную группу, куда добавим только избранных пользователей. После авторизации в Azure AD будем проверять пользователя на принадлежность к заданной группе.

Как вообще возможно задуманное?

Traefik в отличие от других ingress controller'ов дает нам возможность настраивать промежуточные правила для запросов (middleware). Среди прочего есть отдельный тип middleware для реализации внешней авторизации. Это нам и надо.

Схема такая

Нам надо реализовать AuthServer, создать и правильно настроить middleware и использовать его в ingressroute.

Готовую реализацию сервера можно найти на моем github репозитории.

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: auth
spec:
  forwardAuth:
    address: "http://10.97.180.143/auth"
    trustForwardHeader: true  
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard
spec:
  entryPoints:
  - websecure
  routes:
  - kind: Rule
    match: Host(`traefik.example.com`)
    middlewares:
    - name: auth
    services:
    - kind: TraefikService
      name: api@internal
      namespace: default
  tls:
    certResolver: letsencrypt