Code

Site Confluence SSL via IIS

Publié le mercredi mercredi 12 février 2020
Identicon de monjici
Par monjici
Blogueur du dimanche

Un jour j'ai décidé d'avoir mon propre site Confluence. J'étais loin de me douter que ce serait toute une aventure. Mon but ultime: avoir un site sécurisé sur lequel je peux me connecter pour gérer mon calendrier familial et stocker mon livre de recettes. Simple, non ? Pas autant que je l'aurais souhaité, mais je suis éventuellement arrivé au résultat final voulu.

Il y a eu plusieurs embûches. La première était au niveau du matériel. Confluence étant basé sur la plateforme Java, il fallait lui réserver de la mémoire RAM, BEAUCOUP de mémoire pour un simple calendrier visité par deux personnes. Je ne m'en suis pas rendu compte au départ, mais les multiples crash quotidiens m'ont forcé à y jeter un coup d'oeil. Après avoir ajouté de ma mémoire au serveur, et alloué 4 GB à confluence, cet embûche fût chose du passé.

La prochaine embûche fut au niveau technique. Il me fallait un certificat SSL pour sécuriser la connexion au site. Ce n'est pas compliqué en tant que tel, un gros merci à letsencrypt, mais les ports par défaut (80 et 443) étant déjà utilisés par IIS, il me fallait utiliser IIS comme proxy pour me rendre à confluence/tomcat de façon transparente. Chaque éléments pris séparément sont simples, mais rabouter tout cela ensemble ne l'est pas. Voici donc la liste des étapes requises pour arriver à mon but, code et configurations incluses.

  1. Créer un site dans IIS. Nommons le Confluence. Assurez-vous d'avoir le module d'extension URL rewriter. Pour IIS 10, il vous faudra aussi ARR (Application Request Routing) 3.0.
  2. Ajoutez les règles d'URL rewriting. La première règles est inutile si vous avez ARR. La deuxière redirige toutes les reqûetes vers https://localhost:8443/{R:1}, qui est l'URL sécurisé local de Confluence; le votre peut être différent. Notez bien que la deuxième règle tien aussi en compte d'ignorer le chemin ".well-known". Ce dernier est utilisé par letsencrypt pour l'étape de validation lors de la génération d'un certificat d'encryption et cette étape se fait au niveau d'IIS.
<?xml version="1.0" encoding="UTF-8"?>
 <configuration>
      <system.web>
        <httpRuntime maxRequestLength="104857600" executionTimeout="360"  enableVersionHeader="false" />
      </system.web>
    <system.webServer>
        <rewrite>
            <rules>
              <!--
               <rule name="https redirect">
                  <match url="(.*)" ignoreCase="false" />
                     <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="false" />
                     </conditions>
                  <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}{REQUEST_URI}" />
               </rule>
               -->
                <rule name="Confluence" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_URI}" negate="true" pattern=".well-known(.*)" ignoreCase="true" />
                    </conditions>
                    <action type="Rewrite" url="https://localhost:8443/{R:1}" />
                </rule>
            </rules>
        </rewrite>
        <security>
            <requestFiltering allowDoubleEscaping="true">
                <requestLimits maxAllowedContentLength="104857600" />
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>
  1. Changer la configuration des connecteurs de Confluence. Dans server.xml (C:\Program Files\Atlassian\Confluence\conf), modifiez les deux connecteurs pour prendre en compte l'accès via un proxy. Pour le premier, seulement besoin d'ajouter proxyname, proxyport et scheme.
<Connector port="8090" connectionTimeout="20000" redirectPort="8443"
    maxThreads="48" minSpareThreads="10"
    enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
    protocol="org.apache.coyote.http11.Http11NioProtocol"
    proxyName="confluence.grandmenhir.com" proxyPort="80" scheme="http" />

Pour le deuxième, plusieurs changements/ajouts sont requis.

Original :

<Connector port="8090" connectionTimeout="20000" redirectPort="8443"
    maxThreads="48" minSpareThreads="10"
    enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
    protocol="org.apache.coyote.http11.Http11NioProtocol"
    scheme="https" secure="true" proxyName="<subdomain>.<domain>.com" proxyPort="443"/>

Final (remplacez <IIS confluence web path> pour le répertoire Web de confluence dans IIS):

