# 動的接続

## 概要

Keeperコネクションマネージャーでは、暗号化されたJSONファイルを使用して、任意のカスタムソフトウェアまたはサードパーティ製アプリケーションと連携するように設定できます。このJSONファイルでユーザーを認証すると同時にリモート接続へのアクセスを許可します。

## インストール <a href="#id-.providingconnectiondatafromexternalapplicationsv2.x-installingsupportforencryptedjsonauthenticat" id="id-.providingconnectiondatafromexternalapplicationsv2.x-installingsupportforencryptedjsonauthenticat"></a>

動的接続機能を使用するには、Keeperコネクションマネージャー用の暗号化JSON認証モジュールをインストールする必要があります。この機能を有効にするには、[keeper/guacamole](/keeper-connection-manager/jp/installation/docker-compose-install/keeper-guacamole.md)イメージ内のDocker Composeファイルの`JSON_*`パラメータを更新します。

`JSON_SECRET_KEY`

`JSON_TRUSTED_NETWORKS`

これらのパラメータを有効にすると、Keeperコネクションマネージャーの認証拡張機能がロードされます。この拡張機能は、HMAC/SHA-256を使用して署名され、AES-128 CBCで暗号化されたJSONを使用してユーザーを認証します。このJSONには、認証しているユーザーを表す情報がすべて (アクセス可能なすべての接続を含む) 含まれているため、この拡張機能は、Keeperコネクションマネージャーを外部アプリケーションと連携する簡単な手段となります。

`JSON_SECRET_KEY`は128ビットで、以下のように32桁の16進値で指定する必要があります。

`4c0b569e4c96df157eee1b65dd0e4d41`

この鍵は、ランダムなものであれば基本的に何でも構いません。このような鍵を生成する簡単な方法は、「md5sum」ユーティリティにパスフレーズをechoコマンドで入力することで、パスフレーズから128ビット鍵を生成するためにOpenSSL自体が使用している手法となります。以下に例を示します。

```
echo -n "SomeRandomizedPassword" | md5sum
4c0b569e4c96df157eee1b65dd0e4d41
```

以下はopensslを直接使用する例です。

```
echo -n "SomeRandomizedPassword" | openssl md5
```

暗号化されたJSONを既知のマシングループやプライベートサブネットからしか受信しない場合は、`JSON_TRUSTED_NETWORKS`プロパティを使用して、受信したJSONの受け入れを信頼できるマシンのみにさらに制限することをお勧めします。このフィールドは、信頼できるIPアドレスやCIDRサブネットのコンマ区切りのリストです。以下はその例です。

```
127.0.0.0/8, 10.0.0.0/8
```

### JSON形式 <a href="#id-.providingconnectiondatafromexternalapplicationsv2.x-jsonformat" id="id-.providingconnectiondatafromexternalapplicationsv2.x-jsonformat"></a>

JSONの一般的な形式 (暗号化されて、署名され、Keeperコネクションマネージャーに送信される前) は以下のとおりです。

```
{
    "username" : "arbitraryUsername",
    "expires" :TIMESTAMP,
    "connections" : {
        "Connection Name" : {
            "protocol" :"PROTOCOL",
            "parameters" : {
                "name1" : "value1",
                "name2" : "value2",
                ...
            }
        },
        ...
    }
}
```

例えば、craigとしてログインして、すぐにLinuxサーバーへのSSH接続を開始するJSONファイルが必要な場合、そのファイルは以下のようになります。

```
{
    "username" : "craig",
    "expires" : "1740860895000",
    "connections" : {
        "Kali Linux Server" : {
            "protocol" : "ssh",
            "parameters" : {
                "hostname" : "192.168.1.2",
                "port" : "22",
                "username" : "kali",
                "private-key":"<contents of PEM encoded SSH key>"
            }
        }
    }
}
```

ここで「expires」は標準のUNIXエポックタイムスタンプでミリ秒単位 (1970年1月1日UTC真夜中からのミリ秒数) であり、`PROTOCOL`はGuacamoleがサポートする任意のプロトコルの内部名で、`vnc`、`rdp`、`ssh`などとなります。

以下は、現在から24時間後に期限切れになるタイムスタンプの例です。

```
echo $(($(date -v+24H +%s) * 1000))
```

{% hint style="warning" %}
サーバーの時刻がタイムスタンプの時刻を過ぎると、JSONは有効として受け入れられなくなります。タイムスタンプが指定されていない場合、データは失効しません。これは望ましいことですが、慎重に検討せずに指定を省くべきではありません。通常は、タイムスタンプを指定して、暗号化されたJSONの使用を適切な時間間隔に制限し、リプレイ攻撃を防ぐことが重要です。
{% endhint %}

Keeperコネクションマネージャーに送信する必要のある最上位のJSONオブジェクトには、以下のプロパティがあります。

