PlantUML-ServerをBasic認証付きで公開する

  • このエントリーをはてなブックマークに追加

plantuml-serverはdocker imageが既にあるので簡単に公開する事ができます。
外部サーバに立てると、誰でもアクセスできてしまうため、Basic認証を付けたいことがあります。WebのUIから使うだけならIDP連携でOAuth認証を入れてしまえば良いのですが、Visual Studio Codeのプラグインと連携させる場合は、OAuthは対応していないため、Basic認証にするしかありません。

docker-composeを利用して、nginxでbasic認証をかけてplantumlにproxyするのが簡単です。
そして、nginxのbasic認証に特化したイメージがあります ⇒ quay.io/dtan4/nginx-basic-auth-proxy

しかし、普通に設定すると、PlantUMLの画面でホスト名がplantuml:8080というホスト名になってしまいます。
これは、例えば、http://example.comにデプロイしたとして、Userhttp://example.comnginxhttp://plantuml:8080/PlantUMLのApplicationサーバ(Jetty or Tomcat) となり、PlantUML(Jetty)から見ると、plantuml:8080というホスト名でアクセスに来ているからです。

PlantUMLのコード

PlantUMLのコードでは、JSPのTagLibで次のように記述されています。

<c:set var="contextroot" value="${pageContext.request.contextPath}" />
<c:if test="${(pageContext.request.scheme == 'http' && pageContext.request.serverPort != 80) ||
(pageContext.request.scheme == 'https' && pageContext.request.serverPort != 443) }">
<c:set var="port" value=":${pageContext.request.serverPort}" />
</c:if>
<c:set var="scheme" value="${(not empty header['x-forwarded-proto']) ? header['x-forwarded-proto'] : pageContext.request.scheme}" />
<c:set var="hostpath" value="${scheme}://${pageContext.request.serverName}${port}${contextroot}" />
<c:if test="${!empty encoded}">
<c:set var="imgurl" value="${hostpath}/png/${encoded}" />
<c:set var="svgurl" value="${hostpath}/svg/${encoded}" />
<c:set var="txturl" value="${hostpath}/txt/${encoded}" />
<c:if test="${!empty mapneeded}">
<c:set var="mapurl" value="${hostpath}/map/${encoded}" />
</c:if>
</c:if>

<a href="${svgurl}">View as SVG</a>

pageContext.request.serverNameplantuml:8080になります。
一方、nginx-basic-auth-proxyでは、X-Forwarded-Hostを設定しています。(参考)

つまり、Jetty側でこのヘッダをHostとして扱えば良いわけです。
Jettyでは、X-Forwarded-xxの処理を良い感じに処理してくれるモジュールとしてhttp-forwardedがあります。

PlantUMLのJetty版の元のイメージはこちらを利用しており、
http-forwardedはデフォルトでは有効になっていませんが、/usr/local/jetty/etc/jetty-http-forwarded.xmlにあります。
そして、有効にするためには、--module=http-forwardedの引数を付ければ有効になります。

PlantUMLのDockerfileの定義は、Entrypointが/docker-entrypoint.sh。Commandがjava -jar /usr/local/jetty/start.jarです。
ここに引数を追加するには、command: java -jar /usr/local/jetty/start.jar --module=http-forwardedとすれば良いです。

docker-compose.yaml

こんな感じで。
ALLOW_PLANTUML_INCLUDEは、!includeで綺麗にするスタイルを外部ファイル化しており、毎回当てるので有効にしています。

version: "3.3"
services:
nginx-proxy:
image: quay.io/dtan4/nginx-basic-auth-proxy
ports:
- 80:80
environment:
BASIC_AUTH_USERNAME: test-user
BASIC_AUTH_PASSWORD: test-password
PROXY_PASS: http://plantuml:8080/
SERVER_NAME: proxy.internal
networks:
- container-link
plantuml:
image: plantuml/plantuml-server:jetty
command:
- "java"
- "-jar"
- "/usr/local/jetty/start.jar"
- "--module=http-forwarded"
environment:
- ALLOW_PLANTUML_INCLUDE=true
networks:
- container-link
networks:
container-link:

VS Codeのプラグインの設定

利用しているPlantUMLのPluginはこちら。

名前: PlantUML
ID: jebbs.plantuml
説明: Rich PlantUML support for Visual Studio Code.
バージョン: 2.14.5
パブリッシャー: jebbs
VS Marketplace リンク: https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml

次のように、RenderをLocalからPlantUMLServerにします。
そして、Serverにdocker-composeで起動したURLを設定します。Basic認証の情報はURLに入れる事ができるので、http://test-user:test-password@example.com/のように設定します。

参考