> For the complete documentation index, see [llms.txt](https://docs.keeper.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.keeper.io/keeperpam/jp/secrets-manager/developer-sdk-library/rust-sdk.md).

# 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` が使用。`make_caching_post_function` では未使用。プロキシはファクトリへ渡す `reqwest::blocking::Client` で設定 |
| `ClientOptions.insecure_skip_verify` | `true` で TLS 証明書検証を無効化 (テスト以外は非推奨)                                                                                       |
| `KSM_SKIP_VERIFY`                    | `insecure_skip_verify` の環境変数版。`true` で検証をスキップ、`false` (既定) で検証を実施                                                        |

### シークレットの取得 <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".to_string(), "record_uid2".to_string()]; // 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><code>Vec::new()</code></td><td>取得するレコードUID。空のベクターを渡すと、アプリケーションがアクセスできるすべてのレコードを取得します。</td></tr></tbody></table>

**戻り値**

> 型: `Result<Vec<Record>, KSMRError>`

すべての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 のフィールド:**

| フィールド            | 型              | 説明                                                                   |
| ---------------- | -------------- | -------------------------------------------------------------------- |
| `records_filter` | `Vec<String>`  | 取得するレコードUID。空のベクターですべてのレコードを取得                                       |
| `folders_filter` | `Vec<String>`  | 絞り込むフォルダUID。空のベクターではフォルダによる絞り込みなし                                    |
| `request_links`  | `Option<bool>` | `true` のとき、レスポンスに GraphSync によるリンク先レコードを含める。リンク先は `Record.links` で参照 |

**戻り値**

> 型: `Result<Vec<Record>, KSMRError>`

クエリオプションに一致するすべてのレコード。

### シークレットから値を取得 <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", 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();
    // シークレットからログインフィールドを取得
    let my_secret_login = secret.get_standard_field_value(login_field, true)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ        | 型      | 必須 | デフォルト   | 説明           |
| ------------ | ------ | -- | ------- | ------------ |
| `field_type` | `&str` | はい | なし      | 取得するフィールドタイプ |
| `single`     | `bool` | 任意 | `false` | 最初の値のみを返す    |

**戻り値**

> 型: `Result<Value, KSMRError>`

JSON形式のフィールド値。`single = true` のときは最初の値、それ以外は配列を返します。

フィールドタイプは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` | `&str` | はい | -       | 取得するフィールドの型 |
| `single`     | `bool` | 任意 | `false` | 最初の値のみを返す   |

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

**戻り値**

> 型: `Result<Value, KSMRError>`

JSON形式のフィールド値。`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 %}

**レスポンス**

<table><thead><tr><th width="217.11328125">メソッド</th><th width="307.4375">戻り値の型</th><th>説明</th></tr></thead><tbody><tr><td><code>get_secrets_by_title()</code></td><td><code>Result&#x3C;Vec&#x3C;Record>, KSMRError></code></td><td>タイトルが完全一致するすべてのシークレット</td></tr><tr><td><code>get_secret_by_title()</code></td><td><code>Result&#x3C;Option&#x3C;Record>, KSMRError></code></td><td>タイトルが完全一致する最初の1件、または <code>None</code></td></tr></tbody></table>

