Apache2.4でLDAP認証用のリバースプロキシを作る with Docker

## 目次
- [[目次] Prometheusで監視システムを作る with Docker](https://qiita.com/Esfahan/items/7dc780501f418a71ad9d)

## 概要
Apache2.4でLDAP認証をするリバースプロキシをDockerで作る。
この記事では、PrometheusのコンテナにLDAP認証をかける例を書く。Prometheusの環境構築は以下を参照。（ちなみにPrometheus本体に認証システムなどはない）

参考：[Prometheusを使った監視システムをDockerで作る](https://qiita.com/Esfahan/items/0feaedfd771f49ac7ee4)

## ディレクトリ構造

```
├── docker-compose.yaml
├── .env
├── prometheus
│   └── (省略)
└── rproxy
    ├── conf
    │   └── ldap.conf
    └── Dockerfile
```
## docker-compose.yaml
Prometheusコンテナの接続元を127.0.0.1に制限する。

```yaml:docker-compose.yaml
version: '3'
services:
  # Prometheusコンテナ
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    hostname: prometheus
    volumes:
      - ./prometheus:/etc/prometheus
      - metrics_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yaml'
    ports:
      # 接続元を127.0.0.1に制限する
      - 127.0.0.1:9090:9090
    restart: always

  # リバースプロキシコンテナ
  rproxy:
    container_name: rproxy
    build:
      context: ./rproxy
      dockerfile: Dockerfile
    env_file:
      - .env
    volumes:
      # LDAP接続のためのCA証明書をmount。適宜パスを変更。不要な場合は省略。
      - /etc/pki/tls/certs/ca-bundle.crt:/etc/ssl/certs/ca-certificates.crt
    ports:
      - "8080:80"
    restart: always

volumes:
  metrics_data:
    external: true
```

## Dockerfile

```Dockerfile:rproxy/Dockerfile
FROM httpd:2.4

RUN apt-get update -y
RUN apt-get install -y libapache2-mod-webauthldap
RUN mkdir /usr/local/apache2/conf/include/ &&  echo 'Include conf/include/*.conf ' >> /usr/local/apache2/conf/httpd.conf

COPY ./conf/*.conf   /usr/local/apache2/conf/include/
```

## httpdのconf

```conf:rproxy/conf/ldap.conf
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
LoadModule ldap_module modules/mod_ldap.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

LDAPVerifyServerCert off

# Prometheus
<VirtualHost *:80>
    <Location />
        LogLevel info
        AuthName "Prometheus Auth"
        AuthType Basic
        AuthBasicProvider ldap
        AuthLDAPUrl ${LDAP_URL}
        AuthLDAPBindDN ${LDAP_BIND_DN}
        AuthLDAPBindPassword ${LDAP_PASSWORD}
        Require valid-user
        # Proxyするホスト名。対象のDockerコンテナのhostnameとportを指定する。
        ProxyPass http://prometheus:9090/
        ProxyPassReverse http://prometheus:9090/
    </Location>
</VirtualHost>
```

## .env
LDAPの接続情報を書く。

```ini:.env.example
LDAP_URL=ldaps://your_ldap_server.com/o=xxxx,ou=xxxx,dc=xxxx
LDAP_BIND_DN=cn=xxxx,ou=xxxx,dc=xxxx
LDAP_PASSWORD=password
```

## up

```console
$ sudo docker-compose up -d --build
```

## 動作確認
### LDAP確認
ブラウザでrproxyコンテナの8080ポートへ接続する。
http://example.com:8080/

ユーザー名、パスワードのpromptが出るので、LDAP用個人のアカウントを入力する。
URLが:8080のまま、Prometheusの画面が表示されることを確認。

### Prometheusコンテナ確認
ブラウザからPrometheusコンテナに直接接続できない(ERR_CONNECTION_REFUSED)ことを確認。
http://example.com:9090/

## Debug方法
### LDAP接続ができているのか確認する方法
rproxyコンテナに以下をインストールし、ldapsearchコマンドでLDAP接続ができるか確認する。

```console
$ echo '\nHOST your_ldap_server.com\nPORT 636\nTLS_REQCERT allow' >> /etc/ldap/ldap.conf
$ apt-get update -y
$ DEBIAN_FRONTEND=noninteractive apt-get install -y slapd ldap-utils
```

CentOSの場合

```
$ sudo yum install openldap-clients
```

接続確認

YOUR_USER_NAMEには自分のLDAPアカウントを入れる。

```bash
$ ldapsearch -x -W -s one \
      -H ldaps://your_ldap_server.com \
      -b "o=xxxx,ou=xxxx,dc=xxxx" \
      -D "cn=xxxx,ou=xxxx,dc=xxxx" "(cn=YOUR_USER_NAME)" \
      -d 1

ldap_url_parse_ext(ldaps://your_ldap_server.com)
ldap_create
ldap_url_parse_ext(ldaps://your_ldap_server.com:636/??base)
Enter LDAP Password: # ${LDAP_PASSWORD}を入力。YOUR_USER_NAMEのパスワードではない。

# 中略
connect success
```

`connect success` になれば成功。
`ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)`となったら失敗。