GeekFactory

int128.hatenablog.com

Windows上のJenkinsでドメイン認証を使う

Active Directory環境にあるJenkinsをドメイン認証(統合Windows認証)でシングルサインオン化する方法について説明します。

ここでのシングルサインオンは、ドメインアカウントでWindowsにログオンしていて、WebブラウザでJenkinsを開くと自動的にログイン済み状態になることを指します。シングルサインオンによって利用者の負担や共用アカウントの危険性を軽減できます。

前提

下記の環境で確認しています。

Apache httpdの設定

リバースプロキシにmod_proxy_ajpを使うと認証情報を渡せます。ポイントは以下です。

  1. Windows認証を有効にする。
  2. AJPのリバースプロキシを有効にする。
# httpd.conf
LoadModule sspi_auth_module lib/modules/mod_auth_sspi.so
LoadModule proxy_module lib/modules/mod_proxy.so
LoadModule proxy_ajp_module lib/modules/mod_proxy_ajp.so

<Location />
  # Windows認証
  AuthType SSPI
  SSPIAuth On
  SSPIAuthoritative On
  SSPIDomain DOMAIN
  SSPIOmitDomain On
  SSPIOfferBasic On
  Require valid-user
</Location>

<Location /jenkins>
  # リバースプロキシ
  ProxyPass ajp://127.0.0.1:8009/jenkins
</Location>

<Location /svn>
  # Subversionとか同居できます
</Location>

Apache Tomcatの設定

Apache httpdからAJPリクエストを受け取れるようにします。ポイントは以下です。

  1. AJPコネクタを有効にする。
  2. AJPで認証情報を受け取れるように tomcatAuthentication 属性を設定します。
<!-- server.xml -->
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="100" minSpareThreads="10"/>

    <Connector executor="tomcatThreadPool" address="127.0.0.1" URIEncoding="UTF-8"
               tomcatAuthentication="false"
               port="8009" protocol="AJP/1.3" />
    <Connector executor="tomcatThreadPool" address="127.0.0.1" URIEncoding="UTF-8"
               port="18080" protocol="HTTP/1.1" />

Jenkinsの設定

Apache Tomcatの認証情報を使うようにします。

  • Jenkinsの管理
    • システムの設定
      • セキュリティを有効化にチェックを入れる

Apache httpdTomcatの設定がおかしい状態で上記を適用すると、AJP経由でJenkinsにログインできなくなる可能性があります。server.xmlでHTTPコネクタも残しておくことをおすすめします。

Jenkinsの代わりに後述するJSPでも認証結果を確認できます。

カラクリについて

AJPでリバースプロキシすると認証情報がサーブレットコンテナに伝わるようになります。具体的には HttpServletRequest.html#getRemoteUser() が認証済みのユーザ名を返すようになります。

java.lang.String getRemoteUser()

Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been authenticated. Whether the user name is sent with each subsequent request depends on the browser and type of authentication. Same as the value of the CGI variable REMOTE_USER.

HttpServletRequest (Java EE 6 )

このメソッドの戻り値はApache httpdの認証結果(REMOTE_USER)に依存するため、SSPI認証に限らずBasic認証などでも同じことができます。

下記のJSPでも挙動を確認できます。

<%@ page session="false" %>
<html>
<body>
request.getRemoteUser() = <%= request.getRemoteUser() %>
</body>
</html>