toolssecret 0.1.2
Tiny helper to fetch Google Secret Manager secrets with optional service account keyfile support.
Requires Python: >=3.9

# toolssecret

Tiny helper to fetch secrets from **Google Secret Manager**, with optional support for:

- **ADC (Application Default Credentials)** _(default)_
- A **service account JSON keyfile** (`path_keyfile`)
- A **service account info dict** (`keyfile_json`) — useful for CI/CD where you inject JSON via env/secret manager
- A **pre-resolved credentials object** (`credentials`) — reuse credentials from e.g. `toolsbq`
- A **pre-built SM client** (`client`) — fastest option for repeated calls

It's designed so you can simply:

```python
from toolssecret import get_secret
```

## Install

### From pypi

```text
pip install toolssecret
```

## Usage

### 1) Using ADC (Application Default Credentials)

```python
from toolssecret import get_secret

value = get_secret(secret_name="api_key_test", project_id="myproject")
print(value)
```

### 2) Using a service account keyfile

```python
from toolssecret import get_secret

value = get_secret(
    secret_name="api_key_test",
    project_id="myproject",
    path_keyfile="~/.config/gcloud/sa-keys/myserviceaccount.json",
)
print(value)
```

Notes:

- `path_keyfile` supports `~` and environment variable expansion like `$HOME/...` (expanded by Python).

### 3) Using a service account info dict

This is useful when you keep the service account JSON in an environment variable or secret.

```python
import json
import os
from toolssecret import get_secret

sa_info = json.loads(os.environ["GCP_SA_JSON"])
value = get_secret(
    secret_name="api_key_test",
    project_id="myproject",
    keyfile_json=sa_info,
)
print(value)
```

### 4) Reusing credentials from toolsbq

If you already have a BigQuery client from `toolsbq`, you can reuse its credentials to avoid re-reading the SA file:

```python
from toolsbq import bq_get_client
from toolssecret import get_secret

bq = bq_get_client(path_keyfile="~/key.json")
value = get_secret("my-secret", credentials=bq._credentials)
```

### 5) Pre-building an SM client for repeated calls

For hot loops or many secrets, pre-build the client once to avoid repeated gRPC channel setup:

```python
from toolssecret import sm_get_client, get_secret

client = sm_get_client(path_keyfile="~/key.json")
s1 = get_secret("secret-a", client=client)
s2 = get_secret("secret-b", client=client)
s3 = get_secret("secret-c", client=client)
```

### Project ID detection

If you omit `project_id`, `toolssecret` will try to detect it in this order:

1. `GOOGLE_CLOUD_PROJECT`, `GCLOUD_PROJECT`, `GCP_PROJECT` env vars
2. `keyfile_json["project_id"]` (if provided)
3. `path_keyfile`'s embedded project_id (if provided)
4. `GOOGLE_APPLICATION_CREDENTIALS` file's project_id
5. ADC project detection

## API

### `sm_get_client`

```python
sm_get_client(
    *,
    path_keyfile: str | None = None,
    keyfile_json: dict | None = None,
    credentials: Any | None = None,
) -> SecretManagerServiceClient
```

Build a reusable Secret Manager client. Credential priority:

1. `credentials` — pre-resolved credentials object (e.g. from `bq_client._credentials`)
2. `keyfile_json` / `path_keyfile` — explicit SA credentials
3. RAM-ADC / env / ADC fallback

### `get_secret`

```python
get_secret(
    secret_name: str,
    *,
    project_id: str | None = None,
    version_id: str = "latest",
    client: SecretManagerServiceClient | None = None,
    credentials: Any | None = None,
    path_keyfile: str | None = None,
    keyfile_json: dict | None = None,
) -> str
```

Credential priority:

1. `client` — pre-built SM client (fastest for repeated calls)
2. `credentials` — pre-resolved credentials object
3. `keyfile_json` — SA key as dict
4. `path_keyfile` — path to SA JSON file
5. RAM-ADC / env / ADC fallback

Secrets are cached **in-memory per process** (cache key includes project, secret name, version, and credential fingerprint).

## Security notes

- Avoid committing service account keyfiles to git.
- Prefer `keyfile_json` sourced from a secure secret store (CI secrets, vault, etc.).
- `toolssecret` does not log secret values.