Skip to content

decorative_secrets.onepassword

ApplyOnepasswordArgumentsOptions dataclass

This class contains options governing the behavior of the apply_onepassword_arguments decorator.

Attributes:

  • account (str | None) –

    A 1Password account URL. For example, individuals and families will use "my.1password.com", while teams and businesses will use a custom subdomain. If not provided, the OP_ACCOUNT environment variable will be used, if set. This is only necessary when using the 1Password CLI where multiple accounts are configured, and if no token is provided or inferred from an environment variable.

  • token (str | None) –

    A 1Password or 1Password connect service account token. If not provided, the OP_SERVICE_ACCOUNT_TOKEN or OP_CONNECT_TOKEN environment variables will be used, if set.

  • host (str | None) –

    A 1Password Connect host URL. If not provided, the OP_CONNECT_HOST environment variable will be used, if set. This is required when using a self-hosted 1Password Connect server.

  • timeout (float | None) –

    A timeout in seconds for any underlying op CLI invocation.

Source code in src/decorative_secrets/onepassword.py
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
@dataclass(frozen=True)
class ApplyOnepasswordArgumentsOptions:
    """
    This class contains options governing the behavior of the
    [apply_onepassword_arguments
    ](./#decorative_secrets.onepassword.apply_onepassword_arguments) decorator.

    Attributes:
        account: A 1Password account URL. For example, individuals
            and families will use "my.1password.com", while teams and
            businesses will use a custom subdomain. If not provided, the
            `OP_ACCOUNT` environment variable will be used, if set. This is
            only necessary when using the 1Password CLI where multiple
            accounts are configured, and if no token is provided or inferred
            from an environment variable.
        token: A 1Password or 1Password connect service account
            token. If not provided, the `OP_SERVICE_ACCOUNT_TOKEN` or
            `OP_CONNECT_TOKEN` environment variables will be used, if set.
        host: A 1Password Connect host URL. If not
            provided, the `OP_CONNECT_HOST` environment variable will be used,
            if set. This is required when using a self-hosted 1Password
            Connect server.
        timeout: A timeout in seconds for any underlying `op` CLI
            invocation.
    """

    account: str | None = None
    token: str | None = None
    host: str | None = None
    timeout: float | None = None

apply_onepassword_arguments

apply_onepassword_arguments(
    *args: decorative_secrets.onepassword.ApplyOnepasswordArgumentsOptions,
    **kwargs: str
) -> collections.abc.Callable

This decorator maps parameter names to 1Password resources. Each key represents the name of a parameter in the decorated function which accepts an explicit input, and the corresponding mapped value is a parameter name accepting a resource path with which to lookup a secret to pass to the mapped parameter in lieu of an explicitly provided argument.

Parameters:

  • *args (decorative_secrets.onepassword.ApplyOnepasswordArgumentsOptions, default: () ) –

    An optional ApplyOnepasswordArgumentsOptions instance governing the behavior of this decorator. If not provided, a default instance of ApplyOnepasswordArgumentsOptions() will be used. If multiple instances are provided, only the first will be used.

  • **kwargs (str, default: {} ) –

    A mapping of static parameter names to the parameter names of arguments accepting 1Password resource paths from which to retrieve the value when the key argument is not explicitly provided.

Example
from functools import (
    cache,
)
from decorative_secrets.onepassword import (
    apply_onepassword_arguments,
)
from my_client_sdk import (
    Client,
)


@cache
@apply_onepassword_arguments(
    client_id="client_id_onepassword",
    client_secret="client_secret_onepassword",
)
def get_client(
    client_id: str | None = None,
    client_secret: str = None,
    client_id_onepassword: str | None = None,
    client_secret_onepassword: str | None = None,
) -> Client:
    return Client(
        oauth2_client_id=client_id,
        oauth2_client_secret=client_secret,
    )


