Greenlight v3 Workshop 5. Mai 2023

OpenID-Connect/Shibboleth/Keycloak

In der migrations.rake (wget -P lib/tasks/migrations https://raw.githubusercontent.com/bigbluebutton/greenlight/v2/lib/tasks/migrations/migrations.rake) in der Task der user Migration an der folgenden Stelle :social_id gegen :username austauschen:

User.unscoped
        .select(:id, :uid, :name, :email, :username, :language, :role_id)
        .includes(:role)
        .where.not(roles: { name: COMMON[:filtered_user_roles] }, deleted: true)
        .find_each(start: start, finish: stop, batch_size: COMMON[:batch_size]) do |u|
      role_name = infer_role_name(u.role.name)
      params = { user: { name: u.name, email: u.email, external_id: u.username, language: u.language, role: role_name } }

Shibboleth IdP als OpenID Connect - Provider:

https://doku.tid.dfn.de/de:shibidp:config-extensions-oidc

Offene Registrierung muss angeschaltet sein, sonst müssen die Nutzer noch freigegeben werden

https://docs.bigbluebutton.org/greenlight/v3/migration/
https://docs.bigbluebutton.org/greenlight/v3/external-authentication/
https://github.com/bigbluebutton/greenlight/pull/5107
https://github.com/bigbluebutton/greenlight-run

Docker-Compose-File

https://github.com/bigbluebutton/greenlight/blob/master/docker-compose.yml

Alternativen zu Keycloak:

A Federated OpenID Connect Provider
https://dexidp.io/
Authentication Through LDAP
https://dexidp.io/docs/connectors/ldap/
authentik
https://goauthentik.io/
und eine Art Anleitung für authentik
https://github.com/bigbluebutton/greenlight/issues/4817#issuecomment-1501157949

Issues:

https://github.com/bigbluebutton/greenlight/issues/5062
https://groups.google.com/g/bigbluebutton-greenlight/c/gx1Q6Ic96HY/m/bd2dqFhKAQAJ
Aktuell funktioniert der Betrieb unter einem URL-Prefix nicht.
https://github.com/bigbluebutton/greenlight/issues/5176

Deprovisionierung von Nutzerdaten:

ein Projekt hat dies für v2.x mal versucht (PoC): https://github.com/oxzi/greenlight-ldap-sync

Config für Dex

Eine funktionierende Config für Greenlight mit LDAP via Dex. Details unter Dex: Authentication Through LDAP. Hier wird alles per docker-compose auf einem gemeinsamen Host betrieben, dabei nutze ich aus, dass die Container untereinander direkt kommunizieren können und verwende URLs wie http://greenlightv3:3000, http://dex:5556 oder den Docker-Compose container_name um z.B. auf die Postgres-DB zuzugreifen.

Die Datenbank für Dex muss im Vorfeld manuell generiert werden, dazu die Postgres-Commandline aufrufen

docker exec -it root_db14_1 psql -U postgres

Und darin dann die DB erstellen - ob der grant wirklich nötig ist, oder ob postgres sowieso dürfte, hab ich nicht nachgeschaut

create database dex_db
grant all privileges on database dex_db to postgres;

Wenn man nicht den für Greenlight ohnehin vorhandenen Postgres-Docker mitnutzen möchte, gibts hier noch andere Möglichkeiten:
https://dexidp.io/docs/storage/

Wichtig: wenn man bisherige "External IDs" migrieren will, muss sie in einem Dex-spezifischen Format (Protobuf) angelegt werden:

message IDTokenSubject {
  string user_id = 1;
  string conn_id = 2;
}

Ich habe das erst nachträglich in der Datenbank getan, indem ich den Base64-Kodierten Bytestream selbst zusammengebaut habe, was glücklicherweise halbwegs überschaubar war, solange der Inhalt des im Dex konfigurierten "idAttr"s immer < 127 Zeichen lang ist. Für größere Attributlängen (z.B. Tiefe OU-Strukturen im LDAP) müsste man sich noch mit dem Protobuf-VarInt-Datentyp auseinandersetzen. Nützlich war auch ein Javascript-basierendes Online-Decoder-Tool.

update users set external_id=rtrim(encode((chr(10)||chr(length(external_id))|| external_id ||chr(18)||chr(4)||'ldap')::bytea,'base64'),'=');

Eventuell lässt sich das aber auch gleich in der Ruby-Migrationsroutine mit erledigen

Config-files (geschwärzt)

Dex-Config

issuer: https://<external_url>/dex

storage:
  type: postgres
  config:
    host: <docker service name>
    port: 5432
    database: dex_db
    user: postgres
    password: <use same PW as for Greenlight?>
    ssl:
      mode: disable #Local connection only

web:
  http: 0.0.0.0:5556
    
oauth2:
  skipApprovalScreen: true #Sonst wird bei jedem Login gefragt, ob Greenlight auf Name und Email-Adresse zugreifen darf...

connectors:
- type: ldap
  name: OpenLDAP
  id: ldap
  config:
    # The following configurations seem to work with OpenLDAP:
    #
    # 3) LDAPS with certificate validation:
    host: <LDAP HOST>:636
    insecureNoSSL: false
    insecureSkipVerify: false
    #rootCAData: 'CERT'
    # ...where CERT="$( base64 -w 0 your-cert.pem )"
	# alternatively mount /etc/ssl/certs/ca-certificates.crt into the container and point to it with
	# rootCA: /etc/dex/ldap.ca

    # This would normally be a read-only user.
    bindDN: <...>
    bindPW: <...>

	# i18n!
    usernamePrompt: Benutzerkennung 

    userSearch:
      baseDN: ou=people,dc=example,dc=com
      filter: "(&(objectClass=person))"
      username: uid
      # "DN" (case sensitive) is a special attribute name. It indicates that
      # this value should be taken from the entity's DN not an attribute on
      # the entity.
      idAttr: uid
      emailAttr: mail
      nameAttr: cn

#    groupSearch:
#      baseDN: ou=Groups,dc=example,dc=org
#      filter: "(objectClass=groupOfNames)"
#
#      userMatchers:
#        # A user is a member of a group when their DN matches
#        # the value of a "member" attribute on the group entity.
#      - userAttr: DN
#        groupAttr: member
#
#      # The group name should be the "cn" value.
#      nameAttr: cn

staticClients:
- id: greenlight-v3
  redirectURIs:
  - 'https://<Greenlight external URL>/auth/openid_connect/callback'
  name: 'Greenlight v3'
  secret: <Same as in GLv3 env>

Greenlight-Environment

#...
### EXTERNAL AUTHENTICATION METHODS
#
# Same as in Dex-Config:
OPENID_CONNECT_CLIENT_ID=greenlight-v3
OPENID_CONNECT_CLIENT_SECRET=<same as in Dex Config>
OPENID_CONNECT_ISSUER=https://<external_url>/dex
OPENID_CONNECT_REDIRECT=https://<Greenlight eternal URL>
#...

Docker-compose section for dex

  dex:
    image: dexidp/dex:v2.37.0
    container_name: dex
    volumes:
      - /opt/dex/config-ldap.yaml:/etc/dex/config.docker.yaml
    # perhaps use host's CA-Certificates
    #  - /etc/ssl/certs/ca-certificates.crt:/etc/dex/ldap.ca

Nginx location

Da es nicht so leicht ist, eine nginx-Config als Dex-Reverse Proxy zu finden, hab ich eine für Greenlight v3 kopiert und angepasst. Mag sein, dass im folgenden das eine oder andere Setting zu viel ist, geschadet hat es aber nicht:

location  /dex {
        proxy_pass http://dex:5556;
    proxy_read_timeout 60s;
    proxy_redirect off;

    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Cookie "$http_cookie; ip=$remote_addr";
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_http_version 1.1;

    proxy_headers_hash_max_size 512;
    proxy_headers_hash_bucket_size 128;

    proxy_buffer_size 128k;
    proxy_buffers 4 256k;
    proxy_busy_buffers_size 256k;

    client_max_body_size 30m;

}
Select a repo