# Rust SDK

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2F5vcM5JWGy4uvirJdJ09U%2Fimage.png?alt=media&#x26;token=e630112d-d8a2-4f1d-8ef7-c58ac81999e0" alt=""><figcaption></figcaption></figure>

## ダウンロードとインストール <a href="#download-and-installation" id="download-and-installation"></a>

#### 要件 <a href="#requirements" id="requirements"></a>

{% hint style="info" %}
本SDKの利用には**Rust 1.87 以降**が必要です。このバージョン要件により、Edition 2024の依存関係との互換性と、直近のセキュリティ修正への対応が確保されます。
{% endhint %}

### Cargoでパッケージ追加 <a href="#adding-as-package-using-cargo" id="adding-as-package-using-cargo"></a>

```
cargo add keeper-secrets-manager-core
```

詳細については、<https://crates.io/crates/keeper-secrets-manager-core>をご参照ください。

### ソースコード <a href="#source-code" id="source-code"></a>

Rustのソースコードについては[GitHubリポジトリ](https://github.com/Keeper-Security/secrets-manager/tree/master/sdk/rust)をご覧ください。

## SDKの使用方法 <a href="#using-the-sdk" id="using-the-sdk"></a>

### 初期化 <a href="#initialise" id="initialise"></a>

{% hint style="info" %}
トークンのみで新しい設定を生成し、あとから使う場合は、トークンをバインドして `config.json` を完全に生成するまでに、少なくとも1回の読み取り操作が必要です。
{% endhint %}

{% tabs %}
{% tab title="シークレットマネージャー" %}

```rust
SecretsManager::new(client_options)?
```

{% endtab %}

{% tab title="使用例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::FileKeyValueStorage,
    custom_error::KSMRError
};

fn main()-> Result<(), KSMRError>{
    let token = "<Your One time token>".to_string();
    let config = FileKeyValueStorage::new_config_storage("test.json".to_string())?;
    let client_options = ClientOptions::new_client_options_with_token(token, config);
    let mut secrets_manager = SecretsManager::new(client_options)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

<table data-header-hidden><thead><tr><th width="150">パラメータ</th><th width="150">必須</th><th>説明</th><th>型</th></tr></thead><tbody><tr><td>パラメータ</td><td>必須</td><td>説明</td><td>型</td></tr><tr><td>token</td><td>はい</td><td>ワンタイムアクセストークン</td><td>String</td></tr><tr><td>config</td><td>はい</td><td>ストレージ設定</td><td><code>KeyValueStorage</code></td></tr></tbody></table>

### プロキシ設定 <a href="#proxy-configuration" id="proxy-configuration"></a>

SDKの通信をすべてHTTPまたはHTTPSのプロキシ経由にするには、`ClientOptions` の `proxy_url` を設定するか、環境変数を使います。プロキシは、API呼び出し、ファイルのアップロードとダウンロード、サムネイルのダウンロード、キャッシュへのリクエストなど、SDKのすべての操作に適用されます。

{% tabs %}
{% tab title="ClientOptions経由のプロキシ" %}

```rust
let mut client_options = ClientOptions::new_client_options(config);
client_options.proxy_url = Some("http://proxy.example.com:8080".to_string());
let mut secrets_manager = SecretsManager::new(client_options)?;
```

{% endtab %}

{% tab title="認証付きプロキシの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main() -> Result<(), KSMRError> {
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let mut client_options = ClientOptions::new_client_options(config);

    // Authenticated proxy: http://user:pass@host:port
    client_options.proxy_url = Some("http://user:pass@proxy.example.com:8080".to_string());

    let mut secrets_manager = SecretsManager::new(client_options)?;
    let secrets = secrets_manager.get_secrets(Vec::new())?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| オプション                        | 説明                                                        |
| ---------------------------- | --------------------------------------------------------- |
| `ClientOptions.proxy_url`    | コードからプロキシを指定 (環境変数より優先)                                   |
| `HTTP_PROXY` / `HTTPS_PROXY` | 標準のプロキシ用環境変数 (`proxy_url` 未設定時に使用)                        |
| `KSM_PROXY_URL`              | キャッシュモジュール (`caching_post_function`) のリクエストにプロキシが必要なときに使用 |

### シークレットの取得 <a href="#retrieve-secrets" id="retrieve-secrets"></a>

{% tabs %}
{% tab title="Get Secrets" %}

```rust
let records_filter = Vec::new(); // UIDに基づき必要ならレコードフィルターを追加
let secrets = secrets_manager.get_secrets(records_filter)?;
```

{% endtab %}

{% tab title="例: すべてのシークレットを取得" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    custom_error::KSMRError,
    storage::FileKeyValueStorage
};

fn main()-> Result<(), KSMRError>{
    let token = "<Your One time token>".to_string();
    let file_name = FileKeyValueStorage::new_config_storage("test.json".to_string())?;
    let client_options = ClientOptions::new_client_options_with_token(token, file_name);
    
    let mut secrets_manager = SecretsManager::new(client_options)?;
    let secrets = secrets_manager.get_secrets(Vec::new())?;

    for secret in secrets {
        secret.print();
        println!("---");
    }
    Ok(())
}
```

{% endtab %}

{% tab title="例: フィルター付きで取得" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    custom_error::KSMRError,
    storage::FileKeyValueStorage
};

fn main()-> Result<(), KSMRError>{
    let token = "<Your One time token>".to_string();
    let file_name = FileKeyValueStorage::new_config_storage("test.json".to_string())?;
    let client_options = ClientOptions::new_client_options_with_token(token, file_name);
    
    let mut secrets_manager = SecretsManager::new(client_options)?;
    let records_filter = vec!["record_uid1","record_uid2"]; // UIDに基づき必要ならレコードフィルターを追加
    let secrets = secrets_manager.get_secrets(records_filter)?;

    for secret in secrets {
        secret.print();
        println!("---");
    }
    Ok(())
}
```

{% endtab %}
{% endtabs %}

<table data-header-hidden><thead><tr><th width="150">パラメータ</th><th width="150">型</th><th width="150">必須</th><th width="150">デフォルト</th><th>説明</th></tr></thead><tbody><tr><td>パラメータ</td><td>型</td><td>必須</td><td>デフォルト</td><td>説明</td></tr><tr><td><code>uids</code></td><td><code>Vec&#x3C;String></code></td><td>任意</td><td>なし</td><td>取得するレコードUID</td></tr></tbody></table>

#### レスポンス

型: `Vec<Record>`

すべてのKeeperレコード、または指定したUIDのレコード

> デフォルトでは、指定したトークンでアクセス可能なすべてのレコードを取得します

#### オプション付きでシークレットを取得 <a href="#get-secrets-with-options" id="get-secrets-with-options"></a>

GraphSyncによってリンクされたレコードなど、追加データが必要なときは `get_secrets_with_options()` を使います。

{% tabs %}
{% tab title="オプション付きでシークレットを取得" %}

```rust
let query_options = QueryOptions::with_links(Vec::new(), Vec::new(), true);
let secrets = secrets_manager.get_secrets_with_options(query_options)?;
```

{% endtab %}

{% tab title="例: リンクされたレコードを取得" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    dto::payload::QueryOptions,
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main() -> Result<(), KSMRError> {
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // プライマリのシークレットとあわせてリンクされたレコードを要求
    // Vec::new() は UID/フォルダのフィルターなし (全シークレット取得) を表す
    let query_options = QueryOptions::with_links(Vec::new(), Vec::new(), true);
    let secrets = secrets_manager.get_secrets_with_options(query_options)?;

    for secret in &secrets {
        println!("Secret: {}", secret.title);
        if !secret.links.is_empty() {
            println!("  Linked records: {}", secret.links.len());
        }
    }
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ           | 型              | 必須 | 説明          |
| --------------- | -------------- | -- | ----------- |
| `query_options` | `QueryOptions` | はい | リクエストのオプション |

**QueryOptions のフィールド:**

| フィールド           | 型              | 説明                                                                   |
| --------------- | -------------- | -------------------------------------------------------------------- |
| `request_links` | `Option<bool>` | `true` のとき、レスポンスに GraphSync によるリンク先レコードを含める。リンク先は `Record.links` で参照 |

### シークレットから値を取得 <a href="#retrieve-values-from-secret" id="retrieve-values-from-secret"></a>

#### パスワードを取得 <a href="#retrieve-a-password" id="retrieve-a-password"></a>

Keeperシークレットマネージャーからシークレットを取得した後に、そのパスワードを参照できます。

{% tabs %}
{% tab title="パスワードを取得" %}

```rust
secret.get_standard_field_value("password", true);
```

{% endtab %}

{% tab title="例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーのセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;
    
    // レコードUIDを指定してシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["record_uid".to_string()])?;
    let secret = match secrets.len(){
        0 => return Err(KSMRError::CustomError("no secret with given uid is found".to_string())),
        _ => &secrets[0],
    };
    // レコードからパスワードを取得
    let my_secret_password = secret.get_standard_field_value("password", true);
    Ok(())
}
```

{% endtab %}
{% endtabs %}

#### 標準フィールドの取得 <a href="#retrieve-standard-fields" id="retrieve-standard-fields"></a>

{% tabs %}
{% tab title="標準フィールド" %}

```rust
secret.get_standard_field_value(“FIELD_TYPE”.to_string(), true);
```

{% endtab %}

{% tab title="標準フィールドの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::FileKeyValueStorage,
    custom_error::KSMRError,
    enums::StandardFieldTypeEnum
};

fn main()-> Result<(), KSMRError>{
    // Secrets Managerのセットアップ
    let token = "your_token_goes_here".to_string();
    let config = FileKeyValueStorage::new_config_storage("test.json".to_string())?;
    let client_options = ClientOptions::new_client_options_with_token(token, config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // レコードUIDを指定してシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["record_uid".to_string()])?;
    let secret = match secrets.len(){
        0 => return Err(KSMRError::CustomError("no secret with given uid is found".to_string())),
        _ => &secrets[0],
    };
    // タイプミスを避けるためStandardFieldTypeEnumを使用
    let login_field = StandardFieldTypeEnum::LOGIN.get_type().to_string();
    // シークレットからログインフィールドを取得
    let my_secret_login = secret.get_standard_field_value(login_field, true)
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ        | 型         | 必須 | デフォルト | 説明           |
| ------------ | --------- | -- | ----- | ------------ |
| `field_type` | `String`  | はい | None  | 取得するフィールドタイプ |
| `single`     | `boolean` | 任意 | False | 最初の値のみを返す    |

フィールドタイプはKeeper[レコードタイプ](/enterprise-guide/jp/record-types.md)に基づきます。利用可能なフィールドの詳細な一覧については、コマンダーで [`record-type-info`](/keeperpam/jp/commander-cli/command-reference/record-commands/record-type-commands.md#record-type-info-command) コマンドをご参照ください。

#### カスタムフィールドの取得 <a href="#retrieve-custom-fields" id="retrieve-custom-fields"></a>

{% tabs %}
{% tab title="カスタムフィールド" %}

```rust
secret.get_custom_field_value(“FIELD_TYPE”, true);
```

{% endtab %}

{% tab title="カスタムフィールドの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // レコードUIDで特定のシークレットを取得する
    let secrets = secrets_manager.get_secrets(vec!["record_uid".to_string()])?;
    let secret = match secrets.len(){
        0 => return Err(KSMRError::CustomError("no secret with given uid is found".to_string())),
        _ => &secrets[0],
    };
    // カスタムフィールドを取得する、例: APIキー
    let api_key = secret.get_custom_field_value(“API Key”, true)
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ        | 型         | 必須 | デフォルト | 説明          |
| ------------ | --------- | -- | ----- | ----------- |
| `field_type` | `String`  | はい | -     | 取得するフィールドの型 |
| `single`     | `boolean` | 任意 | False | 最初の値のみを返す   |

カスタムフィールドはレコードタイプ定義に含まれないフィールドで、ユーザーによって追加できます。

#### レスポンス

型: `String` または `Vec<String>`

フィールドの値または値の集合。単一値になるのは `single=true` オプションが渡された場合のみです。

#### タイトルでシークレットを検索 <a href="#search-secrets-by-title" id="search-secrets-by-title"></a>

レコードタイトルでシークレットを検索する場合、SDKでは以下のAPIを使います。

* `get_secrets_by_title()` — タイトルが完全一致するシークレットをすべて返す
* `get_secret_by_title()` — タイトルが完全一致する最初の1件だけを返す

{% tabs %}
{% tab title="タイトルですべてのシークレットを取得" %}

```rust
secrets_manager.get_secrets_by_title(record_title)
```

{% endtab %}

{% tab title="タイトルですべてのシークレットを取得する例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // レコードタイトルに一致するすべてのシークレットを取得
    let matching_secrets = secrets_manager.get_secrets_by_title("My Credentials")?;
    println!("Found {} matching secrets", matching_secrets.len());

    Ok(())
}
```

{% endtab %}

{% tab title="タイトルで最初のシークレットを取得" %}

```rust
secrets_manager.get_secret_by_title(record_title)
```

{% endtab %}

{% tab title="タイトルで最初のシークレットを取得する例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // レコードタイトルに一致する最初のシークレットを取得
    if let Some(secret) = secrets_manager.get_secret_by_title("My Credentials")? {
        println!("Found secret: {}", secret.uid);
    } else {
        println!("No secret found with that title");
    }

    Ok(())
}
```

{% endtab %}
{% endtabs %}

#### レスポンス

| メソッド                     | 戻り値の型                    | 説明                         |
| ------------------------ | ------------------------ | -------------------------- |
| `get_secrets_by_title()` | `Result<Vec<Record>>`    | タイトルが完全一致するすべてのシークレット      |
| `get_secret_by_title()`  | `Result<Option<Record>>` | タイトルが完全一致する最初の1件または `None` |

| パラメータ          | 型      | 必須 | 説明                   |
| -------------- | ------ | -- | -------------------- |
| `record_title` | `&str` | はい | 検索するレコードのタイトル (完全一致) |

{% hint style="info" %}
タイトル照合は**大文字小文字を区別**し、**完全一致**が必要です。部分一致や大文字小文字を区別しない検索には、いったんすべてのシークレットを取得し、クライアント側で絞り込んでください。
{% endhint %}

#### Keeper表記法を使用して値を取得 <a href="#retrieve-values-using-keeper-notation" id="retrieve-values-using-keeper-notation"></a>

{% tabs %}
{% tab title="表記を取得" %}

```rust
secrets_manager.get_notation(query)
```

{% endtab %}

{% tab title="表記の例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // 表記法に一致するすべてのシークレットを取得する
    let mut notation = "HDQTnxkTcPSOsHNAlbI4aQ/field/login".to_string();
    let mut result = secrets_manager.get_notation(notation)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

Keeper表記法の形式と機能については、[こちらのページ](/keeperpam/jp/secrets-manager/about/keeper-notation.md) をご参照ください。

| パラメーター  | 型        | 必須 | デフォルト | 説明                               |
| ------- | -------- | -- | ----- | -------------------------------- |
| `query` | `String` | はい | -     | 指定したフィールドから値を取得するためのKeeper表記法クエリ |

#### 戻り値

クエリで指定したフィールドの値

型: `String` または `Vec<String>`

#### TOTPコードの取得 <a href="#retrieve-a-totp-code" id="retrieve-a-totp-code"></a>

{% tabs %}
{% tab title="TOTPコードの取得" %}

```rust
get_totp_code(&url)
```

{% endtab %}

{% tab title="使用例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    enums::StandardFieldTypeEnum,
    utils
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDを指定してシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let record = &secrets[0];

    // レコードからTOTPのURL値を取得
    let value = record.get_standard_field_value(StandardFieldTypeEnum::ONETIMECODE.get_type(), false)?;
    let url: String = utils::get_otp_url_from_value_obj(value)?;

    // TOTPのURLからコードを取得
    let totp = utils::get_totp_code(&url)?;
    println!("{}", totp.get_code());
    Ok(())
}
```

{% endtab %}
{% endtabs %}

#### 戻り値

> 型: `Result<TotpCode,KSMRError>`

| パラメータ | 型        | 必須 | 説明       |
| ----- | -------- | -- | -------- |
| `url` | `String` | はい | TOTP URL |

### シークレットの更新 <a href="#update-a-secret" id="update-a-secret"></a>

{% hint style="warning" %}
レコード更新コマンドは、成功してもローカルのレコードデータ (特に更新後のレコードリビジョン) が更新されないため、すでに更新されたレコードに連続して更新を行うと、リビジョンの不一致により失敗します。各更新バッチの後には、必ず更新されたすべてのレコードを再読み込みしてください。
{% endhint %}

#### **シークレットを更新** <a href="#update-secret" id="update-secret"></a>

`update_secret()` メソッドは、レコードを更新する標準的な方法です。

{% tabs %}
{% tab title="シークレットを更新" %}

```rust
secrets_manager.update_secret(record)
```

{% endtab %}

{% tab title="シークレット更新の例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    enums::StandardFieldTypeEnum
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDで特定のシークレットを取得
    let mut secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let mut secret_to_update = secrets.into_iter().next().unwrap();

    // フィールド値を更新
    let field_type = StandardFieldTypeEnum::LOGIN.get_type();
    secret_to_update.set_standard_field_value_mut(field_type, "sample@ks.com".into())?;

    // 変更を保存
    secrets_manager.update_secret(secret_to_update)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ    | 型        | 必須 | デフォルト | 説明                |
| -------- | -------- | -- | ----- | ----------------- |
| `record` | `Record` | はい |       | 更新後のフィールド値を含むレコード |

**戻り値**

`Result<(), KSMRError>` (成功時は `Ok(())`、失敗時は `Err`)

#### **トランザクションによるパスワードローテーション** <a href="#password-rotation-with-transactions" id="password-rotation-with-transactions"></a>

`update_secret_with_transaction()` メソッドは、新しいパスワードをコミットする前に検証するパスワードローテーションで利用します。

{% tabs %}
{% tab title="パスワードローテーション" %}

```rust
secrets_manager.update_secret_with_transaction(record, UpdateTransactionType::Rotation)?;
// 新しいパスワードを検証...
secrets_manager.complete_transaction(record_uid, false)?; // false = commit, true = rollback
```

{% endtab %}

{% tab title="パスワードローテーションの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    enums::StandardFieldTypeEnum,
    dto::payload::UpdateTransactionType
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDで特定のシークレットを取得
    let mut secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let mut secret_to_update = secrets.into_iter().next().unwrap();
    let record_uid = secret_to_update.uid.clone();

    // パスワードフィールドを更新
    let field_type = StandardFieldTypeEnum::PASSWORD.get_type();
    secret_to_update.set_standard_field_value_mut(field_type, "NewRotatedPassword123!".into())?;

    // ローテーション用トランザクションを開始
    secrets_manager.update_secret_with_transaction(secret_to_update, UpdateTransactionType::Rotation)?;

    // アプリケーションで新しいパスワードを検証...
    // 成功した場合:
    secrets_manager.complete_transaction(record_uid, false)?; // コミット

    // 検証に失敗した場合:
    // secrets_manager.complete_transaction(record_uid, true)?; // ロールバック

    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ              | 型                       | 必須 | デフォルト | 説明               |
| ------------------ | ----------------------- | -- | ----- | ---------------- |
| `record`           | `Record`                | はい | ​     | ストレージおよびクエリ構成    |
| `transaction_type` | `UpdateTransactionType` | はい | ​     | トランザクション更新のための構成 |

<table><thead><tr><th>パラメータ</th><th width="248.54296875">型</th><th width="135.26953125">必須</th><th>説明</th></tr></thead><tbody><tr><td><code>record</code></td><td><code>Record</code></td><td>はい</td><td>更新後のフィールド値を含むレコード</td></tr><tr><td><code>transaction_type</code></td><td><code>UpdateTransactionType</code></td><td>はい</td><td><code>General</code> または <code>Rotation</code></td></tr><tr><td><code>record_uid</code></td><td><code>String</code></td><td>はい</td><td>トランザクションを確定するレコードのUID</td></tr><tr><td><code>rollback</code></td><td><code>bool</code></td><td>はい</td><td><code>false</code>でコミット、<code>true</code>でロールバック</td></tr></tbody></table>

#### **ファイルリンクの削除** <a href="#remove-file-links" id="remove-file-links"></a>

`update_secret_with_options()` メソッドは、ファイルリンクの削除など、更新内容を細かく指定するときに使います。

{% tabs %}
{% tab title="オプション付きで更新" %}

```rust
let update_options = UpdateOptions::new(
    UpdateTransactionType::General,
    vec!["file-uid-to-remove".to_string()]
);
secrets_manager.update_secret_with_options(record, update_options)?;
```

{% endtab %}

{% tab title="オプション付き更新の例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    dto::payload::{UpdateOptions, UpdateTransactionType}
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDで特定のシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let secret_to_update = secrets.into_iter().next().unwrap();

    // 必要に応じてフィールドを変更...

    // ファイルリンクを削除するための更新オプションを作成
    let update_options = UpdateOptions::new(
        UpdateTransactionType::General,
        vec!["file-uid-to-remove-1".to_string(), "file-uid-to-remove-2".to_string()]
    );

    // レコードを更新し、指定したファイルリンクを削除
    secrets_manager.update_secret_with_options(secret_to_update, update_options)?;

    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ            | 型               | 必須 | デフォルト | 説明                |
| ---------------- | --------------- | -- | ----- | ----------------- |
| `record`         | `Record`        | はい |       | 更新後のフィールド値を含むレコード |
| `update_options` | `UpdateOptions` | はい |       | 高度な更新のオプション       |

**UpdateOptions のフィールド:**

| フィールド              | 型                       | 説明                       |
| ------------------ | ----------------------- | ------------------------ |
| `transaction_type` | `UpdateTransactionType` | `General` または `Rotation` |
| `links_to_remove`  | `Vec<String>`           | 削除するファイル添付のUID           |

フィールド値は `set_standard_field_value_mut` または `set_custom_field_value_mut` で設定します。

フィールドはタイプ名で識別します。

フィールドタイプの一覧は[レコードタイプ](/enterprise-guide/jp/record-types.md)をご参照ください。複数値を持つフィールドは、リストとして設定します。

| パラメータ              | 型                       | 必須 | デフォルト | 説明               |
| ------------------ | ----------------------- | -- | ----- | ---------------- |
| `field_type`       | `String`                | はい | ​     | 取得するフィールドの型      |
| `transaction_type` | `UpdateTransactionType` | はい | なし    | トランザクション更新のための構成 |

| パラメータ              | 型                       | 必須 | デフォルト | 説明               |
| ------------------ | ----------------------- | -- | ----- | ---------------- |
| `field_type`       | `String`                | はい | ​     | 取得するフィールドの型      |
| `transaction_type` | `UpdateTransactionType` | はい | なし    | トランザクション更新のための構成 |

#### ランダムパスワードの生成 <a href="#generate-a-random-password" id="generate-a-random-password"></a>

{% tabs %}
{% tab title="パスワードの生成" %}

```rust
generate_password_with_options(password_options);
```

{% endtab %}

{% tab title="パスワード生成の例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    enums::StandardFieldTypeEnum,
    utils::{generate_password_with_options, PasswordOptions}
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDで特定のシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let mut secret = secrets.into_iter().next().unwrap();

    // ランダムなパスワードを生成
    let charset: String = "$_!?#".to_string();
    let length = 32;
    let digits = 2;
    let lowercase = 2;
    let uppercase = 2;
    let special_characters = 2;
    let password_options = PasswordOptions::new()
        .length(length)
        .digits(digits)
        .lowercase(lowercase)
        .uppercase(uppercase)
        .special_characters(special_characters)
        .special_characterset(charset);
    let password = generate_password_with_options(password_options)?;

    // 新しいパスワードでレコードを更新
    let field_type = StandardFieldTypeEnum::PASSWORD.get_type();
    secret.set_standard_field_value_mut(field_type, password.into())?;

    // シークレットへの変更を保存
    secrets_manager.update_secret(secret)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th width="185.8203125">パラメータ</th><th width="157.40234375">型</th><th>必須</th><th>デフォルト</th><th>説明</th></tr></thead><tbody><tr><td><code>password_options</code></td><td><code>PasswordOptions</code></td><td>はい</td><td></td><td>パスワードの構成</td></tr><tr><td><code>charset</code></td><td><code>String</code></td><td>任意</td><td><code>"""!@#$%()+;&#x3C;>=?[]{}^.,"""</code></td><td>パスワードに含める特殊文字の集合</td></tr><tr><td><code>length</code></td><td><code>i32</code></td><td>任意</td><td>32</td><td>パスワードの長さ</td></tr><tr><td><code>lowercase</code></td><td><code>i32</code></td><td>任意</td><td>なし</td><td>パスワードに含める小文字の数</td></tr><tr><td><code>uppercase</code></td><td><code>i32</code></td><td>任意</td><td>なし</td><td>パスワードに含める大文字の数</td></tr><tr><td><code>digits</code></td><td><code>i32</code></td><td>任意</td><td>なし</td><td>パスワードに含める数字の数</td></tr><tr><td><code>special_characters</code></td><td><code>i32</code></td><td>任意</td><td>なし</td><td>パスワードに含める特殊文字の数</td></tr></tbody></table>

デフォルトでは、各件数パラメータはその文字種の**最小**件数を表します。負の値にすると**ちょうど**その件数になります (例: `.lowercase(-8)` で小文字がちょうど8文字)。すべての件数パラメータが負またはゼロ (厳密モード) のときは `length` は無視され、パスワードの総長は絶対値の合計で決まります。

### ファイルのダウンロード <a href="#download-a-file" id="download-a-file"></a>

{% tabs %}
{% tab title="ファイルのダウンロード" %}

```rust
secret.download_file(file_name, path);
```

{% endtab %}

{% tab title="ファイルのダウンロードの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDで特定のシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let secret = &secrets[0];

    // 所定のパスに保存
    let path = format!("./temp/demo_{}.txt", secret.title);
    secret.download_file("uploaded_file.txt", &path)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th>パラメータ</th><th>型</th><th>必須</th><th width="82.734375">デフォルト</th><th>説明</th></tr></thead><tbody><tr><td><code>file_name</code></td><td><code>&#x26;str</code></td><td>はい</td><td></td><td>ダウンロードするファイル名</td></tr><tr><td><code>path</code></td><td><code>&#x26;str</code></td><td>はい</td><td></td><td>ダウンロード先のパス</td></tr></tbody></table>

#### タイトルでファイルをダウンロード <a href="#download-file-by-title" id="download-file-by-title"></a>

レコードのタイトルと添付ファイル名を指定してダウンロードします。SDKはアクセス可能なレコードのうち `record_title` に一致するものを探し、そのレコードから `file_name` の添付を取り出します。

{% tabs %}
{% tab title="タイトルでファイルをダウンロード" %}

```rust
secrets_manager.download_file_by_title(record_title, file_name)
```

{% endtab %}

{% tab title="例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main() -> Result<(), KSMRError> {
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // レコードタイトルとファイル名でダウンロード
    if let Some(file_data) = secrets_manager.download_file_by_title("My Record Title", "report.pdf")? {
        std::fs::write("./report.pdf", &file_data)
            .map_err(|e| KSMRError::CustomError(e.to_string()))?;
        println!("File downloaded successfully");
    } else {
        println!("Record or file not found");
    }
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ          | 型      | 必須 | 説明               |
| -------------- | ------ | -- | ---------------- |
| `record_title` | `&str` | はい | ファイルを含むレコードのタイトル |
| `file_name`    | `&str` | はい | ダウンロードする添付ファイル名  |

**戻り値**

> 型: `Result<Option<Vec<u8>>, KSMRError>`

* `Ok(Some(bytes))` — 復号済みのファイルデータ (バイト列)
* `Ok(None)` — 一致するタイトルのレコードがない、または一致する名前の添付がない
* `Err(...)` — ダウンロードまたは復号のエラー

#### ファイルのサムネイルをダウンロード <a href="#download-file-thumbnail" id="download-file-thumbnail"></a>

一部の添付ファイル (特に画像) にはサムネイル用のプレビューがあります。本体ファイルとは別にサムネイルだけを取得できます。

{% tabs %}
{% tab title="サムネイルをダウンロード" %}

```rust
file.get_thumbnail_data()
```

{% endtab %}

{% tab title="サムネイルのダウンロード例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDで特定のシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let secret = &secrets[0];

    // すべてのファイルのサムネイルをダウンロード
    for mut file in secret.files.clone() {
        if let Some(thumbnail_data) = file.get_thumbnail_data()? {
            let thumbnail_path = format!("./temp/{}_thumb.jpg", file.name);
            std::fs::write(&thumbnail_path, &thumbnail_data)
                .map_err(|e| KSMRError::FileWriteError(thumbnail_path.clone(), e))?;
            println!("Downloaded thumbnail: {}", thumbnail_path);
        } else {
            println!("No thumbnail available for {}", file.name);
        }
    }

    Ok(())
}
```

{% endtab %}
{% endtabs %}

**戻り値**

> 型: `Result<Option<Vec<u8>>, KSMRError>`

* `Ok(Some(bytes))` — サムネイルデータ (通常はJPEG)
* `Ok(None)` — このファイルにサムネイルがない
* `Err(...)` — サムネイルのダウンロードまたは復号エラー

{% hint style="info" %}
画像ファイル (PNG、JPEG など) ではサムネイルが付くことが多いです。ドキュメントなど非画像のタイプでは、多くの場合サムネイルはありません。
{% endhint %}

### ファイルのアップロード <a href="#upload-file" id="upload-file"></a>

{% tabs %}
{% tab title="ファイルのアップロード" %}

```rust
upload_file(owner_record, keeper_file);
```

{% endtab %}

{% tab title="ファイルのアップロードの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    dto::file::KeeperFileUpload
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDで特定のシークレットを取得
    let secrets = secrets_manager.get_secrets(vec!["<RECORD UID>".to_string()])?;
    let owner_record = &secrets[0];

    // アップロード用にファイルデータを準備
    let file_path = "./local_file.txt";
    let file_name = Some("uploaded_file.txt");
    let file_title = Some("My File");
    let mime_type = Some("text/plain");
    let keeper_file = KeeperFileUpload::get_file_for_upload(
        file_path,
        file_name,
        file_title,
        mime_type
    )?;

    // 所有レコードに添付してアップロードし、ファイルUIDを取得
    let file_uid = secrets_manager.upload_file(owner_record, keeper_file)?;
    println!("Uploaded file UID: {}", file_uid);
    Ok(())
}
```

{% endtab %}
{% endtabs %}

**ファイルアップロードのパラメータ**

<table><thead><tr><th>パラメータ</th><th width="162.203125">型</th><th>必須</th><th>デフォルト</th><th>説明</th></tr></thead><tbody><tr><td><code>owner_record</code></td><td><code>Record</code></td><td>はい</td><td>None</td><td>ファイルをアップロードするレコード</td></tr><tr><td><code>keeper_file</code></td><td><code>KeeperFileUpload</code></td><td>はい</td><td></td><td>アップロードするファイル</td></tr></tbody></table>

**ファイルのパラメータ**

| パラメータ        | 型              | 必須 | デフォルト | 説明                                                      |
| ------------ | -------------- | -- | ----- | ------------------------------------------------------- |
| `file_path`  | `&str`         | はい | ​     | アップロードするファイルのパス                                         |
| `file_name`  | `Option<&str>` | はい | ​     | アップロードするファイルの名前                                         |
| `file_title` | `Option<&str>` | はい | ​     | アップロードするファイルのタイトル                                       |
| `mime_type`  | `Option<&str>` | はい | なし    | ファイル内のデータの種類。指定がなければ `application/octet-stream` が使用されます |

**戻り値**

> 型: `String`

添付ファイルのファイルUID

### シークレットの作成 <a href="#create-a-secret" id="create-a-secret"></a>

**要件**

* 共有フォルダUID
  * 共有フォルダはシークレットマネージャーアプリケーションからアクセス可能であること
  * あなたとシークレットマネージャーアプリケーションに編集権限があること
  * 共有フォルダ内に少なくとも1件のレコードがあること
* 作成するレコードとレコードフィールドは正しい形式であること
  * 各レコードタイプで想定されるフィールド形式は、[レコードの作成・更新の手順](/keeperpam/jp/commander-cli/command-reference/record-commands/creating-and-updating-records.md#record-types)をご参照ください
* TOTPフィールドは、KSM SDKの外部で生成されたURLのみを受け付けます
* レコード作成後は [upload\_file](/keeperpam/jp/secrets-manager/developer-sdk-library/python-sdk.md#upload-a-file) を使って添付ファイルをアップロードできます

{% tabs %}
{% tab title="レコードの作成" %}

```rust
secrets_manager.create_secret(folder_uid, record);
```

{% endtab %}

{% tab title="ログイン情報レコードの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    dto::{dtos::RecordCreate, field_structs::RecordField},
    utils
};
use serde_json::{self, json, Number, Value};

fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // これがRecordを作成する方法です
    let mut created_record =  RecordCreate::new("login".to_string(), "Login Record RUST_LOG_TEST".to_string(), Some("Dummy Notes".to_string()));
    
    // これが単一フィールドを作成する方法です 
    let password_field = RecordField::new_record_field_with_options("password".to_string(), Value::String(utils::generate_password()?), Some("Random password label".to_string()), false, true);

    // これはすべてのフィールドをベクターに直接作成する一例です
    let fields = vec![
        RecordField::new_record_field("login".to_string(), Value::String("login@email.com".to_string()), Some("My Custom Login lbl".to_string())),

        password_field,
     ];

    created_record.fields = Some(fields);
  
    // API呼び出しを行う
    let _ = secrets_manager.create_secret("Shared_folder_uid".to_string(), created_record)?;
    Ok(())
}
```

{% endtab %}

{% tab title="カスタムタイプの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    dto::{dtos::RecordCreate, field_structs::RecordField},
    utils
};
use serde_json::{self, json, Number, Value};

fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // これがRecordを作成する方法です
    let mut created_record =  RecordCreate::new("login".to_string(), "Login Record RUST_LOG_TEST".to_string(), Some("Dummy Notes".to_string()));
    
    // これが単一フィールドを作成する方法です 
    let password_field = RecordField::new_record_field_with_options("password".to_string(), Value::String(utils::generate_password()?), Some("Random password label".to_string()), false, true);

    // これはJSON文字列から値オブジェクトを作成する方法の一つです
    let security_question_value = Value::from_str("{\"question\": \"What is the question?\", \"answer\": \"This is the answer!\"}")?;
    
    // これはすべてのフィールドをベクターに直接作成する一例です
    let fields = vec![
        RecordField::new_record_field("login".to_string(), Value::String("login@email.com".to_string()), Some("My Custom Login lbl".to_string())),

        RecordField::new_record_field("login".to_string(), Value::String("login@email.com".to_string()), Some("My Label".to_string())),

        password_field,
        
        RecordField::new_record_field("securityQuestion".to_string(),security_question_value , Some("My Label".to_string())),

        RecordField::new_record_field("multiline".to_string(),Value::String("This\nIs a multiline\nnote".to_string()) , Some("My Multiline lbl".to_string())),

        RecordField::new_record_field("secret".to_string(),Value::String("SecretText".to_string()) , Some("My Hidden Field lbl".to_string())),

        RecordField::new_record_field("pinCode".to_string(),Value::String("1234567890".to_string()) , Some("My Pin Code Field Lbl".to_string())),

        RecordField::new_record_field("addressRef".to_string(),Value::String("some_UID".to_string()) , Some("My Address Reference".to_string())),

        RecordField::new_record_field("phone".to_string(),json!({"region": "US", "number": "510-444-3333"}) , Some("My Phone Number".to_string())),

        RecordField::new_record_field("date".to_string(),Value::Number(Number::from(1641934793000i64)) , Some("My date".to_string())),

        RecordField::new_record_field("date".to_string(),Value::String("September eleventh two thousand and eleven".to_string()) , Some("Bad day in history of humanity".to_string())),

        RecordField::new_record_field("name".to_string(),json!({"first": "Lincoln", "last": "Adams"}) , Some("His Name".to_string())),
        ];

    // ここで標準フィールドにfieldsオブジェクトを追加しています 
    created_record.fields = Some(fields);
    
    created_record.custom = Some(
        vec![
            RecordField::new_record_field("phone".to_string(),json!({"region": "US", "number": "510-222-5555", "ext": "99887", "type": "Mobile"}) , Some("My Custom Phone Lbl".to_string())),
        ]
    );
   
    // API呼び出しを行う
    let _ = secrets_manager.create_secret("Shared_folder_uid".to_string(), created_record)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ            | 型                   | 必須 | デフォルト | 説明                  |
| ---------------- | ------------------- | -- | ----- | ------------------- |
| `record_type`    | `DefaultRecordType` | はい | なし    | 作成するレコードのタイプ        |
| `title`          | `String`            | はい | ​     | 作成されたレコードのタイトル      |
| `note`           | `String`            | はい | なし    | 作成されたレコードに記載するノート   |
| `value`          | `String`            | はい | ​     | フィールドの値             |
| `label`          | `String`            | はい | なし    | フィールドのラベル           |
| `required`       | `bool`              | はい | false | フィールドが必須かどうかを定義します  |
| `privacy_screen` | `bool`              | はい | false | フィールド値を隠すかどうかを定義します |

#### 戻り値

型: `String`

新規レコードのレコードUID

### シークレットの削除 <a href="#delete-a-secret" id="delete-a-secret"></a>

Rust KSM SDKでは、Keeperボルト内のレコードを削除できます。

{% tabs %}
{% tab title="シークレットの削除" %}

```rust
secrets_manager.delete_secret(vec![record_uid]);
```

{% endtab %}

{% tab title="シークレットの削除例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};

fn main() -> Result<(), KSMRError> {
    // シークレットマネージャーのセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // UIDを指定してシークレットを削除
    let secret_to_delete = secrets_manager.delete_secret(["<RECORD UID>".to_string()])?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th width="121.6927490234375">パラメータ</th><th width="105.942626953125">型</th><th width="107.692626953125">必須</th><th width="95.7239990234375">デフォルト</th><th>説明</th></tr></thead><tbody><tr><td><code>record_uid</code></td><td><code>String</code></td><td>はい</td><td>なし</td><td>削除対象のレコードUID</td></tr></tbody></table>

### キャッシュ <a href="#caching" id="caching"></a>

ネットワークにアクセスできなくなった場合にシークレットへのアクセスを失わないようにするため、Rust SDKではシークレットをローカルマシン上の暗号化ファイルにキャッシュできます。

#### キャッシュの設定と構成 <a href="#setup-and-configure-cache" id="setup-and-configure-cache"></a>

Rust SDKには、キャッシュされたクエリをローカルファイルに書き出す既定のポスト関数 `caching_post_function` が含まれています。ネットワークに接続できるときは常にネットワークを優先し、ウェブボルトに到達できないときだけキャッシュへフォールバックします。

{% tabs %}
{% tab title="キャッシュの設定" %}

```rust
use keeper_secrets_manager_core::caching;

let mut client_options = ClientOptions::new_client_options_with_token(token, config);
client_options.set_custom_post_function(caching::caching_post_function);
let mut secrets_manager = SecretsManager::new(client_options)?;
```

{% endtab %}

{% tab title="キャッシュの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::FileKeyValueStorage,
    custom_error::KSMRError,
    caching
};
fn main()-> Result<(), KSMRError>{
    let token = "<Your One time token>".to_string();
    let file_name = FileKeyValueStorage::new_config_storage("test.json".to_string())?;

    let mut client_options = ClientOptions::new_client_options_with_token(token, file_name);

    // 災害復旧用キャッシュを有効化
    client_options.set_custom_post_function(caching::caching_post_function);

    let mut secrets_manager = SecretsManager::new(client_options)?;

    // 最初の成功した呼び出しがキャッシュに保存される (既定: $KSM_CACHE_DIR/ksm_cache.bin)
    let secrets = secrets_manager.get_secrets(Vec::new())?;

    // 以降の呼び出しは、ネットワーク障害時に自動的にキャッシュへフォールバック
    println!("Retrieved {} secrets (with automatic cache fallback)", secrets.len());

    Ok(())
}
```

{% endtab %}
{% endtabs %}

**キャッシュの保存場所**

* 既定: `$KSM_CACHE_DIR/ksm_cache.bin`
* `KSM_CACHE_DIR` が未設定の場合はシステムの一時ディレクトリを使用
* 環境変数で上書き: `export KSM_CACHE_DIR=/path/to/cache`

{% hint style="danger" %}
既定のキャッシュ関数は**最後に成功したリクエスト**の内容だけを保持します。たとえば、最初のリクエスト (R1) で UID1 を取得してキャッシュを更新したあと、続くリクエスト (R2) で UID2 の取得に失敗すると、キャッシュには UID2 が入りません。そのため、ネットワークが使えないときに UID2 を参照しようとしても、キャッシュに載っていなければ空の結果になります。
{% endhint %}

{% hint style="warning" %}
キャッシュからレコードを更新する場合 (または新規レコードを作成する場合)、キャッシュされたレコードデータは無効化され、同一レコードへの連続更新は失敗します。バッチ更新は、異なるレコードを変更する限り問題なく動作します。キャッシュ経由でレコードを更新したあとは、必ず `get_secrets()` を呼び出してキャッシュを更新し、ボルトから新しいレコードリビジョンなどの最新メタデータを取得してください。
{% endhint %}

#### カスタムキャッシュの実装 <a href="#custom-cache-implementations" id="custom-cache-implementations"></a>

ローカルキャッシュをネットワークより優先する、更新間隔を独自に制御するなど、要件が細かい場合は `KSMRCache` を基点にキャッシュ処理を実装できます。

{% tabs %}
{% tab title="カスタムキャッシュの設定" %}

```rust
use keeper_secrets_manager_core::cache::KSMRCache;

let cache = KSMRCache::new_file_cache(Some("./cache.bin"))?;
let mut client_options = ClientOptions::new_client_options_with_token(token, config);
client_options.set_cache(cache.into());
let mut secrets_manager = SecretsManager::new(client_options)?;
```

{% endtab %}

{% tab title="カスタムキャッシュの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    custom_error::KSMRError,
    storage::FileKeyValueStorage,
    cache::KSMRCache
};
fn main()-> Result<(), KSMRError>{
    let cache = KSMRCache::new_file_cache(Some("./cache.bin"))?;
    let token = "<Token>".to_string();
    let file_name = FileKeyValueStorage::new_config_storage("test.json".to_string())?;

    let mut client_options = ClientOptions::new_client_options_with_token(token, file_name);
    client_options.set_cache(cache.into());

    let mut secrets_manager = SecretsManager::new(client_options)?;
    let secrets = secrets_manager.get_secrets(Vec::new())?;

    for secret in secrets {
        println!("Secret: {}", secret.title);
    }

    Ok(())
}
```

{% endtab %}
{% endtabs %}

### フォルダ <a href="#folders" id="folders"></a>

フォルダは、作成・読み取り・更新・削除 (CRUD) の全操作に対応しています。

### フォルダの読み取り <a href="#read-folders" id="read-folders"></a>

フォルダ階層全体をダウンロードします。

{% tabs %}
{% tab title="フォルダの読み取り" %}

```rust
secrets_manager.get_folders()
```

{% endtab %}

{% tab title="フォルダの読み取りの例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーのセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;
    
    // すべてのフォルダを取得
    let folders = secrets_manager.get_folders()?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

**戻り値**

> 型: `Vec<KeeperFolder>`

### フォルダの作成 <a href="#create-folder" id="create-folder"></a>

`CreateOptions` とフォルダ名の指定が必要です。`CreateOptions` のフォルダUIDパラメータは必須で、共有フォルダのUIDです。サブフォルダのUIDは任意で、省略すると親 (共有フォルダ) 直下に通常のフォルダが作成されます。サブフォルダが親共有フォルダの直下の子である必要はなく、深い階層にも配置できます。

{% tabs %}
{% tab title="フォルダの作成" %}

```rust
secrets_manager.create_folder(create_options, folder_name, folders)
```

{% endtab %}

{% tab title="共有フォルダ配下にフォルダを作成" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    dto::payload::CreateOptions
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーのセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // 共有フォルダ直下にフォルダを作成
    let parent_folder_uid = "<PARENT_SHARED_FOLDER_UID>".to_string();
    let create_options = CreateOptions::new(parent_folder_uid, None);
    let new_folder_name = "My New Folder".to_string();

    let folder_uid = secrets_manager.create_folder(create_options, new_folder_name, Vec::new())?;
    println!("Created folder UID: {}", folder_uid);
    Ok(())
}
```

{% endtab %}

{% tab title="入れ子のサブフォルダを作成" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError,
    dto::payload::CreateOptions
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーのセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    // 既存フォルダ内にサブフォルダを作成
    let parent_folder_uid = "<PARENT_SHARED_FOLDER_UID>".to_string();
    let sub_folder_uid = Some("<EXISTING_FOLDER_UID>".to_string());
    let create_options = CreateOptions::new(parent_folder_uid, sub_folder_uid);
    let new_folder_name = "Nested Subfolder".to_string();

    let folder_uid = secrets_manager.create_folder(create_options, new_folder_name, Vec::new())?;
    println!("Created subfolder UID: {}", folder_uid);
    Ok(())
}
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th width="146.0677490234375">パラメータ</th><th width="179.9166259765625">型</th><th width="105.2344970703125">必須</th><th width="97.6875">デフォルト</th><th>説明</th></tr></thead><tbody><tr><td><code>create_options</code></td><td><code>CreateOptions</code></td><td>はい</td><td>なし</td><td>親とサブフォルダのUID</td></tr><tr><td><code>folder_name</code></td><td><code>str</code></td><td>はい</td><td></td><td>フォルダ名</td></tr><tr><td><code>folders</code></td><td><code>Vec&#x3C;KeeperFolder></code></td><td>いいえ</td><td>なし</td><td>CreateOptionsの親/サブフォルダ検索に使用するフォルダ一覧</td></tr></tbody></table>

### フォルダの更新 <a href="#update-folder" id="update-folder"></a>

フォルダのメタデータを更新します。現在はフォルダ名のみ更新可能です。

{% tabs %}
{% tab title="フォルダの更新" %}

```rust
secrets_manager.update_folder(folder_uid, folder_name, folders)
```

{% endtab %}

{% tab title="フォルダの更新の例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーのセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;

    let update_folder = secrets_manager.update_folder("<folder_uid>".to_string(),"dummy_updated_API_RUST".to_string(),Vec::new())?;
    println!("{}",(serde_json::to_string_pretty(&update_folder)?));
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ名        | 型                   | 必須  | デフォルト | 説明                        |
| ------------- | ------------------- | --- | ----- | ------------------------- |
| `folder_uid`  | `str`               | はい  |       | フォルダUID                   |
| `folder_name` | `str`               | はい  |       | 新しいフォルダ名                  |
| `folders`     | `Vec<KeeperFolder>` | いいえ | なし    | 親フォルダを検索するために使用するフォルダのリスト |

### フォルダの削除 <a href="#delete-folders" id="delete-folders"></a>

フォルダのリストを削除します。`force_deletion` フラグを使うと、空でないフォルダも削除できます。

{% hint style="info" %}
ボルトに存在しない、またはKSMアプリケーションと共有されていないフォルダUIDがあっても、エラーにはなりません。
{% endhint %}

{% hint style="info" %}
`force_deletion` を使用する場合、親フォルダとその子フォルダのUIDを同時に送信しないようにしてください。削除の順序によってはエラーが発生する可能性があります。例えば、親を削除する前に子が強制削除された場合などです。リストが常にFIFO順で処理される保証はありません。
{% endhint %}

{% tabs %}
{% tab title="フォルダの削除" %}

```rust
delete_folder(vec![“<FOLDER_UID>”.to_string()], false);
```

{% endtab %}

{% tab title="フォルダの削除の例" %}

```rust
use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result<(), KSMRError>{
    // シークレットマネージャーをセットアップ
    let config_string = "your_base64_goes_here".to_string();
    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
    let mut secrets_manager = SecretsManager::new(client_options)?;
    
    let folder_uids = vec!["folder1_uid".to_string(),"folder_2_uid".to_string()];
    secrets_manager.delete_folder(folder_uids, true)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ名           | 型             | 必須  | デフォルト | 説明              |
| ---------------- | ------------- | --- | ----- | --------------- |
| `folder_uids`    | `Vec<String>` | はい  | ―     | フォルダUIDのリスト     |
| `force_deletion` | `boolean`     | いいえ | false | 空でないフォルダを強制的に削除 |


---

# 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/developer-sdk-library/rust-sdk.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.
