# Azure Key Vaultでの暗号化

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2F4K32wWTSWm0memYWumEB%2Fimage.png?alt=media&#x26;token=f710209a-90da-42de-b226-b555f8c3499e" alt=""><figcaption></figcaption></figure>

KeeperシークレットマネージャーとAzure Key Vaultと連携することで、構成ファイルを暗号化できます。この連携により、接続情報をローカル環境で保護しつつ、すべての機密認証情報に対してKeeperのゼロ知識暗号化を活用できます。

## 機能

* Keeperシークレットマネージャーの構成ファイルをAzure Key Vaultで暗号化および復号化
* シークレットマネージャー接続への不正アクセスを防止
* 最小限のコード変更で即時に保護を実現。すべてのKeeperシークレットマネージャーSDK機能と連携
* AzureのRSA非対称鍵に対応

## 要件

{% tabs %}
{% tab title="Java" %}

* Java/Kotlin版[シークレットマネージャーSDK](/keeperpam/jp/secrets-manager/developer-sdk-library/java-sdk.md)に対応
* Azureパッケージ ([`azure-identity`](https://mvnrepository.com/artifact/com.azure/azure-identity/1.18.1) および [`azure-keyvault-keys`](https://mvnrepository.com/artifact/com.azure/azure-security-keyvault-keys/4.10.4)) が必要
* `WrapKey` および `UnwrapKey` の権限を持つRSA鍵タイプのみに対応
  {% endtab %}

{% tab title="JavaScript" %}

* [JavaScript版シークレットマネージャーSDK](/keeperpam/jp/secrets-manager/developer-sdk-library/javascript-sdk.md)に対応
* Azure依存パッケージ ([`@azure/identity`](https://www.npmjs.com/package/@azure/identity)、[`@azure/keyvault-keys`](https://www.npmjs.com/package/@azure/keyvault-keys)) はバンドル済みのため、別途インストールは不要です
* `WrapKey` および `UnWrapKey` の権限を持つRSA鍵タイプのみに対応
  {% endtab %}

{% tab title="Python" %}

* [Python シークレットマネージャーSDK](/keeperpam/jp/secrets-manager/developer-sdk-library/python-sdk.md)に対応
* [azure-identity](https://pypi.org/project/azure-identity/)および[azure-keyvault-keys](https://pypi.org/project/azure-keyvault-keys/)のパッケージが必要
* `WrapKey` および `UnWrapKey` の権限を持つRSA鍵タイプのみに対応
  {% endtab %}

{% tab title=".Net" %}

* [.Net シークレットマネージャーSDK](/keeperpam/jp/secrets-manager/developer-sdk-library/.net-sdk.md)に対応
* バージョン `net9.0` に対応
* Azureパッケージ ([`Azure.Identity`](https://www.nuget.org/packages/Azure.Identity/1.13.2) および [`Azure.Security.KeyVault.Keys`](https://www.nuget.org/packages/Azure.Security.KeyVault.Keys/4.7.0)) が必要
* `WrapKey` および `UnWrapKey` の権限を持つRSA鍵タイプのみに対応
  {% endtab %}
  {% endtabs %}

## セットアップ

### 1. モジュールのインストール

{% tabs %}
{% tab title="Java" %}
GradleまたはMavenを使用してプロジェクトをセットアップ

**Gradle**

<pre><code>repositories {
  mavenCentral()
}

dependencies {
<strong>  implementation("com.keepersecurity.secrets-manager:azurekv:1.0.0")
</strong>  implementation("com.keepersecurity.secrets-manager:core:17.0.0")
  implementation("com.azure:azure-identity:1.15.0")
  implementation("com.azure:azure-security-keyvault-keys:4.9.2")
  implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
  implementation("com.fasterxml.jackson.core:jackson-core:2.18.2")
  implementation("com.google.code.gson:gson:2.12.1")
  implementation("org.slf4j:slf4j-api:1.7.32"){
        exclude("org.slf4j:slf4j-log4j12")
    }
  implementation("ch.qos.logback:logback-classic:1.2.6")
  implementation("ch.qos.logback:logback-core:1.2.6")
  implementation("org.bouncycastle:bc-fips:1.0.2.4")
}
</code></pre>

**Maven**

<pre class="language-xml"><code class="lang-xml">&#x3C;!-- KMS-core -->
 &#x3C;dependency>
     &#x3C;groupId>com.keepersecurity.secrets-manager&#x3C;/groupId>
     &#x3C;artifactId>azurekv&#x3C;/artifactId>
     &#x3C;version>1.0.0&#x3C;/version>
&#x3C;/dependency>
&#x3C;dependency>
     &#x3C;groupId>com.keepersecurity.secrets-manager&#x3C;/groupId>
     &#x3C;artifactId>core&#x3C;/artifactId>
     &#x3C;version>17.0.0&#x3C;/version>
 &#x3C;/dependency>

 &#x3C;!-- Azure-identity -->
   &#x3C;dependency>
       &#x3C;groupId>com.azure&#x3C;/groupId>
       &#x3C;artifactId>azure-identity&#x3C;/artifactId>
       &#x3C;version>1.15.0&#x3C;/version>
        &#x3C;scope>compile&#x3C;/scope>
   &#x3C;/dependency>
  &#x3C;!-- Azure-keyvault -->
   &#x3C;dependency>
       &#x3C;groupId>com.azure&#x3C;/groupId>
       &#x3C;artifactId>azure-security-keyvault-keys&#x3C;/artifactId>
       &#x3C;version>4.9.2&#x3C;/version>
   &#x3C;/dependency>
      	
   &#x3C;!--gson -->
   &#x3C;dependency>
   	&#x3C;groupId>com.google.code.gson&#x3C;/groupId>
   	&#x3C;artifactId>gson&#x3C;/artifactId>
   	&#x3C;version>2.12.1&#x3C;/version>
   &#x3C;/dependency>

   &#x3C;!--jackson-core -->
   &#x3C;dependency>
   	&#x3C;groupId>com.fasterxml.jackson.core&#x3C;/groupId>
   	&#x3C;artifactId>jackson-core&#x3C;/artifactId>
   	&#x3C;version>2.18.2&#x3C;/version>
   &#x3C;/dependency>
   	
   &#x3C;!--jackson-databind -->
   &#x3C;dependency>
   	&#x3C;groupId>com.fasterxml.jackson.core&#x3C;/groupId>
   	&#x3C;artifactId>jackson-core&#x3C;/artifactId>
   	&#x3C;version>2.18.2&#x3C;/version>
   &#x3C;/dependency>
   &#x3C;!-- slf4j-api -->
	&#x3C;dependency>
	   &#x3C;groupId>org.slf4j&#x3C;/groupId>
	   &#x3C;artifactId>slf4j-api&#x3C;/artifactId>
	   &#x3C;version>1.7.32&#x3C;/version>
	   &#x3C;scope>runtime&#x3C;/scope>
	&#x3C;/dependency>	
  &#x3C;!-- logback-classic -->
   &#x3C;dependency>
	&#x3C;groupId>ch.qos.logback&#x3C;/groupId>
	&#x3C;artifactId>logback-classic&#x3C;/artifactId>
	&#x3C;version>1.2.6&#x3C;/version>
	&#x3C;scope>compile&#x3C;/scope>
<strong>  &#x3C;/dependency>
</strong>&#x3C;!-- logback-core -->
   &#x3C;dependency>
      &#x3C;groupId>ch.qos.logback&#x3C;/groupId>
      &#x3C;artifactId>logback-core&#x3C;/artifactId>
      &#x3C;version>1.2.6&#x3C;/version>
      &#x3C;scope>compile&#x3C;/scope>
   &#x3C;/dependency>  	
   &#x3C;!-- bc-fips -->
   &#x3C;dependency>
   	&#x3C;groupId>org.bouncycastle&#x3C;/groupId>
   	&#x3C;artifactId>bc-fips&#x3C;/artifactId>
   	&#x3C;version>1.0.2.4&#x3C;/version>
   &#x3C;/dependency>
   	
</code></pre>

{% endtab %}

{% tab title="JavaScript" %}
npmを使用してシークレットマネージャーとAzure Key Vaultモジュール統合をインストールします。

```bash
npm install @keeper-security/secrets-manager-azure
```

{% endtab %}

{% tab title="Python" %}
シークレットマネージャーストレージモジュールは、pipを使用してインストールできます。

```bash
pip3 install keeper-secrets-manager-storage
```

{% endtab %}

{% tab title=".Net" %}
KeeperシークレットマネージャーのKSMモジュールは、Keeperシークレットマネージャーのストレージモジュールに含まれており、`dotnet` を使用してインストールします。

```bash
dotnet add package Keeper.SecretsManager.AzureKeyVault
```

{% endtab %}

{% tab title="GoLang" %}
シークレットマネージャーとAzure KSMモジュールの統合は、以下のコマンドでインストールします。

```bash
go get github.com/keeper-security/secrets-manager-go/integrations/azure
```

{% endtab %}
{% endtabs %}

### 2. **Azure Key Vaultの接続を構成**

Azure Key Vaultインスタンスが利用可能であることを確認してください。Azure Key Vaultに接続するために必要な以下のパラメータが必要です。\
`AZURE_TENANT_ID: The Microsoft Entra tenant (directory) ID.`

`AZURE_CLIENT_ID: The client (application) ID of an App Registration in the tenant.`

`AZURE_CLIENT_SECRET: A client secret that was generated for the App Registration.`

Azure Key Vault統合を使用するには、Azure Appディレクトリのアプリが必要です。

{% hint style="info" %}
Azure Appディレクトリのアプリ登録および権限の詳細については、以下のAzureのドキュメントをご参照ください。

<https://learn.microsoft.com/en-us/azure/key-vault/general/authentication>
{% endhint %}

### 3. コードにAzure Key Vaultストレージを追加する

Azure接続が構成されたら、Azureキーを使用してKSM構成の暗号化/復号化を行うためにキーを取得できます。また、シークレットマネージャーSDKに対して、キー ボルトをストレージとして使用するよう指示する必要があります。

### Azure Key Vault統合の使用

設定が完了すると、Secrets Manager Azure Key Vault統合はすべてのシークレットマネージャーSDK機能をサポートします。コードは、KSM構成ファイルの暗号化および復号化を管理するために、Azureキーにアクセスできる必要があります。\
\
**指定された接続認証情報の使用**

{% tabs %}
{% tab title="Java" %}
この操作を行うには、`AzureKeyValueStorage` インスタンスを作成し、`SecretManagerOptions` コンストラクタで使用します。

`AzureKeyValueStorage` は、`azure_key_id`、`azure_keyvault_URL`、構成が含まれたシークレットマネージャー構成ファイルの名前を必要とします。

```java
import java.security.Security;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import static com.keepersecurity.secretsManager.core.SecretsManager.initializeStorage;
import com.keepersecurity.secretmanager.azurekv.AzureKeyValueStorage;
import com.keepersecurity.secretmanager.azurekv.AzureSessionConfig;
import com.keepersecurity.secretsManager.core.SecretsManagerOptions;


class Test {
	public static void main(String args[]){
		String oneTimeToken = "[One_Time_Token]";
		String keyId = "https://<vault-name>.vault.azure.net/keys/<keyname>/<keyversion>";
		String configFileLocation="<KSM-client-config.json>";
		String azTenantId = "<azure-tenant-id>";
		String azClientId = "<azure-client-id>";
		String azClientSecret = "<azure-client-secret>";
		String keyVaultUrl = "https://<vault-name>.vault.azure.net/";
		Security.addProvider(new BouncyCastleFipsProvider());
		try{
			//set azure KV configuration, 
			AzureSessionConfig azConfig= new AzureSessionConfig(azTenantId, azClientId, azClientSecret, keyVaultUrl);
			//Get Storage 
			AzureKeyValueStorage azkvstorage =  AzureKeyValueStorage.getInternalStorage(keyId, configFileLocation, azConfig);
			initializeStorage(azkvstorage, oneTimeToken);
			SecretsManagerOptions options = new SecretsManagerOptions(azkvstorage);
			//getSecrets(options)
		}catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

```

{% endtab %}

{% tab title="JavaScript" %}
この操作を行うには、`SecretsManager` コンストラクタで、`AzureKeyValueStorage` をシークレットマネージャーのストレージとして使用します。

このストレージには、`Azure Key ID` と、Azure Key Vaultによって暗号化されるシークレットマネージャー構成ファイルの名前が必要となります。

```javascript
 import { getSecrets, initializeStorage, localConfigStorage } from '@keeper-security/secrets-manager-core';
 import {AzureKeyValueStorage, AzureSessionConfig} from "@keeper/secrets-manager-azure";
 
     const getKeeperRecords = async () => {
        const tenant_id="<tenant_id>" 
        const client_id="<client_id>"
        const client_secret="<client-secret>"
        const azureSessionConfig = new AzureSessionConfig(tenant_id, client_id, client_secret)
        
        let config_path = "<path to ksm-client-config.json>"
        const logLevel = LoggerLogLevelOptions.info;
        // oneTimeToken is used only once to initialize the storage
        // after the first run, subsequent calls will use ksm-config.txt
        const oneTimeToken = "[One Time Token]";
        
        const keyId = 'https://<vault_name>.vault.azure.net/keys/<key_name>/<version>'
        const storage = await new AzureKeyValueStorage(keyId,config_path,azureSessionConfig,logLevel).init();
        await initializeStorage(storage, oneTimeToken);
        
        const {records} = await getSecrets({storage: storage});
        console.log(records)
    }
    getKeeperRecords()

```

{% endtab %}

{% tab title="Python" %}
この操作を行うには、`SecretsManager` コンストラクタで、トークンと共に`AzureKeyValueStorage` を構成として指定し、シークレットマネージャーのストレージとして使用します。

このストレージでは、`Azure Key ID`、Azure-KSM統合によって暗号化されるシークレットマネージャー構成ファイルの場所、そして以下のようなAzureセッション構成が必要です。

```python
from keeper_secrets_manager_storage.storage_azure_keyvault import AzureSessionConfig,AzureKeyValueStorage
from keeper_secrets_manager_core import SecretsManager

tenant_id = "<Tenant_ID>"
client_id = "<CLIENT_ID>"
client_secret = "<CLIENT_SECRET>"

azure_session_config = AzureSessionConfig(tenant_id, client_id, client_secret)
config_path = "<path_to_client_config_python.json>"

token="<One Time Token>"

key_id = "<key_id>"

azure_key_value_storage = AzureKeyValueStorage(key_id=key_Id,config_file_location=config_path ,az_session_config=azure_session_config)
    
secrets_manager = SecretsManager(token = token,config=azure_key_value_storage)
    
records  = secrets_manager.get_secrets()
    
for record in records:
    print(record)

```

{% endtab %}

{% tab title=".Net" %}
この操作を行うには、`SecretsManager` コンストラクタで、`AzureKeyValueStorage` をシークレットマネージャーのストレージとして使用します。\
\
このストレージでは、`Azure Key ID` と、Azure Key Vaultによって暗号化されるシークレットマネージャー構成ファイルの名前が必要です。オプションで `AzureSessionConfig` を指定することも可能です。認証情報が指定されていない場合は、既定の認証情報が使用されます。

```csharp
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OracleKeyManagement;
using SecretsManager;

public class Program
{
   private static async Task getOneIndividualSecret()
    {
        var tenant_id = "<TENANT_ID>";
        var client_secret = "<CLIENT_SECRET>";
        var client_id = "<CLIENT_ID>";
        var keyId = "<KEY_ID>";
        var path = "ksmConfigDotnet.json";
        var dotnet_access_token = "<ACCESS_TOKEN>";
        var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder.SetMinimumLevel(LogLevel.Debug);
            builder.AddConsole();
        });
        var logger = loggerFactory.CreateLogger<AzureKeyValueStorage>();
        var azure_session_config = new AzureSessionConfig(tenant_id, client_id, client_secret);
        AzureKeyValueStorage azure_storage = new AzureKeyValueStorage(keyId, path, azure_session_config, logger);
        SecretsManagerClient.InitializeStorage(azure_storage, dotnet_access_token);
        
        var options = new SecretsManagerOptions(azure_storage);
                    var records_list = await SecretsManagerClient.GetSecrets(options);
        records_list.Records.ToList().ForEach(record => Console.WriteLine(record.RecordUid + " - " + record.Data.title));
    }
	static async Task Main()
	{
		await getOneIndividualSecret();
	}
}
```

{% endtab %}

{% tab title="Go" %}
この操作を行うには、`SecretsManager` コンストラクタで、`NewAzureKeyValueStorage` をシークレットマネージャーのストレージとして使用します。

`NewAzureKeyVaultStorage` でAzure Key Vaultを使用してKSM構成を暗号化するには、以下のパラメータが必要です：

* `ksmConfigFileName`: KSM構成ファイルの名前
* `keyURL`: Azure KeyのURL

```go
package main

import (
	"encoding/json"
	"fmt"

	"github.com/keeper-security/secrets-manager-go/core"
	azurekv "github.com/keeper-security/secrets-manager-go/integrations/azure"
)

func main() {
	
	ksmConfigFile := ""
	oneTimeToken := "oneTimeToken"
	keyURL := "<Key URL>"   	}
	
	//Initialize the Azure Key Vault Storage
	cfg := azurekv.NewAzureKeyValueStorage(ksmConfigFileName, keyURL, &azurekv.AzureConfig{
		TenantID:     "<Azure Tenant ID>",
		ClientID:     "<Azure Client ID>",
		ClientSecret: "<Azure Client Secret>",
	})
	// create a new secrets manager client
	secrets_manager := core.NewSecretsManager(
		&core.ClientOptions{
			Config: cfg,
			Token:  oneTimeToken,
		},
	)
	// Fetch all the secrets from the vault
	secrets, err := secrets_manager.GetSecrets([]string{})
	if err != nil {
		// do something
		fmt.Printf("Error: %s\n", err)
	} else {
		for _, secret := range secrets {
			fmt.Printf("Recieved secret: %s\n", secret.Title())
		}
	}

}
```

{% endtab %}
{% endtabs %}

## 追加オプション

### キーの変更

KSM構成の暗号化に使用するキーを変更することも可能です。以下の例は、そのために必要なコードとなります。

{% tabs %}
{% tab title="Java" %}

```java
// `changeKey(newKeyID)`メソッドは、新しいAzureキーでKSM構成ファイルを暗号化するために使用されます。
....
 String newKeyID = "https://<vault-name>.vault.azure.net/keys/<keyname>/<keyversion>";
 AzureKeyValueStorage azkvstorage =  AzureKeyValueStorage.getInternalStorage(keyId, configFileLocation, azConfig);
 boolean isChanged = azkvstorage.changeKey(newKeyID);	 // Change the key for encryption/decryption
....
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
// 暗号化に使用するAzure Key Vaultキーを変更するには、`OciKeyValueStorage`インスタンスで`changeKey`メソッドを呼び出すことができます。
.....
 const keyId = 'https://<vault_name>.vault.azure.net/keys/<key_name>/<version>'
 const keyId2 = "https://<vault_name>.vault.azure.net/keys/<key_name>/<version>"
 const storage = await new AzureKeyValueStorage(keyId,config_path,azureSessionConfig).init();
 await storage.changeKey(keyId2);

.....
```

{% endtab %}

{% tab title="Python" %}

```python
azure_key_value_storage = AzureKeyValueStorage(key_id=key_id,config_file_location=config_path ,az_session_config=azure_session_config)
new_key_id = "<new key id>"
is_changed = azure_key_value_storage.change_key(new_key_id = new_key_id)
print("Key is changed " + is_changed)
```

{% endtab %}

{% tab title=".Net" %}

```csharp
// 暗号化に使用するAzureキーを変更するには、`AzureKeyValueStorage`インスタンスで`ChangeKeyAsync`メソッドを呼び出すことができます。  
`Microsoft.Extensions.Logging`を使用して、ログ機能を統合することも可能です。
 ....
     var keyId2 = "<KEY_ID_2>";
     var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder.SetMinimumLevel(LogLevel.Debug);
                builder.AddConsole();
            });
    var logger = loggerFactory.CreateLogger<AzureKeyValueStorage>();
    AzureKeyValueStorage azure_storage = new AzureKeyValueStorage(keyId, path, azure_session_config, logger);
    azure_storage.ChangeKeyAsync(keyId2).Wait();
 ....
```

{% endtab %}

{% tab title="GoLang" %}

```go
	....	
		updatedConfig := &azurekv.AzureConfig{
			TenantID:     "<Updated Tenant ID>",
			ClientID:     "<Updated Client ID>",
			ClientSecret: "<Updated Client Secret>",
		}
		updatedKeyURL := "<Updated Key URL>"		
		// Changes the key
		// If you don't want to change Config, pass nil as a paramter
		isChanged, err := cfg.ChangeKey(updatedKeyURL, updatedConfig)
		if err != nil {
			fmt.Printf("Error while changing key: %v", err)
		} else {
			fmt.Printf("Key changed: %v\n", isChanged)
		}
		.....
```

{% endtab %}
{% endtabs %}

### 構成の復号化

現在の実装を別のクラウド環境へ移行する場合や、生の認証情報を取得したい場合には、構成の復号が可能です。この関数はブール値を受け取り、`true` に設定すると復号化された構成をファイルに保存し、`false` の場合は復号化された構成を返します。

{% tabs %}
{% tab title="Java" %}

```java
....
 AzureKeyValueStorage azkvstorage =  AzureKeyValueStorage.getInternalStorage(keyId, configFileLocation, azConfig);
 azkvstorage.decryptConfig(false); // falseをパラメータとして設定すると、プレーンテキストのみが抽出されます。
 //または
 azkvstorage.decryptConfig(true); //trueをパラメータとして設定すると、プレーンテキストを抽出し、構成をプレーンテキストとして保存します。
....
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
 //構成ファイルを復号化してプレーンテキストとして再保存するには、`AzureKeyValueStorage`インスタンスで`DecryptConfigAsync`メソッドを呼び出すことができます。
.... 
 const storage = await new AzureKeyValueStorage(keyId,config_path,azureSessionConfig).init();
 const decryptedConfig = storage.DecryptConfigAsync(true).wait(); // return decrypted and Saves to file
  //OR
 const decryptedConfig = await storage.decryptConfig(false); // returns the decrypted config 
.... 
```

{% endtab %}

{% tab title="Python" %}

```python
storage = AzureKeyValueStorage(key_id=key_id,config_file_location=config_path ,az_session_config=azure_session_config)
storage.decrypt_config() #プレーンな構成ファイルを保存
 # or
storage.decrypt_config(False)#復号化された構成は戻り値として返され、ファイル自体は暗号化されたまま保持されます。
```

{% endtab %}

{% tab title=".Net" %}

```csharp
//構成ファイルを復号化してプレーンテキストとして再保存するには、AzureKeyValueStorageインスタンスで DecryptConfigAsyncメソッドを呼び出します。
.... 
var keyId2 = "<KEY_ID_2>";
 AzureKeyValueStorage azure_storage = new AzureKeyValueStorage(keyId, path, azure_session_config, logger);
await azure_storage.DecryptConfigAsync(true); // return decrypted and Saves to file
//OR
await azure_storage.DecryptConfigAsync(false); // returns the decrypted config 
.... 
```

{% endtab %}

{% tab title="GoLang" %}

```go
		.....
		configs := make(map[core.ConfigKey]interface{})
		plainText, err := cfg.DecryptConfig(true)
		if err != nil {
			// do something
			fmt.Printf("Error while decrypting config: %v", err)
		} else {
			if err := json.Unmarshal([]byte(plainText), &configs); err != nil {
				fmt.Printf("Error while unmarshalling: %v", err)
			}
			fmt.Printf("Decrypted data: %v\n", configs["clientId"])
		}
		.....
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
KSM統合機能を使用する準備ができました。
{% endhint %}

{% hint style="info" %}
その他の例と機能については、[KSM SDKのドキュメント](/keeperpam/jp/secrets-manager/developer-sdk-library.md)をご参照ください。
{% endhint %}


---

# 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/keeperpam/jp/secrets-manager/integrations/azure-key-vault-ksm.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.