<Connector port="8443" maxHttpHeaderSize="8192"
    maxThreads="150" minSpareThreads="25"
    protocol="org.apache.coyote.http11.Http11NioProtocol"
    enableLookups="false" disableUploadTimeout="true"
    acceptCount="100" scheme="https" secure="true"
    clientAuth="false" sslProtocols="TLSv1,TLSv1.1,TLSv1.2" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2" SSLEnabled="true"
    URIEncoding="UTF-8" keystorePass="changeit" keystoreFile="<IIS confluence web path>\.keystore"  keystoreType="PKCS12"
    proxyName="confluence.grandmenhir.com" proxyPort="443" />

Portez attention aux keystorePass, keystoreFile et keystoreType. Ceux-ci seront référez lors d'une des étapes suivantes.

  1. Générer le certificat SSL pour IIS. Grâce à Let's Encrypt, c'est tout à fait gratuit. Pour leur v2 et pour un client sur Windows, je vous suggère win-acme. https://pkisharp.github.io/win-acme/. Une fois téléchargé et décompressé, changez le fichier settings.config pour permettre l'exportation de clé privée. Cette étape est inportante car, comme on le verra plus bientôt, nous en aurons aussi besoin au delà d'IIS.
<setting name="PrivateKeyExportable" serializeAs="String">
    <value>True</value>
</setting>

Vous pouvez maintenant ouvrir une console Powershell entant qu'administrateur et exécutez wacs.exe. Choisissez l'option N pour nouveau certificat, ensuite l'option 1 pour single binding, ensuite le numéro de votre site. Si tout s'est bien passé, vous aurez un certificate dans IIS relié à une nouvelle liaison sur le port 443 de ver application.

  1. La partie la plus compliquée reste à faire, mais je vous la donne toute cuite dans le bec. Il faut maintenant connecter le tout en exportant le certificat de IIS et en l'important dans Confluence/tomcat. Après plusieurs itérations, je susi arrivé avec le script suivant que fait le tout pour vous. Remplacez <script Path> pour le répertoire dans lequel vous sauvegarderez le script et <IIS confluence web path> pour celui du site Web dans IIS.
 # Export PFX from Windows Certificate store to file
Write-Host "Exporting PFX to file"
$pfxPath = "<script Path>\Confluence.pfx"
Remove-Item $pfxPath
$pwd = ConvertTo-SecureString -String "changeit" -Force -AsPlainText
$thumbprint = (Get-ChildItem -Path "cert:\LocalMachine\WebHosting" | Where-Object { $_.Subject -match "confluence.grandmenhir.com" }).Thumbprint
$certpath = "cert:\LocalMachine\WebHosting\$thumbprint"
Export-PfxCertificate -cert $certpath -Password $pwd -FilePath $pfxPath | Out-File <script Path>\ConfluenceExport.txt

#  Change context to the JRE
C:
cd "\Program Files\Atlassian\Confluence\jre\bin"

#  Get alias from certificate in PFX
Write-Host "Getting certificate alias"

#  Output PFX content to file
.\keytool -list -keystore "<script Path>\Confluence.pfx" -storepass changeit -noprompt | Out-File <script Path>\ConfluenceList.txt
$confluenceList = get-content <script Path>\ConfluenceList.txt

#  Parse content to get alias (guid)
$confluenceSrcAlias = $confluenceList | Select-String -Pattern '{[-0-9A-F]+?}' -AllMatches | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value

#  Import new certificate
Write-Host "Importing $confluenceSrcAlias certificate"
.\keytool -importkeystore -srckeystore <script Path>\Confluence.pfx -destkeystore "<IIS confluence web path>\.keystore" -srcstoretype pkcs12  -deststoretype JKS -srcalias $confluenceSrcAlias -destalias tomcat -srcstorepass changeit -deststorepass changeit -noprompt

#  Restarting confluence
cd "\Program Files\Atlassian\Confluence"
.\stop_service.bat
.\start_service.bat

#  Put context back to the original folder
D:

En gros, les détails sont dans les commentaires. IIS peut maintenant recevoir des requêtes sécurisées et parler à Confluence de façon sécurisée.

  1. Automatisé les renouvellements. À chaque fois que le certificat SSL sera renouvellé, vous devrez ré-exécuter le script précédant. Je vous suggère de l'ajouter comme seconde étape dans la tâche créée par l'outil client wacs pour que vous n'ayez pas à vous en préoccuper.

En conclusion, toute cette complexité aurait pu être évitée si Confluence était directement exposé au Web sur le port 8443. Mais ceci n'était pas le résultat que je recherchais. Cela m'a permis de creuser et d'apprendre un peu plus sur l'interconnexion de la chaîne complète d'une requête sécurisée via proxy vers Confluence. J'espère que ça vous a été utile ou, du moins, informatif.

Commentaires

Vous devez être connecté pour ajouter un commentaire.