セキュリティ要件に対応した Yellowfin コンテンツ埋め込みサイトの構築

### 概要
ブラウザ機能のセキュリティ強化などもあり、Yellowfin 埋め込みサイトを整備する際にも、セキュリティ面で色々と検討しなければいけない事項が増えてきています。
SSL 接続が必須な状況で、Yellowfin サーバーと、Yellowfin コンテンツを埋め込む Web サーバーの構築に関して記載しようと思います。今回は、Yellowfin および Web サーバーともに、Windows Server 上に構築すること前提とします。全体イメージは以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/72a63ee8-4792-423e-548c-9f332bc25365.png)

- Yellowfin を Windows サーバーで稼働させます。Yellowfin に SSL 接続できるように、Yellowfin が稼働する Tomcat に PKCS12 形式のファイルを配置します。同ファイルには、ルート証明書、サーバー証明書、秘密鍵を含みます。
- フロントに Apache for Windows を実装した Web サーバーを立て、html コンテンツを配置します。html コンテンツの中に、Yellowfin のダッシュボードを埋め込みます。Web サーバーに対して SSL 接続できるように、Apache にルート証明書、サーバー証明書、秘密鍵を配置します。
- エンドユーザーからは、ブラウザで html コンテンツを参照します。この際、html に埋め込まれた Yellowfin コンテンツには SSO ログインし、Yellowfin の Cookie が受け入れられるようにします。

以下で、それぞれの設定内容の詳細を説明します。

### Yellowfin の設定
Yellowfin が稼働する Tomcat に対して、SSL でアクセスできるように設定します。
そのために、キーストアを作成し、ルート証明書、サーバー証明書、秘密鍵をキーストアに格納します。

今回、AWS 上に環境を整えたのですが、発行済みの証明書と鍵は以下 3 点でした。Linux 環境で扱うためにはこのままの形式で問題無いのですが、Windows 環境で使用するためには、秘密鍵と証明書を PKCS12 形式のファイルに変換する必要があります。
|役割|ファイル名|
|---|---|
|ルート証明書|ca.crt|
|サーバー証明書|server.crt|
|秘密鍵|server.key|
|キーストア|server.keystore|

