動的接続

暗号化されたJSON認証を使用して、Keeperコネクションマネージャーを外部データソースと連携

概要

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

インストール

動的接続機能を使用するには、Keeperコネクションマネージャー用の暗号化JSON認証モジュールをインストールする必要があります。この機能を有効にするには、keeper/guacamoleイメージ内の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形式

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がサポートする任意のプロトコルの内部名で、vncrdpsshなどとなります。

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

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

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

プロパティ名
説明

username

string

JSONによって認証されたユーザーの一意のユーザー名。ユーザーが匿名の場合は、空の文字列 ("") にする必要があります。

expires

number

署名が有効であっても、ミリ秒の解像度を持つ標準のUNIXエポックタイムスタンプ (UTCの1970年1月1日深夜からの経過ミリ秒数) として、JSONが受け入れられなくなる絶対時間。

connections

object

対応する一意の名前でユーザーに公開する必要がある接続のセット。ユーザーに公開される接続がない場合は、単に空のオブジェクト ({}) で構いません。

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

プロパティ名
説明

protocol

string

サポートされているプロトコルの内部名 (vncrdpsshなど)。

parameters

object

接続に適用する接続パラメータの名前と値のペアを表すオブジェクト (*)。

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

パラメータ名を確認

暗号化されたJSONの生成

上記の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/tokensRESTエンドポイントにPOSTします (または、dataという名前のクエリパラメータとしてKeeperコネクションマネージャーページのURLに含めます)。

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

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

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

参照実装

Apache Guacamoleのソースコードには、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=

このBase64 blobを使用する際は、改行を含めないようにしてください。

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

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

HTTP POST

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

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

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

Postmanでテスト

HTTP GET

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

  • +%2B

  • /%2F

  • =%3D

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

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

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

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

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

動的接続を開く

Last updated