client: Client = get_client(
    client_id_onepassword=(
        "op://Vault Name/Client ID Item Name/username",
    ),
    client_secret_onepassword=(
        "op://Vault Name/Client Secret Item Name/credential",
    ),
)
Source code in src/decorative_secrets/onepassword.py
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def apply_onepassword_arguments(
    *args: ApplyOnepasswordArgumentsOptions,
    **kwargs: str,
) -> Callable:
    """
    This decorator maps parameter names to 1Password resources.
    Each key represents the name of a parameter in the decorated function
    which accepts an explicit input, and the corresponding mapped value is a
    parameter name accepting a resource path with which to lookup a secret
    to pass to the mapped parameter in lieu of an explicitly provided
    argument.

    Parameters:
        *args: An optional [ApplyOnepasswordArgumentsOptions
            ](./#decorative_secrets.onepassword.ApplyOnepasswordArgumentsOptions)
            instance governing the behavior of this decorator. If not provided,
            a default instance of [ApplyOnepasswordArgumentsOptions()
            ](./#decorative_secrets.onepassword.ApplyOnepasswordArgumentsOptions)
            will be used. If multiple instances are provided, only the first
            will be used.
        **kwargs:
            A mapping of static parameter names to the parameter names
            of arguments accepting 1Password resource paths from which to
            retrieve the value when the key argument is not explicitly
            provided.

    Example:
        ```python
        from functools import (
            cache,
        )
        from decorative_secrets.onepassword import (
            apply_onepassword_arguments,
        )
        from my_client_sdk import (
            Client,
        )


        @cache
        @apply_onepassword_arguments(
            client_id="client_id_onepassword",
            client_secret="client_secret_onepassword",
        )
        def get_client(
            client_id: str | None = None,
            client_secret: str = None,
            client_id_onepassword: str | None = None,
            client_secret_onepassword: str | None = None,
        ) -> Client:
            return Client(
                oauth2_client_id=client_id,
                oauth2_client_secret=client_secret,
            )


        client: Client = get_client(
            client_id_onepassword=(
                "op://Vault Name/Client ID Item Name/username",
            ),
            client_secret_onepassword=(
                "op://Vault Name/Client Secret Item Name/credential",
            ),
        )
        ```
    """
    options: ApplyOnepasswordArgumentsOptions
    args, options = _get_args_options(*args)
    read_onepassword_secret_: Callable[..., str] = read_onepassword_secret
    async_read_onepassword_secret_: Callable[
        [str, str | None, str | None, str | None], Coroutine[Any, Any, str]
    ] = async_read_onepassword_secret
    if (
        (options.account is not None)
        or (options.token is not None)
        or (options.host is not None)
        or (options.timeout is not None)
    ):  # pragma: no cover
        read_onepassword_secret_ = partial(
            read_onepassword_secret_,
            **({"account": options.account} if options.account else {}),
            **({"token": options.token} if options.token else {}),
            **({"host": options.host} if options.host else {}),
            **(
                {"timeout": options.timeout}
                if options.timeout is not None
                else {}
            ),
        )
        async_read_onepassword_secret_ = partial(
            async_read_onepassword_secret_,
            **({"account": options.account} if options.account else {}),
            **({"token": options.token} if options.token else {}),
            **({"host": options.host} if options.host else {}),
            **(
                {"timeout": options.timeout}
                if options.timeout is not None
                else {}
            ),
        )
    return apply_callback_arguments(
        read_onepassword_secret_,
        async_read_onepassword_secret_,
        **kwargs,
    )

which_op

which_op(*, timeout: float | None = 60) -> str

Locate the 1Password CLI executable, or attempt to install it if not found.

Source code in src/decorative_secrets/onepassword.py
186
187
188
189
190
191
192
193
194
195
196
197
def which_op(*, timeout: float | None = 60) -> str:
    """
    Locate the 1Password CLI executable, or attempt
    to install it if not found.
    """
    op: str = which("op") or "op"
    try:
        check_output((op, "--version"), timeout=timeout)
    except (CalledProcessError, FileNotFoundError):  # pragma: no cover
        _install_op(timeout=timeout)
        op = which("op") or "op"
    return op

iter_op_account_list

iter_op_account_list(
    *, timeout: float | None = 60
) -> collections.abc.Iterable[str]

Yield all 1password account names.

