QGIS データを Web で表示 #10 - https 化と同一オリジン化

QGIS で作成したデータ（"プロジェクト"）を Web ページで表示する方法について、ノウハウを共有します。

第3回から第6回までで QGIS Server を設置し、QWC2 (QGIS Client 2) によって QGIS プロジェクトを表示する Web 地図アプリを作成し、MapCache を使って実用に耐えるパフォーマンスを確保しました。

- [QGIS データを Web で表示 #3 - QGIS Server](https://qiita.com/softark/items/c1da4f9a52e6727a5e97)
- [QGIS データを Web で表示 #4 - QWC2](https://qiita.com/softark/items/88ac73163cff278063a3)
- [QGIS データを Web で表示 #5 - QWC2（続）](https://qiita.com/softark/items/9d172c9cd6447d13ff0d)
- [QGIS データを Web で表示 #6 - MapCache](https://qiita.com/softark/items/0279178a484b451b15a5)

更に QWC2 の外観と機能のカスタマイズを3回連続で行ってきました。

- [QGIS データを Web で表示 #7 - QWC2（続々）](https://qiita.com/softark/items/c0e7bc72a07ad2aa85ac)
- [QGIS データを Web で表示 #8 - QWC2（続々々）](https://qiita.com/softark/items/cf7c4262b7377927ec1b)
- [QGIS データを Web で表示 #9 - QWC2（続々々々）](https://qiita.com/softark/items/f48e31e7d1ef9623d3ec)

今回は一旦 QWC2 のカスタマイズを中断して、Web 地図アプリの `https` 化と同一オリジン化を行います。

長々と続く QWC2 カスタマイズ作業に飽きてきたということもありますが、QWC2 に `https` でないと動作しない機能があったり、QGIS Server が同一オリジンでないと動作に支障があったりすることに気付いたからでもあります。

## 1. 基本方針

これまでは以下のように QWC2, QGIS Server, MapCache をポートによってルーティングしてきました。

```
-- nginx(PORT 80)    -- /         = QWC2 運用版

-- nginx(PORT 8082)  -- /         = QGIS Server

-- httpd(PORT 8080)  -- /mapcache = MapCache

-- nodejs(PORT 8081) -- /         = QWC2 開発版
```

今後は、ポートによるルーティングからパスによるルーティングに移行します。

```
-- nginx(PORT 443) ----- /       = Landing Page
              |
              +--------- /map/   = QWC2 運用版
              |
              +--------- /qsv/   = QGIS Server
              |
              +--------- /mc/ -- httpd(PORT 8080) -- /mc  = MapCache
                       
-- nodejs(PORT 8081) -- / ... QWC2 開発版
```

MapCache については、`nginx` で直接に駆動することも可能なようですが、方法がよく分らないので、現行の `httpd` 設定はあまり変更せず、`nginx` をリバース・プロキシとして使用して、同一オリジン化を行います。

## 2. nginx の設定

`/etc/nginx/conf.d/webgis.conf` を次の内容に変更します。

```nginx
# gis.vmware ... QGIS Web Client 2 / QGIS Server / MapCache
server {
    listen 80;
    server_name webgis.mydomain;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name webgis.mydomain;

    ssl_certificate /etc/pki/tls/certs/mydomain.crt;
    ssl_certificate_key /etc/pki/tls/certs/mydomain.key;

    # CORS を許可
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

    # Landing Page
    location / {
        root /var/www/qwc2;
        index index.html;

        error_log /var/log/nginx/webgis-error.log;
        access_log /var/log/nginx/webgis-access.log;
    }

    # QWC2
    location /map/ {
        root /var/www/qwc2/map;
        index index.html;

        error_log /var/log/nginx/map-error.log;
        access_log /var/log/nginx/map-access.log;
    }
    
    # QGIS Server
    location /qsv/ {
        gzip off;
        include fastcgi_params;

        location /qsv/isg/ {
            fastcgi_pass unix:/run/qgis-server-isg.sock;
            error_log /var/log/nginx/isg-error.log;
            access_log /var/log/nginx/isg-access.log;
        }
    }
    
    # MapCache
    location /mc/ {
        proxy_set_header    Host                $host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto   $scheme;
        proxy_pass          http://gis.vmware:8080/mc/;
    }
}
```

上記はローカルの開発サーバの設定で、SSL サーバ証明書はいわゆる「オレオレ証明書」です。運用環境では `Let's Encrypt` を使用する予定です。

CORS 許可の設定は、運用環境では不要な筈ですが、開発環境では必要です。

## 3. httpd の設定

MapCache 用の `Httpd` の設定は従来のものとほとんど変りません。

```apache
<IfModule mapcache_module>
    <Directory "/mc">
        Require all granted
    </Directory>
    MapCacheAlias /mc "/etc/mapcache.xml"
</IfModule>
```

## 4. サーバ URL の変更

QGIS Server と MapCache の URL が変ります。

- QGIS Server
    - `"http://webgis.mydomain:8082/"` => `"https://webgis.mydomain/qsv/"`
- MapCache
    - `"http://webgis.mydomain:8080/mapcache/"` => `"https://webgis.mydomain/mc/"`

従って、以下の構成ファイルにおいて、サーバ URL の修正が必要です。

- `"/etc/mapcache.xml"` ... MapCache 構成ファイル
- `"qwc2-demo-app/themesConfig.json"` ... QWC2 テーマ構成ファイル
- `"qwc2-demo-app/static/config.json"` ... QWC2 構成ファイル

## 5. 開発環境での障害をねじ伏せる

開発環境では、上記のように `https` 化を行うと、「オレオレ証明書」を使っていることに起因する障害が発生しますので、対応が必要になります。

### 5-1. "yarn start", "yarn run prod" が動かなくなる

`"yarn start"` および `"yarn run prod"` がともに途中でエラーを吐いて終了します。調べてみると、これらから呼び出されている `"themesConfig.js"` が QGIS Server からテーマ情報を取得しようとしたときに

```
Error: unable to verify the first certificate
```

というエラーで異常終了していました。QGIS Server の「オレオレ証明書」なんか信じられないわ、ということですね。ごもっとも。

#### 5-1-1. 対策

`qwc2-demo-app/qwc2/scripts/themesConfig.js` を以下のように修正します。

```diff_javascript
    /**
     * Copyright 2016-2024 Sourcepole AG
     * All rights reserved.
     *
     * This source code is licensed under the BSD-style license found in the
     * LICENSE file in the root directory of this source tree.
     */
    
+   process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
    
    const urlUtil = require('url');
    const axios = require('axios');
    ...
```

「確認の取れない証明書でも拒否しない」ということですね。

推奨される事ではないので、`"themesConfig.js"` も "Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification." という警告を表示します。

しかし、`"themesConfig.js"` は開発専用のツール・プログラムです。運用時にダウンロードされてエンド・ユーザのブラウザで動作するプログラムとは異なりますので、特に問題は無いはずです。

### 5-2. MapCache でキャッシュ・データの作成が出来なくなる

MapCache でキャッシュ・データの作成が出来なくなります。`mapcache_seed` プログラムを使用してもダメです。

これは、MapCache が QGIS Server から地図画像を取得するときに使用している `curl` コマンドが「オレオレ証明書」では信用ならないと言って異常終了するためです。

#### 5-2-1. 対策

`/etc/pki/tls/certs/ca-bundle.crt` (シンボリック・リンク。実体は `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`）の先頭に「オレオレ証明書」(`mydomain.crt`) を追加します。

これで `curl` が文句を言わないようになります。

これも勿論、開発環境だけのチートです。

なお、この対策が `"themesConfig.js"` にも効くかと思ったのですが、何故かダメでした。

## And so, what's next?

前回約束したところに従って、QWC2 のメニュー項目の残りを片付けます。なお、次回で一連の記事を完結させます。

- [QGIS データを Web で表示 #11 - QWC2（終り）](https://qiita.com/softark/items/b4b36e24b49dc10280a0)