| パラメータ          | 型      | 必須 | 説明                   |
| -------------- | ------ | -- | -------------------- |
| `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="表記の例" %}

<pre class="language-rust"><code class="lang-rust">use keeper_secrets_manager_core::{
    core::{ClientOptions, SecretsManager},
    storage::InMemoryKeyValueStorage,
    custom_error::KSMRError
};
fn main()-> Result&#x3C;(), KSMRError>{
    // シークレットマネージャーをセットアップ
<strong>    let config_string = "your_base64_goes_here".to_string();
</strong>    let config = InMemoryKeyValueStorage::new_config_storage(Some(config_string))?;
    let client_options = ClientOptions::new_client_options(config);
<strong>    let mut secrets_manager = SecretsManager::new(client_options)?;
</strong>
    // 表記法に一致するすべてのシークレットを取得する
    let notation = "HDQTnxkTcPSOsHNAlbI4aQ/field/login".to_string();
    let result = secrets_manager.get_notation(notation)?;
    Ok(())
}
</code></pre>

{% endtab %}
{% endtabs %}

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

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

**戻り値**

> 型: `Result<serde_json::Value, KSMRError>`

照会したフィールドの値 (JSON形式)。フィールドが単一値のときはJSON文字列に、複数値のときはJSON配列に解決されます。

#### 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` | `&str` | はい | 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()
        .ok_or_else(|| KSMRError::CustomError("no secret found with given UID".to_string()))?;

    // フィールド値を更新
    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>` — 成功またはエラー

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

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

{% hint style="info" %}
`rollback` パラメータは名前どおり、`true` でローテーションをロールバック、`false` で確定 (コミット) します。新しいパスワードを確定するには `false` を渡します。
{% endhint %}

{% 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()
        .ok_or_else(|| KSMRError::CustomError("no secret found with given UID".to_string()))?;
    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 %}

<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()
        .ok_or_else(|| KSMRError::CustomError("no secret found with given UID".to_string()))?;

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

    // ファイルリンクを削除するための更新オプションを作成
    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)をご参照ください。複数値を持つフィールドは、リストとして設定します。

#### ランダムパスワードの生成 <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()
        .ok_or_else(|| KSMRError::CustomError("no secret found with given UID".to_string()))?;

    // ランダムなパスワードを生成
    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>special_characterset</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>usize</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 %}

| パラメータ       | 型      | 必須 | 説明                          |
| ----------- | ------ | -- | --------------------------- |
| `file_name` | `&str` | はい | ダウンロードするファイルの名前、タイトル、またはUID |
| `path`      | `&str` | はい | ダウンロード先のパス                  |

**戻り値**

> 型: `Result<bool, KSMRError>`

`true` — ファイルが見つかり、`path` に保存された場合。`false` — レコードに一致する名前・タイトル・UIDのファイルがない場合。

#### タイトルでファイルをダウンロード <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` が使用されます |

**戻り値**

> 型: `Result<String, KSMRError>`

添付ファイルのファイル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) を使って添付ファイルをアップロードできます

> **複数値フィールド**: 1つのフィールドに複数の値を割り当てる場合 (電話番号が2件、セキュリティ質問が2件など) は、JSON配列を `RecordField::new_record_field` に直接渡します。単一オブジェクトはこれまでどおり自動でラップされます。2件以上ある場合のみ配列を指定してください。

