> 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/commander-sdk/keeper-commander-sdks/sdk-command-reference/secrets-manager-commands/secrets-manager-share-commands.md).

# Secrets Manager Share Commands

This page focuses on usage of secrets manager commands related to sharing and removing the secrets to an application

### Overview

Controls which **records or folders** (secrets) are accessible to a Secrets Manager App.

* User "share" secrets with an App by linking them via this command.
* User can also choose whether the app has **read-only** or **editable** access.

### Commands Supported

* [Secrets manager Share Command](#secrets-manager-share)
* [Secrets Manager Unshare Command](#secrets-manager-unshare)

### Secrets Manager Share

This command associates a vault folder or record with a Secrets Manager Application, granting the app access to those secrets.

<details>

<summary>DotNet CLI</summary>

**Command:** `ksm`

**Action:** `share`

**Flags:**

* `--folder` : Shared Folder UID or name. "share", "unshare" only
* `-e, --can-edit` : Can secret be edited? "share", "unshare" only
* `--help` : Display this help screen.
* `--version` : Display version information.
* `value pos. 0` : KSM command: "view", "create", "delete", "share", "unshare", "add-client",\
  "delete-client", "list", "app-share", "app-unshare"
* `value pos. 1` : Secret Manager application UID or Title

**Example:**

```bash
My Vault > ksm share ksm_app_uid --folder folder_uid
  Application UID: ksm_app_uid
               Title: Test_Example Application

Shares
  #  Share Type    Share UID               Share Title                    Editable  Created           
---  ------------  ----------------------  -----------------------------  --------  ------------------
  1  SharedFolder  ksm_app_uid             Example Resources                 X         5/2/2025 9:53 AM

Devices
  #  Name                  Device ID  Created             Last Accessed     
---  --------------------  ---------  ------------------  ------------------
  1  Exmaple Application    4xeebo     5/2/2025 9:53 AM    7/8/2025 10:56 AM  
```

</details>

<details>

<summary>DotNet SDK</summary>

**Function:** `ShareToSecretManagerApplication`

```csharp
 Task<SecretsManagerApplication> ShareToSecretManagerApplication(string applicationId,
            string sharedFolderOrRecordUid, bool canEdit);
```

**Arguments:**

`applicationId` - ID of ksm application to whom the folder or record is being shared

`sharedFolderOrRecordUid` ID of record or shared folder

`canEdit` - Boolean whether the permission to be edited is to be given or not

</details>

<details>

<summary>PowerCommander</summary>

**Command:** `Grant-KeeperSecretManagerFolderAccess`

**Aliases :** `ksm-share`

**Flags:**

* `-App` : Application UID
* `-Secret` : UID of the Secret/Record/Folder

**Example:**

```powershell
PS > Grant-KeeperSecretManagerFolderAccess -App ksm_app_uid  -Secret record_uid   

Uid                    Title                    IsExternalShare DeviceCount ShareCount
---                    -----                    --------------- ----------- ----------
ksm_app_uid            Example Application         False           7           6
```

</details>

<details>

<summary>Python CLI</summary>

**Command**: `secrets-manager-share --command=<add/remove/update>`

**Parameters**:

* `--command` Add, remove, or update
* `-a` `--app` Application Name or UID
* `-s` `--secret` Record UID - space separated (e.g., "uid1 uid2 uid3")

**Options**:

* `-e` `--editable` Grant editable access
* `--readonly` Set the share to read-only access

**Examples:**

```sh
secrets-manager-share --command add --app "My KSM App" --secret "IQ_uid1 IQ_uid2" --editable
```

```sh
secrets-manager-share --command remove --app "My KSM App" --secret "IQ_uid1 IQ_uid2"
```

```sh
secrets-manager-share --command update --app "My KSM App" --secret "IQ_uid1" --readonly
```

</details>

<details>

<summary>Python SDK</summary>

**Function map:**

* Add: `ksm_management.KSMShareManagement.add_secrets_to_ksm_app()`
* Remove: `ksm_management.KSMShareManagement.remove_secrets_from_ksm_app()`
* Update: `ksm_management.update_secrets_manager_app_shares()`

**Example:**

```python
import sqlite3
from typing import List, Optional, Tuple

from keepersdk import errors
from keepersdk.authentication import keeper_auth
from keepersdk.enterprise import enterprise_data as enterprise_data_types
from keepersdk.vault import sqlite_storage, vault_online, ksm_management


def open_vault(keeper_auth_context: keeper_auth.KeeperAuth) -> vault_online.VaultOnline:
    """Create vault, sync down, and return VaultOnline."""
    conn = sqlite3.Connection('file::memory:', uri=True)
    vault_storage = sqlite_storage.SqliteVaultStorage(
        lambda: conn,
        vault_owner=bytes(keeper_auth_context.auth_context.username, 'utf-8'),
    )
    vault = vault_online.VaultOnline(keeper_auth_context, vault_storage)
    vault.sync_down()
    return vault


def resolve_app_uid(vault: vault_online.VaultOnline, app_uid_or_name: str) -> str:
    """Resolve KSM app UID from UID or application name."""
    app = ksm_management.get_secrets_manager_app(vault, app_uid_or_name)
    return app.uid


def get_app_master_key(vault: vault_online.VaultOnline, app_uid: str) -> bytes:
    """Get decrypted record key for the KSM application."""
    master_key = vault.vault_data.get_record_key(app_uid)
    if not master_key:
        raise ValueError(f'Could not resolve record key for application {app_uid}')
    return master_key


# ---------------------------------------------------------------------------
# ADD — share record(s) or shared folder(s) TO a KSM app
# CLI: secrets-manager-share --command add --app ... --secret "uid1 uid2" [--editable]
# ---------------------------------------------------------------------------
def add_secrets_to_ksm_app(
    vault: vault_online.VaultOnline,
    app_uid_or_name: str,
    secret_uids: List[str],
    *,
    is_editable: bool = False,
    enterprise: Optional[enterprise_data_types.EnterpriseData] = None,
) -> List[Tuple[str, str]]:
    """
    Add secrets to a KSM application.

    Args:
        vault: Synced VaultOnline instance.
        app_uid_or_name: KSM app name or UID.
        secret_uids: Record or shared-folder UIDs to share.
        is_editable: True = editable by KSM client, False = read-only (default).
        enterprise: Enterprise data (used to refresh user permissions on shared items).
                    Pass None if you only need the KSM share add API call.

    Returns:
        List of (secret_uid, secret_type) tuples for successfully added secrets.
    """
    app_uid = resolve_app_uid(vault, app_uid_or_name)
    master_key = get_app_master_key(vault, app_uid)

    # Shares secrets via KSM app-share API; sync_down() runs inside
    added = ksm_management.KSMShareManagement.add_secrets_to_ksm_app(
        vault=vault,
        enterprise=enterprise,
        app_uid=app_uid,
        master_key=master_key,
        secret_uids=secret_uids,
        is_editable=is_editable,
    )

    perm = 'editable' if is_editable else 'read-only'
    print(f'Added {len(added)} secret(s) to app {app_uid} ({perm}):')
    for secret_uid, secret_type in added:
        print(f'  {secret_uid}\t{secret_type}')
    return added


# ---------------------------------------------------------------------------
# REMOVE — remove existing secret shares FROM a KSM app
# CLI: secrets-manager-share --command remove --app ... --secret "uid1 uid2"
# ---------------------------------------------------------------------------
def remove_secrets_from_ksm_app(
    vault: vault_online.VaultOnline,
    app_uid_or_name: str,
    secret_uids: List[str],
) -> List[str]:
    """
    Remove secrets already shared with a KSM application.

    Returns:
        List of UIDs that were actually removed.
    """
    if not secret_uids:
        raise ValueError('At least one secret UID is required')

    app_uid = resolve_app_uid(vault, app_uid_or_name)

    # Optional: validate UIDs are currently shared (same as CLI behavior)
    app_infos = ksm_management.get_app_info(vault, app_uid)
    if not app_infos:
        raise ValueError(f'Could not retrieve application info for UID: {app_uid}')

    current_shared = {
        share.secretUid if isinstance(share.secretUid, str)
        else __import__('keepersdk.utils', fromlist=['utils']).utils.base64_url_encode(share.secretUid)
        for share in getattr(app_infos[0], 'shares', [])
    }
    # Normalize to base64-url UIDs
    from keepersdk import utils
    current_shared = {
        uid if len(uid) == 22 else utils.base64_url_encode(uid)
        for uid in current_shared
    }

    valid_uids = [uid for uid in secret_uids if uid in current_shared]
    invalid_uids = [uid for uid in secret_uids if uid not in current_shared]

    for uid in invalid_uids:
        print(f'Warning: {uid} is not shared with this application; skipping.')

    if not valid_uids:
        print('No valid secrets to remove.')
        return []

    ksm_management.KSMShareManagement.remove_secrets_from_ksm_app(
        vault, app_uid, valid_uids
    )
    vault.sync_down()  # remove API does not sync automatically

    print(f'Removed {len(valid_uids)} secret(s) from app {app_uid}:')
    for uid in valid_uids:
        print(f'  {uid}')
    return valid_uids


# ---------------------------------------------------------------------------
# UPDATE — change editable <-> read-only on secrets ALREADY shared with the app
# CLI: secrets-manager-share --command update --app ... --secret "uid1" --editable|--readonly
# ---------------------------------------------------------------------------
def update_secrets_manager_app_shares(
    vault: vault_online.VaultOnline,
    app_uid_or_name: str,
    secret_uids: List[str],
    *,
    is_editable: bool,
) -> List[str]:
    """
    Update share permissions on secrets already in the KSM app (remove + re-add).

    Returns:
        List of UIDs that were actually updated.
    """
    updated_uids = ksm_management.update_secrets_manager_app_shares(
        vault=vault,
        uid_or_name=app_uid_or_name,
        secret_uids=secret_uids,
        is_editable=is_editable,
    )

    if updated_uids:
        perm = 'editable' if is_editable else 'read-only'
        print(f'Updated share permissions to {perm}:')
        for uid in updated_uids:
            print(f'  {uid}')
    else:
        print('No shares were updated (may already match, or not shared with app).')

    return updated_uids


# ---------------------------------------------------------------------------
# Example usage
# ---------------------------------------------------------------------------
def main():
    keeper_auth_context = ...  # from your login flow
    enterprise_data = ...      # optional for add; EnterpriseData if enterprise admin

    vault = open_vault(keeper_auth_context)

    app_uid_or_name = 'My KSM App'
    secret_uids = ['IQ_recordUid1', 'IQ_recordUid2', 'IQ_sharedFolderUid3']

    try:
        # 1) ADD secrets to the app (read-only by default; pass is_editable=True for editable)
        add_secrets_to_ksm_app(
            vault,
            app_uid_or_name,
            secret_uids,
            is_editable=False,
            enterprise=enterprise_data,
        )

        # 2) UPDATE permissions to editable
        update_secrets_manager_app_shares(
            vault,
            app_uid_or_name,
            secret_uids=['IQ_recordUid1'],
            is_editable=True,
        )

        # 3) UPDATE permissions to read-only
        update_secrets_manager_app_shares(
            vault,
            app_uid_or_name,
            secret_uids=['IQ_recordUid1'],
            is_editable=False,
        )

        # 4) REMOVE secrets from the app
        remove_secrets_from_ksm_app(
            vault,
            app_uid_or_name,
            secret_uids=['IQ_recordUid2'],
        )

    except ValueError as e:
        print(f'Validation error: {e}')
    except errors.KeeperApiError as e:
        print(f'API error ({e.result_code}): {e.message}')
    except Exception as e:
        print(f'Error: {e}')
    finally:
        vault.close()
        keeper_auth_context.close()


if __name__ == '__main__':
    main()
```

</details>

### Secrets Manager Unshare

This command removes a previously shared folder or record from a Secrets Manager Application, revoking its access to that secret.

<details>

<summary>DotNet CLI</summary>

**Command:** `ksm`

**Action:** `unshare`

**Flags:**

* `--folder` : Shared Folder UID or name. "share", "unshare" only
* `-e, --can-edit` : Can secret be edited? "share", "unshare" only
* `value pos. 1` : Secret Manager application UID or Title

**Example:**

```bash
My Vault > ksm unshare ksm_app_uid --folder folder_uid
  Application UID: ksm_app_uid
               Title: Test_Example Application

Shares
  #  Share Type    Share UID               Share Title                    Editable  Created           
---  ------------  ----------------------  -----------------------------  --------  ------------------

Devices
  #  Name                  Device ID  Created             Last Accessed     
---  --------------------  ---------  ------------------  ------------------
  1  Exmaple Application    4xeebo     5/2/2025 9:53 AM    7/8/2025 10:56 AM    
```

</details>

<details>

<summary>DotNet SDK</summary>

**Function:** `UnshareFromSecretManagerApplication`

```csharp
Task<SecretsManagerApplication> UnshareFromSecretManagerApplication(string applicationId,
            string sharedFolderOrRecordUid);
```

**Arguments:**

`applicationId` - ID of ksm application to whom the folder or record is being unshared

`sharedFolderOrRecordUid` ID of record or shared folder whose permissions are being revoked

</details>

<details>

<summary>PowerCommander</summary>

**Command**: `Revoke-KeeperSecretManagerFolderAccess`

**Alias:** `ksm-unshare`

**Flags**:

* `-App` : Application UID
* `-Secret` : UID of the Secret/Record/Folder

**Example:**

```powershell
PS > Revoke-KeeperSecretManagerFolderAccess -App ksm_app_uid  -Secret record_uid 

Uid                    Title                    IsExternalShare DeviceCount ShareCount
---                    -----                    --------------- ----------- ----------
ksm_app_uid            Example Application         False           7           5
```

</details>

<details>

<summary>Python CLI</summary>

**Command**: `secrets-manager-share --command=<add/remove>`

**Parameters**:

* `--command` Add or remove
* `-a` `--app` Application Name or UID
* `-s` `--secret` Record UID - space separated (e.g., "uid1 uid2 uid3")

**Example:**

```sh
My Vault> secrets-manager-share --command='remove' -a='ksm_uid' -s='record_uid'
Shared secrets were successfully removed from the application
```

</details>

<details>

<summary>Python SDK</summary>

**Function:**

```python
ksm_management.KSMShareManagement.remove_secrets_from_ksm_app(
    vault=vault,
    app_uid=app_uid,
    secret_uids=secret_uids,
)
```

</details>


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.keeper.io/keeperpam/commander-sdk/keeper-commander-sdks/sdk-command-reference/secrets-manager-commands/secrets-manager-share-commands.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
