diff --git a/example/desktop_app.py b/example/desktop_app.py index 49992766..234ed7de 100644 --- a/example/desktop_app.py +++ b/example/desktop_app.py @@ -14,7 +14,8 @@ async def main(): # Connect to the 1Password desktop app client = await Client.authenticate( auth=DesktopAuth( - account_name="YourAccountNameAsShownInTheDesktopApp" # Set to your 1Password account name as shown at the top left sidebar of the app, or your account UUID. + # Set to your 1Password account name as shown at the top left sidebar of the app, or your account UUID. + account_name="YourAccountNameAsShownInTheDesktopApp" ), # Set to your own integration name and version integration_name="My 1Password Integration", @@ -42,16 +43,26 @@ async def main(): group_id = os.environ.get("OP_GROUP_ID") if group_id is None: raise Exception("OP_GROUP_ID is required") - + await showcase_group_permission_operations(client, vault_id, group_id) + environment_id = os.environ.get("OP_ENVIRONMENT_ID") + if environment_id is not None: + # [developer-docs.sdk.python.get-environment-variables]-start + # Read variables from a 1Password Environment + environment = await client.environments.get_variables(environment_id) + for variable in environment.variables: + print(f"{variable.name}: {variable.value} (masked: {variable.masked})") + # [developer-docs.sdk.python.get-environment-variables]-end + + async def showcase_vault_operations(client: Client): # [developer-docs.sdk.python.create-vault]-start # Create a vault vault_create_params = VaultCreateParams( - title="Python SDK Vault", - description="A description", - allow_admins_access=False, + title="Python SDK Vault", + description="A description", + allow_admins_access=False, ) created_vault = await client.vaults.create(vault_create_params) print(f"Created vault: {created_vault.id} - {created_vault.title}") @@ -69,7 +80,7 @@ async def showcase_vault_operations(client: Client): title="Python SDK Updated Name", description="Updated description", ) - + await client.vaults.update(created_vault.id, update_params) # [developer-docs.sdk.python.update-vault]-end @@ -95,6 +106,7 @@ async def showcase_vault_operations(client: Client): print(vault.title) # [developer-docs.sdk.python.list-vault]-end + async def showcase_group_permission_operations(client: Client, vault_id: str, group_id: str): # [developer-docs.sdk.python.grant-group-permissions]-start # Grant group permissions in a vault @@ -117,7 +129,7 @@ async def showcase_group_permission_operations(client: Client, vault_id: str, gr GroupVaultAccess( vault_id=vault_id, group_id=group_id, - permissions= READ_ITEMS | CREATE_ITEMS | UPDATE_ITEMS, + permissions=READ_ITEMS | CREATE_ITEMS | UPDATE_ITEMS, ) ], ) @@ -131,13 +143,14 @@ async def showcase_group_permission_operations(client: Client, vault_id: str, gr group_id=group_id, ) # [developer-docs.sdk.python.update-group-permissions]-end - + # [developer-docs.sdk.python.get-group]-start # Get a group group = await client.groups.get(group_id, GroupGetParams(vaultPermissions=False)) print(group) # [developer-docs.sdk.python.get-group]-end + async def showcase_batch_item_operations(client: Client, vault_id: str): # [developer-docs.sdk.python.batch-create-items]-start items_to_create = [] @@ -189,7 +202,8 @@ async def showcase_batch_item_operations(client: Client, vault_id: str): item_ids = [] for res in batchCreateResponse.individual_responses: if res.content is not None: - print('Created item "{}" ({})'.format(res.content.title, res.content.id)) + print('Created item "{}" ({})'.format( + res.content.title, res.content.id)) item_ids.append(res.content.id) elif res.error is not None: print("[Batch create] Something went wrong: {}".format(res.error)) @@ -200,7 +214,8 @@ async def showcase_batch_item_operations(client: Client, vault_id: str): batchGetReponse = await client.items.get_all(vault_id, item_ids) for res in batchGetReponse.individual_responses: if res.content is not None: - print('Obtained item "{}" ({})'.format(res.content.title, res.content.id)) + print('Obtained item "{}" ({})'.format( + res.content.title, res.content.id)) elif res.error is not None: print("[Batch get] Something went wrong: {}".format(res.error)) # [developer-docs.sdk.python.batch-get-items]-end @@ -215,6 +230,5 @@ async def showcase_batch_item_operations(client: Client, vault_id: str): print("Deleted item {}".format(id)) # [developer-docs.sdk.python.batch-delete-items]-end - if __name__ == "__main__": asyncio.run(main()) diff --git a/example/example.py b/example/example.py index 5f0399d2..36c57985 100644 --- a/example/example.py +++ b/example/example.py @@ -204,13 +204,23 @@ async def main(): await showcase_batch_item_operations(client, vault_id) + environment_id = os.environ.get("OP_ENVIRONMENT_ID") + if environment_id is not None: + # [developer-docs.sdk.python.get-environment-variables]-start + # Read variables from a 1Password Environment + environment = await client.environments.get_variables(environment_id) + for variable in environment.variables: + print(f"{variable.name}: {variable.value} (masked: {variable.masked})") + # [developer-docs.sdk.python.get-environment-variables]-end + + async def showcase_vault_operations(client: Client): # [developer-docs.sdk.python.create-vault]-start # Create a vault vault_create_params = VaultCreateParams( - title="Python SDK Vault", - description="A description", - allow_admins_access=False, + title="Python SDK Vault", + description="A description", + allow_admins_access=False, ) created_vault = await client.vaults.create(vault_create_params) print(f"Created vault: {created_vault.id} - {created_vault.title}") @@ -259,6 +269,7 @@ async def showcase_vault_operations(client: Client): print(f"{vault.title} ({vault.id})") # [developer-docs.sdk.python.list-vault]-end + async def showcase_batch_item_operations(client: Client, vault_id: str): # [developer-docs.sdk.python.batch-create-items]-start items_to_create = [] @@ -310,7 +321,8 @@ async def showcase_batch_item_operations(client: Client, vault_id: str): item_ids = [] for res in batchCreateResponse.individual_responses: if res.content is not None: - print('Created item "{}" ({})'.format(res.content.title, res.content.id)) + print('Created item "{}" ({})'.format( + res.content.title, res.content.id)) item_ids.append(res.content.id) elif res.error is not None: print("[Batch create] Something went wrong: {}".format(res.error)) @@ -321,7 +333,8 @@ async def showcase_batch_item_operations(client: Client, vault_id: str): batchGetReponse = await client.items.get_all(vault_id, item_ids) for res in batchGetReponse.individual_responses: if res.content is not None: - print('Obtained item "{}" ({})'.format(res.content.title, res.content.id)) + print('Obtained item "{}" ({})'.format( + res.content.title, res.content.id)) elif res.error is not None: print("[Batch get] Something went wrong: {}".format(res.error)) # [developer-docs.sdk.python.batch-get-items]-end @@ -657,7 +670,7 @@ async def showcase_group_permission_operations(client: Client, vault_id: str, gr ) print(f"Revoked group {group_id}'s permissions in vault {vault_id}") # [developer-docs.sdk.python.revoke-group-permissions]-end - + # [developer-docs.sdk.python.get-group]-start # Get a group group = await client.groups.get(group_id, GroupGetParams(vaultPermissions=False)) diff --git a/src/onepassword/__init__.py b/src/onepassword/__init__.py index bd9be8dd..af799df1 100644 --- a/src/onepassword/__init__.py +++ b/src/onepassword/__init__.py @@ -7,6 +7,7 @@ from .secrets import Secrets from .items import Items from .vaults import Vaults +from .environments import Environments from .groups import Groups @@ -19,6 +20,7 @@ "Secrets", "Items", "Vaults", + "Environments", "Groups", "DesktopAuth", "DEFAULT_INTEGRATION_NAME", diff --git a/src/onepassword/build_number.py b/src/onepassword/build_number.py index 74489d5d..2e22cdb4 100644 --- a/src/onepassword/build_number.py +++ b/src/onepassword/build_number.py @@ -1 +1 @@ -SDK_BUILD_NUMBER = "0040003" +SDK_BUILD_NUMBER = "0040101" diff --git a/src/onepassword/client.py b/src/onepassword/client.py index f5d191ce..e9f56ebb 100644 --- a/src/onepassword/client.py +++ b/src/onepassword/client.py @@ -8,6 +8,7 @@ from .secrets import Secrets from .items import Items from .vaults import Vaults +from .environments import Environments from .groups import Groups @@ -15,6 +16,7 @@ class Client: secrets: Secrets items: Items vaults: Vaults + environments: Environments groups: Groups @classmethod @@ -41,6 +43,7 @@ async def authenticate( authenticated_client.secrets = Secrets(inner_client) authenticated_client.items = Items(inner_client) authenticated_client.vaults = Vaults(inner_client) + authenticated_client.environments = Environments(inner_client) authenticated_client.groups = Groups(inner_client) authenticated_client._finalizer = weakref.finalize( cls, core.release_client, client_id diff --git a/src/onepassword/environments.py b/src/onepassword/environments.py new file mode 100644 index 00000000..e54c7dfe --- /dev/null +++ b/src/onepassword/environments.py @@ -0,0 +1,33 @@ +# Code generated by op-codegen - DO NO EDIT MANUALLY + +from .core import InnerClient +from pydantic import TypeAdapter +from .types import GetVariablesResponse + + +class Environments: + """ + The Environments API holds all the operations the SDK client can perform on 1Password Environments. + """ + + def __init__(self, inner_client: InnerClient): + self.inner_client = inner_client + + async def get_variables(self, environment_id: str) -> GetVariablesResponse: + """ + Get environment variables belonging to an Environment. + """ + response = await self.inner_client.invoke( + { + "invocation": { + "clientId": self.inner_client.client_id, + "parameters": { + "name": "EnvironmentsGetVariables", + "parameters": {"environment_id": environment_id}, + }, + } + } + ) + + response = TypeAdapter(GetVariablesResponse).validate_json(response) + return response diff --git a/src/onepassword/lib/aarch64/libop_uniffi_core.dylib b/src/onepassword/lib/aarch64/libop_uniffi_core.dylib index 1bd9aeb6..35636374 100755 Binary files a/src/onepassword/lib/aarch64/libop_uniffi_core.dylib and b/src/onepassword/lib/aarch64/libop_uniffi_core.dylib differ diff --git a/src/onepassword/lib/aarch64/libop_uniffi_core.so b/src/onepassword/lib/aarch64/libop_uniffi_core.so index 7a2aa2b3..0c099eb9 100755 Binary files a/src/onepassword/lib/aarch64/libop_uniffi_core.so and b/src/onepassword/lib/aarch64/libop_uniffi_core.so differ diff --git a/src/onepassword/lib/x86_64/libop_uniffi_core.dylib b/src/onepassword/lib/x86_64/libop_uniffi_core.dylib index dcd27d14..d56feb01 100755 Binary files a/src/onepassword/lib/x86_64/libop_uniffi_core.dylib and b/src/onepassword/lib/x86_64/libop_uniffi_core.dylib differ diff --git a/src/onepassword/lib/x86_64/libop_uniffi_core.so b/src/onepassword/lib/x86_64/libop_uniffi_core.so index 69227f60..784d972f 100755 Binary files a/src/onepassword/lib/x86_64/libop_uniffi_core.so and b/src/onepassword/lib/x86_64/libop_uniffi_core.so differ diff --git a/src/onepassword/lib/x86_64/op_uniffi_core.dll b/src/onepassword/lib/x86_64/op_uniffi_core.dll index c6cc4a09..8e7e7d61 100644 Binary files a/src/onepassword/lib/x86_64/op_uniffi_core.dll and b/src/onepassword/lib/x86_64/op_uniffi_core.dll differ diff --git a/src/onepassword/types.py b/src/onepassword/types.py index a3d51210..d74f011e 100644 --- a/src/onepassword/types.py +++ b/src/onepassword/types.py @@ -88,6 +88,25 @@ class DocumentCreateParams(BaseModel): """ +class EnvironmentVariable(BaseModel): + """ + Represents an environment variable (name:value pair) and its masked state + """ + + name: str + """ + An environment variable's name + """ + value: str + """ + An environment variable's value + """ + masked: bool + """ + An environment variable's masked state + """ + + class FileAttributes(BaseModel): name: str """ @@ -140,6 +159,17 @@ class GeneratePasswordResponse(BaseModel): """ +class GetVariablesResponse(BaseModel): + """ + Response containing the full set of environment variables from an Environment. + """ + + variables: List[EnvironmentVariable] + """ + List of environment variables. + """ + + class GroupType(str, Enum): OWNERS = "owners" """ diff --git a/src/release/RELEASE-NOTES b/src/release/RELEASE-NOTES index 76360a19..4ed3b186 100644 --- a/src/release/RELEASE-NOTES +++ b/src/release/RELEASE-NOTES @@ -1,9 +1,6 @@ -# 1Password Python SDK v0.4.0 +# 1Password Python SDK v0.4.1b1 ## NEW -- **Desktop App integration:** The SDK can now authenticate via an authorization prompt from the 1Password app. -- **Vault CRUDL:** You can now fully manage 1Password vaults with the SDK, including creating, reading, updating, deleting and listing. -- **Vault group permission management operations:** You can now grant, update and revoke group access to vaults using `grantGroupPermissions`, `updateGroupPermissions`, and `revokeGroupPermissions` functions. -- **Item batch management:** You can now retrieve, create, update and delete items in batch, enabling more scalable item management. +- **1Password Environment access:** The SDK can now read variables from a 1Password Environment. diff --git a/version.py b/version.py index a529f410..b10330c8 100644 --- a/version.py +++ b/version.py @@ -1 +1 @@ -SDK_VERSION = "0.4.0" +SDK_VERSION = "0.4.1b1"