Arme-Leute-Rechteverwaltung mit SSL-Client-Zertifikaten

Für ein Pro­jekt ad­mi­nis­trie­re ich einen Ser­ver, auf dem ver­schie­de­ne Web­an­wen­dun­gen lau­fen. Si­cher­heits­po­li­cy ist, daß ein Zu­griff dar­auf nur über https und Cli­ent-Zer­ti­fi­ka­ten mög­lich sein darf - so weit, so ein­fach.
Eine der An­wen­dun­gen ist git­lab, eine git­hub-ähn­li­che We­bo­b­er­flä­che für git-Re­po­si­to­ries. Er­freu­li­cher­wei­se be­geis­ter­ten sich immer mehr Leute, die nicht di­rekt zum Pro­jekt ge­hör­ten, für git... und dann folg­te der Klas­si­ker: Es soll nun Leute geben, die aus­schlie­ß­lich auf git­lab, aber auf keine der an­de­ren An­wen­dun­gen zu­grei­fen kön­nen. Also mußte zu­sätz­lich zur Au­then­ti­sie­rung noch eine Aut­ho­ri­sie­rung her... aber wie? Die Rech­te­kon­trol­le soll­te auf Basis von URL (bzw. URL-Teil) sowie den Cli­ent-Zer­ti­fi­ka­ten er­fol­gen und au­ßer­dem "ab­wärts­kom­pa­ti­bel" zu den be­reits aus­ge­ge­be­nen Zer­ti­fi­ka­ten sein.
Wer eben­falls in eine sol­che Si­tua­ti­on kommt - fol­gen­de Mög­lich­kei­ten sind mir hier­zu ein­ge­fal­len:

Meh­re­re CAs

Das Zer­ti­fi­kat der CA, von wel­cher die Cli­ent-Zer­ti­fi­ka­te aus­ge­stellt sein müs­sen, wird mit­tels

SS­LCA­Cer­ti­fi­ca­te­Fi­le /pfad/zum/zertifikat.​crt

kon­fi­gu­riert. Diese Datei kann aber meh­re­re Zer­ti­fi­ka­te be­inhal­ten - Apa­che ak­zep­tiert dann Cli­ent-Zer­ti­fi­ka­te von all die­sen CAs. Eine Mög­lich­keit wäre somit ge­we­sen, eine neue CA für den ein­ge­schränk­ten Be­nut­zer­kreis auf­zu­set­zen; Nach­teil wäre je­doch (ab­ge­se­hen vom zu­sätz­li­chen Ver­wal­tungs­auf­wand), daß die Be­schrän­kung nur pro vhost mög­lich wäre. Oben­drein wird das ganze kom­pli­ziert, wenn man­che Be­nut­zer meh­re­re Zer­ti­fi­ka­te in­stal­lie­ren müs­sen.
Die Mög­lich­keit meh­re­rer CAs ist also ein in­ter­es­san­tes Fak­tum, aber keine Lö­sung für mei­nen An­wen­dungs­fall.

Zu­griffs­be­schrän­kung auf ein­zel­ne Zer­ti­fi­ka­te

Eine wei­te­re Mög­lich­keit be­steht in der Fake Basic Au­then­ti­ca­ti­on. Hier wird der Dis­tin­gu­is­hed Name des Zer­ti­fi­kats als User­na­me, sowie das Pass­wort "pass­word" an die Basic Au­then­ti­ca­ti­on durch­ge­reicht. Man kon­fi­gu­riert also den Zu­griffs­schutz für einen be­stimm­ten Pfad mit­tels

<Lo­ca­ti­on /your/web­path>
  SS­LOp­ti­ons         +Fake­Ba­si­cAuth
  Au­th­Ty­pe           Basic
  Au­th­Ba­sic­Pro­vi­der  file
  Re­qui­re            va­lid-user
  Aut­hU­ser­File       /path/to/your/httpd.​passwd
</Lo­ca­ti­on>