Source code in src/decorative_secrets/onepassword.py
215
216
217
218
219
220
221
222
223
224
225
226
def iter_op_account_list(*, timeout: float | None = 60) -> Iterable[str]:
    """
    Yield all 1password account names.
    """
    op: str = which_op(timeout=timeout)
    line: str
    for line in (
        check_output((op, "account", "list"), timeout=timeout)
        .strip()
        .split("\n")[1:]
    ):
        yield line.partition(" ")[0]

op_signin

op_signin(
    account: str | None = None,
    *,
    timeout: float | None = 60
) -> str

Sign in to 1Password using the CLI if not already signed in.

Source code in src/decorative_secrets/onepassword.py
229
230
231
232
233
234
235
236
237
238
239
240
241
def op_signin(
    account: str | None = None, *, timeout: float | None = 60
) -> str:
    """
    Sign in to 1Password using the CLI if not already signed in.
    """
    account = account or os.getenv("OP_ACCOUNT")
    if account:
        return _op_signin(account, timeout=timeout)
    op: str | None = None
    for account in iter_op_account_list(timeout=timeout):
        op = _op_signin(account, timeout=timeout)
    return op or which_op(timeout=timeout)

async_read_onepassword_secret async

async_read_onepassword_secret(
    resource: str,
    account: str | None = None,
    token: str | None = None,
    host: str | None = None,
    *,
    timeout: float | None = 60
) -> str

Asynchronously read a secret from 1Password using either the onepassword-sdk or onepasswordconnectsdk libraries, or the op executable (1password CLI), depending on the provided arguments and environment variables.

Parameters:

  • resource (str) –

    A 1Password secret resource path. For example: "op://Vault Name/Client Secret Item Name/credential"

  • account (str | None, default: None ) –

    A 1Password account URL. For example, individuals and families will use "my.1password.com", while teams and businesses will use a custom subdomain. This is only necessary when using the 1Password CLI where multiple accounts are configured.

  • token (str | None, default: None ) –

    A 1Password or 1Password connect service account token.

  • host (str | None, default: None ) –

    A 1Password Connect host URL. This is required when using self-hosted 1Password Connect.

  • timeout (float | None, default: 60 ) –

    A timeout in seconds for any underlying op CLI invocation.

Returns:

  • str

    The resolved secret value.

Source code in src/decorative_secrets/onepassword.py
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
@alru_cache(maxsize=None)
async def async_read_onepassword_secret(
    resource: str,
    account: str | None = None,
    token: str | None = None,
    host: str | None = None,
    *,
    timeout: float | None = 60,
) -> str:
    """
    Asynchronously read a secret from 1Password using either the
    `onepassword-sdk` or `onepasswordconnectsdk` libraries, or the `op`
    executable (1password CLI), depending on the provided arguments and
    environment variables.

    Parameters:
        resource: A 1Password secret resource path. For example:
            "op://Vault Name/Client Secret Item Name/credential"
        account: A 1Password account URL. For example, individuals and families
            will use "my.1password.com", while teams and businesses will use
            a custom subdomain. This is only necessary when using
            the 1Password CLI where multiple accounts are configured.
        token: A 1Password or 1Password connect service account token.
        host: A 1Password Connect host URL. This is required when using
            self-hosted 1Password Connect.
        timeout: A timeout in seconds for any underlying `op` CLI
            invocation.

    Returns:
        The resolved secret value.
    """
    account, token, host = _resolve_auth_arguments(account, token, host)
    if token:
        if host:
            return await _async_resolve_connect_resource(token, host, resource)
        return await _async_resolve_resource(token, resource)
    op: str | None = None
    with suppress(FileNotFoundError, CalledProcessError):
        op = op_signin(account, timeout=timeout)
    if not op:  # pragma: no cover
        op = which_op(timeout=timeout) or "op"
    return check_output(
        (op, "read")
        + (("--account", account) if account else ())
        + (("--session", token) if token else ())
        + (resource,),
        timeout=timeout,
    )

get_onepassword_secret