{% 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", Value::String(utils::generate_password()?), Some("Random password label".to_string()), false, true);

    // これはすべてのフィールドをベクターに直接作成する一例です
    let fields = vec![
        RecordField::new_record_field("login", 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>{
    // setup secrets manager
    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)?;

    // This is how we create a Record
    let mut created_record = RecordCreate::new("login".to_string(), "Login Record RUST_LOG_TEST".to_string(), Some("Dummy Notes".to_string()));

    // This is how we create a single field
    let password_field = RecordField::new_record_field_with_options("password", Value::String(utils::generate_password()?), Some("Random password label".to_string()), false, true);

    // This is one way to create all fields directly in a vector
    let fields = vec![
        RecordField::new_record_field("login", Value::String("login@email.com".to_string()), Some("My Custom Login lbl".to_string())),

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

        password_field,

        // Single security question (pass an object for one entry)
        RecordField::new_record_field("securityQuestion", json!({"question": "What is the question?", "answer": "This is the answer!"}), Some("My Security Question".to_string())),

        // Multiple security questions (pass an array for more than one entry)
        RecordField::new_record_field("securityQuestion", json!([
            {"question": "Childhood pet?", "answer": "Fluffy"},
            {"question": "City of birth?", "answer": "Chicago"},
        ]), Some("My Security Questions".to_string())),

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

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

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

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

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

        // Multiple phone numbers (pass an array for more than one entry)
        RecordField::new_record_field("phone", json!([
            {"region": "US", "number": "510-444-3333", "type": "Mobile"},
            {"region": "US", "number": "510-555-6666", "type": "Work"},
        ]), Some("My Phone Numbers".to_string())),

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

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

    // Here we are adding fields object to standard fields
    created_record.fields = Some(fields);

    created_record.custom = Some(
        vec![
            RecordField::new_record_field("phone", json!({"region": "US", "number": "510-222-5555", "ext": "99887", "type": "Mobile"}), Some("My Custom Phone Lbl".to_string())),
        ]
    );

    // Make the API call
    let _ = secrets_manager.create_secret("Shared_folder_uid".to_string(), created_record)?;
    Ok(())
}
```

{% endtab %}
{% endtabs %}

| パラメータ                  | 型              | 必須 | 説明                      |
| ---------------------- | -------------- | -- | ----------------------- |
| `parent_folder_uid`    | `String`       | はい | レコードを作成する共有フォルダのUID     |
| `record_create_object` | `RecordCreate` | はい | レコード定義 (タイプ、タイトル、フィールド) |

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

<table><thead><tr><th width="142.94140625">フィールド</th><th width="170.390625">型</th><th width="116.734375">必須</th><th>デフォルト</th><th>説明</th></tr></thead><tbody><tr><td><code>record_type</code></td><td><code>String</code></td><td>はい</td><td></td><td>レコードタイプ (例: <code>"login"</code>)</td></tr><tr><td><code>title</code></td><td><code>String</code></td><td>はい</td><td></td><td>レコードのタイトル</td></tr><tr><td><code>notes</code></td><td><code>Option&#x3C;String></code></td><td>いいえ</td><td>なし</td><td>レコードの任意メモ</td></tr><tr><td><code>fields</code></td><td><code>Vec&#x3C;RecordField></code></td><td>いいえ</td><td>なし</td><td>標準フィールド</td></tr><tr><td><code>custom</code></td><td><code>Vec&#x3C;RecordField></code></td><td>いいえ</td><td>なし</td><td>カスタムフィールド</td></tr></tbody></table>

**戻り値**

> 型: `Result<String, KSMRError>`

新規レコードのレコード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(vec!["<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>Vec&#x3C;String></code></td><td>はい</td><td>なし</td><td>削除対象レコードのUID</td></tr></tbody></table>

**戻り値**

> 型: `Result<String, KSMRError>`

成功時のサーバー応答文字列。

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

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

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

Rust SDKには、災害復旧用キャッシュとして `caching::make_caching_post_function(client)` があります。最後に成功したAPIレスポンスをローカルの暗号化ファイルに保存し、サーバーに到達できないときはそのデータへ自動的にフォールバックします。`reqwest::blocking::Client` は非同期コンテキストの外で一度だけ構築してください (`tokio::task::spawn_blocking` 内での利用は安全です)。構築したクライアントをファクトリに渡します。ネットワーク接続があるときは、キャッシュよりライブ応答が優先されます。

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

```rust
use keeper_secrets_manager_core::caching;

// Build the client once outside any async context — safe under tokio::spawn_blocking
let http_client = reqwest::blocking::Client::builder().build()?;
let mut client_options = ClientOptions::new_client_options_with_token(token, config);
client_options.set_custom_post_function(caching::make_caching_post_function(http_client));
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);

    // Build the client once outside any async context — safe under tokio::spawn_blocking
    let http_client = reqwest::blocking::Client::builder()
        .build()
        .map_err(|e| KSMRError::HTTPError(e.to_string()))?;
    client_options.set_custom_post_function(caching::make_caching_post_function(http_client));

    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 %}

**戻り値**

> 型: `Result<Vec<KeeperFolder>, KSMRError>`

### フォルダの作成 <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>String</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`  | `String`            | はい  |       | フォルダUID                   |
| `folder_name` | `String`            | はい  |       | 新しいフォルダ名                  |
| `folders`     | `Vec<KeeperFolder>` | いいえ | なし    | 親フォルダを検索するために使用するフォルダのリスト |

**戻り値**

> 型: `Result<String, KSMRError>`

成功時のサーバー応答文字列。

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

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

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

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

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

```rust
secrets_manager.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_delete` | `bool`        | いいえ | `false` | `true` にすると空でないフォルダも削除。既定の `false` ではレコードを含むフォルダはエラー |

**戻り値**

> 型: `Result<Vec<HashMap<String, Value>>, KSMRError>`

削除した各フォルダの応答エントリのリスト。成功時は通常空です。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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.
