Apache Guacamoleをdocker-composeで構築する

# 感想
- ブラウザだけあればリモートアクセスが出来そう（利用者がうれしい）
- 操作ログや画面操作を動画で残すことが出来そう（管理者がうれしい）
- docker版だとTomcatとか諸々のライブラリのインストールを考えなくて良くて構築が楽っぽい（自分がうれしい）

# Apache Guacamoleとは
OSSのリモートアクセスゲートウェイソフトで、クライアントはHTML5対応のWEBブラウザだけで利用できる。使える接続プロトコルはVNC,RDP,SSH,TELNETがあり、Apache License、Version 2.0が適用されたOSS。またTOTPによるMFA（個人的に最近気に入っている）もできる。詳細はこちら[公式](https://guacamole.apache.org)にて。

#### 構成イメージ
<img width="379" alt="スクリーンショット 2020-01-13 10.02.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317297/ada1e309-1eff-6cef-c1ad-c24eca273bbd.png">
※画像は[公式](https://guacamole.apache.org/doc/gug/guacamole-architecture.html)より。

# きっかけ
仕事で使っているリモートアクセス環境が、Windows Server 2008サポート終了のあおりを受けて更新しないといけなくなった。この際なのでセキュリティレベルを確保しつつ、コストを抑えた構成を考えようと思いついた。Windows OSからLinuxへ、有償シンクラソフトからOSSのApache Guacamoleへ。あわせてWEBブラウザだけでクライアント側に専用ソフトが不要なので、今まで温めていたアイデアが実現出来そうと言う淡い期待があった。今回はその際に実施した検証メモ。


# 前提

・環境
　検証用環境

・OS
　Ubuntu 18.04

・その他
　Docker and Docker-Compose はインストール済み。

# 適当にdocker-compose.ymlを作る

公式ドキュメントの手順を読むと、３種類のコンテナイメージを起動する必要がありそうなので、docker-composeで構築することにした。※以下のコンテナの役割は[公式](https://guacamole.apache.org/doc/gug/guacamole-docker.html)をGoogle翻訳。

#### guacamole/guacd
リリースされたguacamole-serverソースから構築されたguacdデーモンを提供し、VNC、RDP、SSH、およびtelnetをサポートします。

#### guacamole/guacamole
Tomcat 8内で実行されているGuacamole WebアプリケーションにWebSocketのサポートを提供します。guaker、MySQL、PostgreSQL、LDAPなどに接続するために必要な構成は、Dockerリンクまたは環境変数に基づいてイメージが開始されるときに自動的に生成されます。

#### mysql または postgresql
Guacamoleが接続構成データの認証と保存に使用するデータベースを提供します。

#### docker-compose.ymlの中身

本番環境はもうちょっと考える必要がある。
nginxはとりあえず的な感じで。

```docker-compose.yml
version: "3"
services:

  postgres:
    image: postgres:latest
    restart: unless-stopped
    environment:
      PGDATA: /var/lib/postgresql/data/guacamole
      POSTGRES_DB: guacamole_db
      POSTGRES_PASSWORD: guacamole1234567890
      POSTGRES_USER: guacamole_user
    volumes:
      - ./pginit:/docker-entrypoint-initdb.d
      - ./pgdata:/var/lib/postgresql/data

  guacd:
    image: guacamole/guacd:latest
    restart: unless-stopped

  guacamole:
    image: guacamole/guacamole:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      GUACD_HOSTNAME: guacd
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_HOSTNAME: postgres
      POSTGRES_PASSWORD: guacamole1234567890
      POSTGRES_USER: guacamole_user
    depends_on:
      - postgres
      - guacd

  nginx:
    image: nginx:latest
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
```
#### default.confの中身

ディレクトリを作って、そこに置く。

```
# mkdir -p ./nginx/conf.d
```

```default.conf
server {
    listen       80;
    server_name  localhost;
 
    location /guacamole/ {
        proxy_pass http://guacamole:8080/guacamole/;
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
 
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
```

# 初期化用のSQL作成

PostgreSQLは公式Dockerイメージの初期化機能を使います。初期化スクリプト（.sql or .shとか？）が/docker-entrypoint-initdb.dディレクトリ内で見つかった場合に1度だけ実行されるらしいので、そこに作成しておく。


```
# mkdir ./pginit
# chmod -R +x ./pginit
# docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > ./pginit/initdb.sql
```

# 起動
```
# docker-compose up -d
# docker-compose ps
        Name                      Command               State           Ports         
--------------------------------------------------------------------------------------
gucamole_guacamole_1   /opt/guacamole/bin/start.sh      Up      0.0.0.0:8080->8080/tcp
gucamole_guacd_1       /bin/sh -c /usr/local/guac ...   Up      4822/tcp              
gucamole_nginx_1       nginx -g daemon off;             Up      0.0.0.0:80->80/tcp    
gucamole_postgres_1    docker-entrypoint.sh postgres    Up      5432/tcp 

# docker-compose logs -f
```

# 動作確認

http://<IPアドレス or ホスト名＞/guacamole/

ユーザー名：guacadmin 
パスワード：guacadmin

でログイン。

<img width="298" alt="スクリーンショット 2020-01-13 13.35.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317297/373a6282-02e9-7372-5363-d709804dd127.png">

# TOTPの設定

[公式（ver1.0.0の場合）](https://guacamole.apache.org/releases/1.0.0/)からTOTP用 jarファイルをダウンロードししてくる。その後、${GUACAMOLE_HOME}/extensions ディレクトリに置いて起動させる必要がある。なのでdocker-compose.ymlファイルをちょっと編集し3行追加。

```docker-compose.yml（抜粋）
  guacamole:
    image: guacamole/guacamole:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      GUACD_HOSTNAME: guacd
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_HOSTNAME: postgres
      POSTGRES_PASSWORD: guacamole1234567890
      POSTGRES_USER: guacamole_user
      GUACAMOLE_HOME: /etc/guacamole  ⬅️①
    volumes:                          ⬅️②
      - ./guacamole:/etc/guacamole    ⬅️③
    depends_on:
      - postgres
      - guacd
```

ディレクトリを作る。

```
# mkdir -p ./gucamole/extensions
```

ダウンロード＆解凍したTOTP用jarファイルをコピー。

```
# cp ~/Downloads/guacamole-auth-totp-1.0.0/guacamole-auth-totp-1.0.0.jar ./guacamole/extensions
```

再起動

```
docker-compose down
docker-compose up
```

初回 or 次回の認証後、登録画面が表示されます。あとは‎「Google Authenticator」や‎「IIJ SmartKey」で登録しておくと、次回以降は6桁のコード入力を求められます。

<img width="594" alt="スクリーンショット 2020-01-13 14.11.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317297/866a0e9d-2b5a-1f56-b5ed-9468a807044c.png">

# ちょっとハマったとこ

ユーザにパスワード変更権限を付与しておかないとこのTOTPが有効にならないようです。

<img width="301" alt="スクリーンショット 2020-01-13 13.55.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317297/451d192a-0446-ab61-511a-d57eef1d81b0.png">