| プロパティ名        | 型        | 説明                                                                                          |
| ------------- | -------- | ------------------------------------------------------------------------------------------- |
| `username`    | `string` | JSONによって認証されたユーザーの一意のユーザー名。ユーザーが匿名の場合は、空の文字列 (`""`) にする必要があります。                             |
| `expires`     | `number` | 署名が有効であっても、ミリ秒の解像度を持つ標準のUNIXエポックタイムスタンプ (UTCの1970年1月1日深夜からの経過ミリ秒数) として、JSONが受け入れられなくなる絶対時間。 |
| `connections` | `object` | 対応する一意の名前でユーザーに公開する必要がある接続のセット。ユーザーに公開される接続がない場合は、単に空のオブジェクト (`{}`) で構いません。                 |

送信された各JSONオブジェクト内で定義された各接続には、以下のプロパティがあります。

| プロパティ名       | 型        | 説明                                        |
| ------------ | -------- | ----------------------------------------- |
| `protocol`   | `string` | サポートされているプロトコルの内部名 (`vnc`、`rdp`、`ssh`など)。 |
| `parameters` | `object` | 接続に適用する接続パラメータの名前と値のペアを表すオブジェクト (\*)。     |

(\*) プロパティの名前を確認するには、Keeperコネクションマネージャーの接続UIでフィールドを右クリックし、フィールドのDOM要素「name」を確認します。

<figure><img src="https://4041518992-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZ7s6LQJaKa1G17O787JG%2Fuploads%2Fwo00W5w9SJDs78Jgky93%2Fimage.png?alt=media&#x26;token=dfecc669-1f27-439c-b57c-45abe607ed32" alt=""><figcaption><p>パラメータ名を確認</p></figcaption></figure>

### 暗号化されたJSONの生成 <a href="#id-.providingconnectiondatafromexternalapplicationsv2.x-generatingencryptedjson" id="id-.providingconnectiondatafromexternalapplicationsv2.x-generatingencryptedjson"></a>

上記のJSON形式でユーザーを認証するには、Docker Composeファイルの`JSON_SECRET_KEY`値で指定された128ビットの同じ秘密鍵を使用して、JSONに署名と暗号化の両方を行う必要があります。

1. 上記の形式でのJSONを生成します。
2. HMAC/SHA-256の秘密鍵 (`JSON_SECRET_KEY`プロパティに格納されているのと同じ128ビット鍵) を使用してJSONに署名します。署名されたプレーンテキストのJSONの先頭に署名プロセスのバイナリの結果を追加します。
3. CBCモードでAESを使用し、初期ベクトル (IV) をすべて0バイトに設定して、手順2の結果を暗号化します。
4. 暗号化された結果をbase 64でエンコードします。
5. 暗号化された結果を、`data`という名前のHTTPパラメータの値として、`/api/tokens`RESTエンドポイントにPOSTします (または、`data`という名前のクエリパラメータとしてKeeperコネクションマネージャーページのURLに含めます)。

たとえば、Keeperがkcm.example.comで実行されており、`BASE64_RESULT`が上記のプロセスの結果である場合、「curl」ユーティリティで実行すると、以下のようになります。

{% code overflow="wrap" %}

```
$ curl --data-urlencode "data=BASE64_RESULT" https://kcm.example.com/api/tokens
```

{% endcode %}

{% hint style="warning" %}
`/api/tokens`にPOSTする前、またはURLに含める前に、必ずbase64でエンコードされた結果をURLエンコードしてください。Base64には、URL内で特別な意味を持つ「+」と「=」の両方の文字を使用できます。
{% endhint %}

データが何らかの形で無効である場合、署名が一致しない場合、復号化または署名の検証が失敗した場合、または送信されたデータの有効期限が切れている場合、RESTサービスは無効なクレデンシャルエラーを返し、ユーザーに説明を表示せずに失敗します。発生したエラーの詳細は、KCMのログに記録されます。

## 参照実装