und ge­ne­riert eine pas­sen­de httpd.​passwd, z.B.
/O=My fancy com­pa­ny/CN=Hugo Han­sel:xx­j31ZMTZz­kVA
/O=My fancy com­pa­ny/CN=Co­lo­nel Panic:xx­j31ZMTZz­kVA
/O=My fancy com­pa­ny/CN=Ge­ne­ral Pro­tec­tion­fault:xx­j31ZMTZz­kVA

In mei­nem Fall wäre das zwar ein An­satz ge­we­sen, hätte aber be­deu­tet, daß ich jeden neuen Nut­zer des Diens­tes in der Zu­griffs­da­tei hätte nach­pfle­gen müs­sen - ein Auf­wand, den ich mir nicht antun woll­te.

Grup­pen/Rol­len mit­tels Re­gu­lar Ex­pres­si­on Matching

Nun also der von mir ge­wähl­te An­satz, wel­cher mir die ge­wünsch­te Fle­xi­bi­li­tät bie­tet und den­noch den Ver­wal­tungs­aufand ge­ring hält: Mit der Di­rek­ti­ve SS­L­Re­qui­re be­steht die Mög­lich­keit, auf den In­halt der Fel­der des Zer­ti­fi­kats zu prü­fen. In mei­nem Fall sah das fol­gen­der­ma­ßen aus:

<Lo­ca­ti­on /my/path>
  SS­L­Re­qui­re %{SS­L_CLI­EN­T_S_D­N_L} == "" or %{SS­L_CLI­EN­T_S_D­N_L} =~ m/^.*\+myser­vice\+.*$/
</Lo­ca­ti­on>

Beim Durch­se­hen der be­ste­hen­den Zer­ti­fi­ka­te hatte ich fest­ge­stellt, daß das Feld Lo­ca­li­ty Name in kei­nem der be­ste­hen­den Zer­ti­fi­ka­te be­nutzt wurde. Daher ent­stand die obige Regel: Sie er­laubt den Zu­griff, wenn das Feld ent­we­der leer ist (Kom­pa­ti­bi­li­tät zu den be­reits aus­ge­ge­be­nen Zer­ti­fi­ka­ten) oder aber den String "+myser­vice+" ent­hält.
Die Idee hin­ter "+myser­vice+": Es ist so mög­lich, auf ver­schie­de­ne Diens­te zu prü­fen. Als Trenn­zei­chen (wel­ches nicht im Name der Diens­te vor­kom­men darf) habe ich mich will­kür­lich für das Plus ent­schie­den. Somit be­kom­men Zer­ti­fi­ka­te, wel­che im Feld Lo­ca­li­ty Name eine An­ga­be wie "+myser­vice+", "+myser­vice+myo­ther­ser­vice+" oder "+ye­ta­no­ther­ser­vice+myser­vice+" be­inhal­ten, Zu­griff.
Eine wei­te­re Über­le­gung, die man bei die­sem An­satz an­stel­len soll­te: Kommt spä­ter ein neuer Dienst hinzu, muß man die Zer­ti­fi­ka­te der Leute, die auch Zu­griff er­hal­ten sol­len, aus­tau­schen. Sinn­vol­ler ist es, sich über ein Rol­len­kon­zept ge­dan­ken zu ma­chen und statt Be­zei­chern von Diens­ten Rol­len­na­men zu ver­wen­den. Mo­men­tan er­hal­ten Zer­ti­fi­ka­te mit "+stu­dent+" nur Zu­griff auf git­lab - soll­te es in Zu­kunft einen wei­te­ren Web Ser­vice geben, auf den alle Stu­den­ten zu­grei­fen sol­len, so muß nur die Aut­ho­ri­sie­rungs­re­gel in der Apa­che-Kon­fi­gu­ra­ti­on an­ge­pa­ßt wer­den - die be­reits an Stu­den­ten aus­ge­ge­be­nen Zer­ti­fi­ka­te müs­sen nicht ak­tua­li­siert wer­den.