get_onepassword_secret(
    resource: str,
    account: str | None = None,
    token: str | None = None,
    host: str | None = None,
    *,
    timeout: float | None = 60
) -> str

Read a secret from 1Password using either the onepassword-sdk or onepasswordconnectsdk libraries, or the op executable (1password CLI), depending on the provided arguments and environment variables.

Parameters:

  • resource (str) –

    A 1Password secret resource path. For example: "op://Vault Name/Client Secret Item Name/credential"

  • account (str | None, default: None ) –

    A 1Password account URL. For example, individuals and families will use "my.1password.com", while teams and businesses will use a custom subdomain. This is only necessary when using the 1Password CLI where multiple accounts are configured.

  • token (str | None, default: None ) –

    A 1Password or 1Password connect service account token.

  • host (str | None, default: None ) –

    A 1Password Connect host URL. This is required when using self-hosted 1Password Connect.

  • timeout (float | None, default: 60 ) –

    A timeout in seconds for any underlying op CLI invocation.

Returns:

  • str

    The resolved secret value.

Source code in src/decorative_secrets/onepassword.py
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
def get_onepassword_secret(
    resource: str,
    account: str | None = None,
    token: str | None = None,
    host: str | None = None,
    *,
    timeout: float | None = 60,
) -> str:
    """
    Read a secret from 1Password using either the `onepassword-sdk` or
    `onepasswordconnectsdk` libraries, or the `op` executable (1password CLI),
    depending on the provided arguments and environment variables.

    Parameters:
        resource: A 1Password secret resource path. For example:
            "op://Vault Name/Client Secret Item Name/credential"
        account: A 1Password account URL. For example, individuals and families
            will use "my.1password.com", while teams and businesses will use
            a custom subdomain. This is only necessary when using
            the 1Password CLI where multiple accounts are configured.
        token: A 1Password or 1Password connect service account token.
        host: A 1Password Connect host URL. This is required when using
            self-hosted 1Password Connect.
        timeout: A timeout in seconds for any underlying `op` CLI
            invocation.

    Returns:
        The resolved secret value.
    """
    return _read_onepassword_secret(
        resource,
        account=account,
        token=token,
        host=host,
        timeout=timeout,
        **get_prefixed_environ("OP_"),
    )

main

main() -> None

Run a command: - install: Install the Databricks CLI if not already installed - get: Get a secret from Databricks and print it to stdout

Source code in src/decorative_secrets/onepassword.py
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
def main() -> None:
    """
    Run a command:
    -   install: Install the Databricks CLI if not already installed
    -   get: Get a secret from Databricks and print it to stdout
    """
    command = _get_command()
    if command in ("--help", "-h"):
        _print_help()
        return
    parser: argparse.ArgumentParser
    if command == "install":
        parser = argparse.ArgumentParser(
            prog="decorative-secrets onepassword install",
            description="Install the 1Password CLI",
        )
        parser.add_argument(
            "--timeout",
            default=None,
            type=float,
            help="A timeout, in seconds, for the install command",
        )
        namespace: argparse.Namespace = parser.parse_args()
        _install_op(timeout=namespace.timeout)
    elif command == "get":
        parser = argparse.ArgumentParser(
            prog="decorative-secrets onepassword get",
            description="Get a secret from 1Password",
        )
        parser.add_argument(
            "reference",
            type=str,
        )
        parser.add_argument(
            "--account",
            default=None,
            type=str,
            help="Which 1Password account to use",
        )
        parser.add_argument(
            "-t",
            "--token",
            default=None,
            type=str,
            help="A 1Password Service Account Token",
        )
        parser.add_argument(
            "--host",
            default=None,
            type=str,
            help="A 1Password Connect Host URL",
        )
        parser.add_argument(
            "--timeout",
            default=60,
            type=float,
            help="A timeout, in seconds, for any underlying `op` CLI "
            "invocation",
        )
        namespace = parser.parse_args()
        print(  # noqa: T201
            read_onepassword_secret(
                namespace.reference,
                host=namespace.host,
                account=namespace.account,
                token=namespace.token,
                timeout=namespace.timeout,
            )
        )