Apache Guacamoleのソースコードには、[`doc/encrypt-json.sh`](https://raw.githubusercontent.com/apache/guacamole-client/master/extensions/guacamole-auth-json/doc/encrypt-json.sh)というシェルスクリプトが含まれており、OpenSSLコマンドラインユーティリティを使用して、`guacamole-auth-json`が要求する形式でJSONを暗号化および署名します。このスクリプトは詳細なコメントが付いており、優れた参照実装として、テスト用、開発のための比較点として機能します。スクリプトを実行するには、以下のコマンドを使用します。

```
$ ./encrypt-json.sh HEX_ENCRYPTION_KEY file-to-sign-and-encrypt.json
```

以下は`auth.json`というファイルに以下の内容が含まれている場合となります。

```
{
    "username" : "test",
    "expires" : "1446323765000",
    "connections" : {
        "My Connection" : {
            "protocol" : "rdp",
            "parameters" : {
                "hostname" : "10.10.209.63",
                "port" : "3389",
                "ignore-cert": "true",
                "recording-path": "/recordings",
                "recording-name": "My-Connection-${GUAC_USERNAME}-${GUAC_DATE}-${GUAC_TIME}"
            }
        },
        "My OTHER Connection" : {
            "protocol" : "rdp",
            "parameters" : {
                "hostname" : "10.10.209.64",
                "port" : "3389",
                "ignore-cert": "true",
                "recording-path": "/recordings",
                "recording-name": "My-OTHER-Connection-${GUAC_USERNAME}-${GUAC_DATE}-${GUAC_TIME}"
            }
        }
    }
}
```

以下を実行します。

```
$ ./encrypt-json.sh 4C0B569E4C96DF157EEE1B65DD0E4D41 auth.json
```

以下が出力されます。

```
A2Pf5Kpmm97I2DT1PifIrfU6q3yzoGcIbNXEd60WNangT8DAVjAl6luaqwhBJnCK
uqcf9ZZlRo3uDxTHvUM3eq1YvdghL0GbosOn8Mn38j2ydOMk+Cd15a8ggb4/ddt/
yIBK4DxrN7MNbouZ091KYtXC6m20E6sGzLy676BlMSg1cmsENRIihOynsSLSCvo0
diif6H7T+ZuIqF7B5SW+adGfMaHlfknlIvSpLGHhrIP4aMYE/ZU2vYNg8ez27sCS
wDBWu5lERtfCYFyU4ysjRU5Hyov+yKa+O7jcRYpw3N+fHbCg7/dxVNW07qNOKssv
pzUciGvDPUCPpa02WmPJNEBowwQireO1952/MNAI77cW2UepbljD/bwOiZl2THJz
LrENo7K5acimBa+EjWEesgn7lx/WTCF3zxR6TH1CWrQM8Et1aUK1Nf8K11xEQbTy
klyaNtCmTfyahRZ/fUPxDNrdJVpPOSELkf7RJO5tOdK/FFIFIbze3ZUyXgRq+pHY
owpgOmudDBTBlxhXiONdutRI/RZbFM/7GBMdmI8AR/401OCV3nsI4jLhukjMXH3V
f3pQg+xKMhi/QExHhDk8VTNYk7GurK4vgehn7HQ0oSGh8pGcmxB6W43cz+hyn6VQ
On6i90cSnIhRO8SysZt332LwJCDm7I+lBLaI8NVHU6bnAY1Axx5oH3YTKc4qzHls
HEAFYLkD6aHMvHkF3b798CMravjxiJV3m7hsXDbaFN6AFhn8GIkMRRrjuevfZ+q9
enWN14s24vt5OVg69DljzALobUNKUXFx69SR8EpSBvUcKq8s/OgbDpFvKbwsDY57
HGT4T0CuRIA0TGUI075uerKBNApVhuBA1BmWJIrI4JXw5MuX6pdBe+MYccO3vfo+
/frazj8rHdkDa/IbueMbvq+1ozV2+UuxrbaTrV2i4jSRgd74U0QzOh9e8Q0i7vOi
l3hnIfOfg+v1oULmZmJSeiAYWxeGvPptp+n7rNFqHGM=
```

{% hint style="info" %}
このBase64 blobを使用する際は、改行を含めないようにしてください。
{% endhint %}

結果として得られたbase64エンコードされたデータは、Keeperコネクションマネージャーの`data`パラメータを使用して送信することで、ユーザーを認証し、JSONに記載された接続へのアクセスを許可します。このアクセスは`expires`タイムスタンプに達するまで有効で、それ以降はJSONは受け入れられなくなります。

この暗号化されたBase64データを使用して、コネクションマネージャーを起動する方法は2つあります。

#### HTTP POST

HTTP POSTリクエストを生成する場合

```sh
curl --data-urlencode "data=BASE64_RESULT" https://kcm.example.com/api/tokens
```

Postmanでは、`x-www-form-urlencoded`データを含む**POSTリクエスト**を使用してテストできます。

<figure><img src="https://4041518992-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZ7s6LQJaKa1G17O787JG%2Fuploads%2FpE5kW93QKWmwZbdf65ve%2Fimage.png?alt=media&#x26;token=ea1740d0-8a77-428e-9134-3f7f00a7f7d7" alt=""><figcaption><p>Postmanでテスト</p></figcaption></figure>

#### HTTP GET

HTTP GETリクエストを介してブラウザで接続を読み込むためのURLを生成する場合、改行を削除し、Base64ペイロードをURLエンコード文字列に変換します。以下のキー変換が必要となります。

* `+` → `%2B`
* `/` → `%2F`
* `=` → `%3D`

Pythonで変換することもできます。

```sh
python3 -c "import urllib.parse; print(urllib.parse.quote('XXXX', safe=''))"
```

その後、以下のようにURLエンコードされた文字列をサーバーのURL内の`data`パラメータとして指定します。

```
https://my.kcmserver.com/?data=URL_ENCODED_BASE64_STRING  
```

これをブラウザで開くと、接続が即座に認証されて開きます。

<figure><img src="https://4041518992-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZ7s6LQJaKa1G17O787JG%2Fuploads%2FT09fkhqOSdfgPS0FTB9H%2Fimage.png?alt=media&#x26;token=7c783126-e773-4ec9-94d8-df901a1657d2" alt=""><figcaption><p>動的接続を開く</p></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeper-connection-manager/jp/using-keeper-connection-manager/dynamic-connections.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