openssl を使って PKCS12 形式のファイルに変換します。Windows に openssl をインストールする手順に関しては、[こちら]( https://atmarkit.itmedia.co.jp/ait/articles/1601/29/news043.html)の情報を参考にさせていただきました。
コマンド例は以下の通りです。

```powershell:openssl
openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -certfile ca.crt
```

次に、PCCS12 形式のファイルにまとめられた秘密鍵と証明書を、Java KeyStore（JKS）に格納します。

```powershell:keytool
keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore server.keystore -deststoretype JKS
```

作成したキーストアを (Yellowfin)/appserver/conf/ 直下に保存します。

server.xml に以下の行を追加し、Tomcat がキーストアにアクセスできるように設定します。server.xml の修正手順に関しては、[サポートサイトの記事]( https://support.yellowfin.co.jp/hc/ja/articles/115012569308-HTTPS%E7%B5%8C%E7%94%B1%E3%81%A7Yellowfin%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)も合わせてご確認ください。

```xml:server.xml
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true"
        scheme="https" secure="true"
        keystoreFile="conf/server.keystore" keystorePass="changeit"
        clientAuth="false" sslProtocol="TLS"/>
```

ブラウザを立ち上げて、Yellowfin のログイン画面に https でアクセスできることを確認します。
例：https\://yellowfin.example.jp

Yellowfin に対して SSL 接続するために、今回は Yellowfin が稼働する Tomcat が証明書と秘密鍵を取り扱えるように設定しました。一方で、[『EC2にYellowfinのベストなテスト環境を構築するまでのメモ』](https://qiita.com/hadatuna/items/d0782d78498f535b08ca#ssl%E3%81%AE%E8%A8%AD%E5%AE%9A) や[『IIS をリバースプロキシに設定 － セキュアな Yellowfin 環境を構築』](https://qiita.com/ExtremeCarvFJ/items/134012d0af00f6355e16)で紹介されているように、Yellowfin エンジンと、Yellowfin にアクセスするための Web サーバーを別立てにし、Web サーバーで証明書と秘密鍵を管理する方法もあります。要件によって、適切な方法を選択いただければと思います。

### Web サーバーの設定
Windows Server 上で Apache を稼働させます。
Apache のインストールに関しては、[こちら](https://www.kkaneko.jp/tools/win/apacheinstall.html)の情報を参考にさせていただきました。上記情報を参考に、インストーラーのダウンロード、インストール、httpd.conf の初期設定まで実施します。重要な点として、httpd.conf に定義する ServerName を、証明書に定義されているドメイン名と一致させることです。

次に、SSL アクセスできるように設定します。

httpd.conf を開いて、以下 2 行のコメントを外し、必要なモジュールを有効にします。

```text:httpd.conf
LoadModule ssl_module modules/mod_ssl.so
Include conf/extra/httpd-ssl.conf
```

使用する証明書と秘密鍵は先ほどと同じで以下のものです。
|役割|ファイル名|
|---|---|
|ルート証明書|ca.crt|
|サーバー証明書|server.crt|
|秘密鍵|server.key|

分かりやすくするために、conf&yen;ssl.crt と conf&yen;ssl.key フォルダを作成し、ssl.crt フォルダにルート証明書とサーバー証明書を、ssl.key フォルダに秘密鍵をそれぞれ保存します。

conf&yen;extra フォルダ内の httpd-ssl.conf 開いて、先ほど格納した証明書と鍵の保管先を指定します。

```text:httpd-ssl.conf
SSLCertificateFile "${SRVROOT}/conf/ssl.crt/server.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/ssl.key/server.key"
SSLCACertificateFile "${SRVROOT}/conf/ssl.crt/ca.crt"
```

ブラウザを立ち上げて、Web サーバーに https でアクセスできることを確認します。
例：https\://web.example.jp

### 埋め込みコンテンツの作成
あくまで参考程度に、今回は以下のような記述で、HTML 内に Yellowfin ダッシュボードを埋め込んでいます。

```html:test.html
<!DOCTYPE html>
<html lang="ja">
  <meta charset="UTF-8">
  <title>Yellowfin embedded</title>
  <head>
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
  </head>
<body>
  <form method="post">
    <p><font size="7" color="red">Yellowfin埋め込み画面</font></p>
  </form>
  <div id="reportDiv"></div>
  <script>
    var authUserId = 'embed@yf.com';
    var authUserPass = 'test';
    var adminId = 'admin@yellowfin.com.au';
    var adminPassword = 'test';
    var orgId = '1';

    var body = {
      signOnUser: {
        userName: authUserId,
        password: authUserPass,
        clientOrgRef: orgId
      },
      noPassword: 'true',
      adminUser: {
        userName: adminId,
        password: adminPassword
      }
    };
    //encode to JSON
    var json_text = JSON.stringify(body);
    $.ajax({
    
      type: 'POST',
      contentType: "application/json;charset=UTF-8",
      data: json_text,
      crossDomain: true,
      url: "https://hoge.yellowfin.co.jp:8443/api/rpc/login-tokens/create-sso-token",
      headers: {
        'Authorization': 'YELLOWFIN ts=' + new Date().getTime() + ', nonce=123',
        "Accept": 'application/vnd.yellowfin.api-v2+json'
      },
      success: function (res, textStatus, jqXHR) {
      alert(res.securityToken);
        securityToken = res.securityToken;
	let url = 'https://hoge.yellowfin.co.jp:8443/JsAPI/v3?token=' + securityToken;
        let tp = 'text/javascript';
        let sc = document.createElement('script');
        sc.src = url;
        sc.type = tp;
        document.body.appendChild(sc);

        setTimeout(function () {
          yellowfin.showLoginPrompt = false;
          yellowfin.init().then(() => {
            yellowfin.loadDashboard({
              dashboardUUID: 'f20c11a1-4aa3-4a2c-925a-209ba032558f',
              element: document.querySelector('div#reportDiv')
            });
          });
        }, 1000);
      },
      error: function (responseData, textStatus, errorThrown) {
        alert("Error!");
      }
    });
  </script>
</body>
</html>
```
- html 内に記述した JavaScript の中で、SSO に必要な JSON データ (HEADER / BODY) を扱っています。詳細は[こちら](https://qiita.com/ExtremeCarvFJ/items/989a3c2bfa34ccdd177f)をご覧ください。
- JavaScript API を呼び出して、埋め込むコンテンツを定義しています。詳細は[こちら](https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=6591558)をご覧ください。
- jQuery を活用して、上記を非同期処理しています。

HTML ファイルに、test.thml という名前を付けて、Web サーバーの C:&yen;Apache24&yen;htdocs 直下に保管します。
これで、ブラウザを立ち上げて https://web.example.jp/test.html にアクセスすれば、埋め込み画面が表示されるはずです。
しかし、埋め込みコンテンツが表示されてこない可能性が大です。理由は、クロスサイト Cookie の扱いにあります。
Yellowfin は Cookie を使ってセッション管理をしています。Cookie を使ったコンテンツが Web 画面に埋め込まれているため、ブラウザのセキュリティ設定次第で動作しないことがあります。

### ブラウザ側の対応
##### Firefox
Firefox の場合、おそらく既定のままでは Yellowfin のコンテンツが表示されません。
アドレスバーの左端に、盾アイコンが見えるかと思います。これは、強化型トラッキングが有効になっていることを示します。Web サーバーと Yellowfin サーバーで、強化型トラッキングを無効化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/05f3c62a-06af-c4e5-75cf-2e8997ae86da.png)

盾アイコンをクリックして、「強化型トラッキング防止」をオフにします。盾アイコンが以下のように変われば大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/cbfa4178-8e53-17b8-37ab-272706230f3e.png)

##### Chrome
[設定] > [プライバシーとセキュリティ] > [サードパーティ Cookie] > [シークレット モードでサードパーティ Cookie をブロックする] を選択します。

##### Edge
[設定] > [プライバシー、検索、サービス] > [トラッキングの防止] > [バランス(推奨)] が選択されていれば大丈夫な感じです。

https で Web サイトにアクセスして、Yellowfin のコンテンツが埋め込まれていることが確認できます (下記 Chrome の例)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/510afd0c-0823-da74-a416-b202fe56e99e.png)

ブラウザはバージョンによって挙動が変わることが頻繁に起き得ます。うまく表示されない場合、セキュリティに関する設定を見直す必要があるかも知れません。

### 最後に
毎日のように、情報漏洩やらランサムウェアやら、セキュリティに関する事件が頻発していますね。ロシアや北朝鮮のハッカーたちの仕業も大きいようですな。有能なエンジニアのリソースを、もっと生産的なことに技術力を使ってくれればいいのにと思います。宇宙開発とか、地球温暖化防止とか。知らんけど。
おかげで、セキュリティ関連の設定がガチガチになってきて、そのための対応も増えてきてしまってます。

何はともあれ、我々はデータを有効的に活用できるようにしていきたいと思います。
では皆様、良いデータ分析を! Cheers, geeks!!