h2o-secure-store 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- h2o_secure_store-1.0.0/.gitignore +8 -0
- h2o_secure_store-1.0.0/Makefile +23 -0
- h2o_secure_store-1.0.0/PKG-INFO +34 -0
- h2o_secure_store-1.0.0/PUBLIC_README.md +15 -0
- h2o_secure_store-1.0.0/README.md +40 -0
- h2o_secure_store-1.0.0/pyproject.toml +91 -0
- h2o_secure_store-1.0.0/src/.openapi-generator-ignore +4 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/__init__.py +3 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/auth/token_api_client.py +25 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/base/workspace.py +5 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/connection_config.py +110 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/login.py +175 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/oauth_client/client.py +239 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/oauth_client/oauth_client.py +114 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/oauth_client/page.py +21 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/secret/client.py +195 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/secret/page.py +19 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/secret/secret.py +69 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/secret/state.py +16 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/secret_version/client.py +160 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/secret_version/page.py +21 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/secret_version/secret_version.py +54 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/token_source/client.py +172 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/token_source/page.py +21 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/clients/token_source/token_source.py +77 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/exception.py +36 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/__init__.py +27 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/oauth_client_pb2.py +64 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/oauth_client_pb2.pyi +45 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/oauth_client_pb2_grpc.py +4 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/oauth_client_service_pb2.py +79 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/oauth_client_service_pb2.pyi +78 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/oauth_client_service_pb2_grpc.py +262 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_pb2.py +48 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_pb2.pyi +35 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_pb2_grpc.py +4 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_service_pb2.py +82 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_service_pb2.pyi +85 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_service_pb2_grpc.py +257 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_version_pb2.py +40 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_version_pb2.pyi +20 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_version_pb2_grpc.py +4 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_version_service_pb2.py +70 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_version_service_pb2.pyi +71 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/secret_version_service_pb2_grpc.py +214 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/token_source_pb2.py +56 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/token_source_pb2.pyi +36 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/token_source_pb2_grpc.py +4 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/token_source_service_pb2.py +72 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/token_source_service_pb2.pyi +67 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/ai/h2o/securestore/v1/token_source_service_pb2_grpc.py +212 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/api/__init__.py +3 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/api/o_auth_client_service_api.py +748 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/api/secret_service_api.py +780 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/api/secret_version_service_api.py +618 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/api/token_source_service_api.py +623 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/api_client.py +896 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/apis/__init__.py +20 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/configuration.py +446 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/exceptions.py +158 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/__init__.py +5 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/o_auth_client_resource.py +333 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/protobuf_any.py +263 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/rpc_status.py +277 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/secret_state.py +283 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_create_o_auth_client_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_create_secret_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_create_secret_version_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_create_token_source_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_delete_secret_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_get_o_auth_client_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_get_secret_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_get_secret_version_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_get_token_source_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_list_o_auth_clients_response.py +273 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_list_secret_versions_response.py +277 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_list_secrets_response.py +277 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_list_token_sources_response.py +273 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_o_auth_client.py +338 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_reveal_secret_version_value_response.py +272 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_secret.py +299 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_secret_version.py +289 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_token_source.py +318 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_undelete_secret_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model/v1_update_o_auth_client_response.py +269 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/model_utils.py +2056 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/models/__init__.py +35 -0
- h2o_secure_store-1.0.0/src/h2o_secure_store/gen/rest.py +352 -0
- h2o_secure_store-1.0.0/tests/integration/conftest.py +169 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/oauth_client/test_create_oauth_client.py +114 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/oauth_client/test_delete_oauth_client.py +39 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/oauth_client/test_get_oauth_client.py +42 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/oauth_client/test_list_oauth_client.py +70 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/oauth_client/test_update_oauth_client.py +82 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret/test_create_secret.py +93 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret/test_delete_secret.py +55 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret/test_get_secret.py +36 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret/test_list_secret.py +149 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret/test_prune_deleted.py +47 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret/test_undelete_secret.py +52 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret_version/test_create_secret_version.py +44 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret_version/test_get_secret_version.py +113 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret_version/test_key_rotation.py +28 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret_version/test_list_secret_versions.py +136 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/secret_version/test_reveal_secret_version.py +90 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/test_login.py +17 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/token_source/test_create_token_source.py +65 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/token_source/test_delete_token_source.py +54 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/token_source/test_get_token_source.py +64 -0
- h2o_secure_store-1.0.0/tests/integration/e2e/token_source/test_list_token_source.py +90 -0
- h2o_secure_store-1.0.0/usage.py +88 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
build:
|
|
2
|
+
hatch -v build
|
|
3
|
+
|
|
4
|
+
clean-build:
|
|
5
|
+
rm -rf dist
|
|
6
|
+
|
|
7
|
+
test-unit:
|
|
8
|
+
hatch run test:unit -v
|
|
9
|
+
|
|
10
|
+
test-api:
|
|
11
|
+
hatch run test:api -v
|
|
12
|
+
|
|
13
|
+
test-e2e:
|
|
14
|
+
hatch run test:e2e -v
|
|
15
|
+
|
|
16
|
+
lint-check:
|
|
17
|
+
hatch run lint:check -v
|
|
18
|
+
|
|
19
|
+
lint-fix:
|
|
20
|
+
hatch run lint:fix -v
|
|
21
|
+
|
|
22
|
+
generate-docs:
|
|
23
|
+
hatch run docs:generate -v
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: h2o-secure-store
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python client for H2O Secure Store
|
|
5
|
+
Project-URL: Documentation, https://docs.h2o.ai/secure-store/py/initialization
|
|
6
|
+
Author-email: "H2O.ai" <support@h2o.ai>
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Requires-Dist: certifi>=2022.12.7
|
|
9
|
+
Requires-Dist: gcloud>=0.18.3
|
|
10
|
+
Requires-Dist: google-api-python-client>=2.108.0
|
|
11
|
+
Requires-Dist: grpcio>=1.60.0
|
|
12
|
+
Requires-Dist: h2o-authn>=1.1.0
|
|
13
|
+
Requires-Dist: h2o-cloud-discovery>=2.1.0
|
|
14
|
+
Requires-Dist: protobuf>=4.25.1
|
|
15
|
+
Requires-Dist: python-dateutil>=2.8.2
|
|
16
|
+
Requires-Dist: requests>=2.26.0
|
|
17
|
+
Requires-Dist: urllib3>=1.26.15
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# `h2o-secure-store`
|
|
21
|
+
|
|
22
|
+
[](https://pypi.org/project/h2o-secure-store/)
|
|
23
|
+
|
|
24
|
+
Python client for [H2O Secure Store](https://docs.h2o.ai/secure-store/).
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pip install h2o-secure-store
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
Visit the [documentation](https://docs.h2o.ai/secure-store/py/initialization) for more information.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# `h2o-secure-store`
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/h2o-secure-store/)
|
|
4
|
+
|
|
5
|
+
Python client for [H2O Secure Store](https://docs.h2o.ai/secure-store/).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pip install h2o-secure-store
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Visit the [documentation](https://docs.h2o.ai/secure-store/py/initialization) for more information.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# H2O Secure Store
|
|
2
|
+
|
|
3
|
+
H2O Secure Store Python client.
|
|
4
|
+
This Python client implements interaction with the Secure Store REST API server.
|
|
5
|
+
|
|
6
|
+
## Local development
|
|
7
|
+
|
|
8
|
+
This python project is managed by [hatch](https://github.com/pypa/hatch) (environment management, version management,
|
|
9
|
+
dependency management, building, publishing, etc.).
|
|
10
|
+
|
|
11
|
+
You're free to use any tools for local development for managing python environments that you're comfortable with.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Run using hatch
|
|
16
|
+
|
|
17
|
+
You can run H2O Secure Store Python client using Hatch.
|
|
18
|
+
Hatch will automatically create an environment and install all required dependencies:
|
|
19
|
+
|
|
20
|
+
```shell
|
|
21
|
+
hatch run python local/example.py
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
You can also switch to hatch's environment and run commands in it:
|
|
25
|
+
|
|
26
|
+
```shell
|
|
27
|
+
hatch shell
|
|
28
|
+
python local/example.py
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Run in custom env
|
|
32
|
+
|
|
33
|
+
If you want to use your own environment for running the client (global, virtual env, etc.), you can do so.
|
|
34
|
+
For example to build, install and run H2O Secure Store Python client in the current python env:
|
|
35
|
+
|
|
36
|
+
```shell
|
|
37
|
+
hatch build
|
|
38
|
+
pip install dist/h2o_secure_store-*.whl
|
|
39
|
+
python local/example.py
|
|
40
|
+
```
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "h2o-secure-store"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = 'Python client for H2O Secure Store'
|
|
9
|
+
readme = "PUBLIC_README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
keywords = []
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "H2O.ai", email = "support@h2o.ai" },
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"urllib3>=1.26.15",
|
|
17
|
+
"python-dateutil>=2.8.2",
|
|
18
|
+
"h2o-authn>=1.1.0",
|
|
19
|
+
"h2o-cloud-discovery>=2.1.0",
|
|
20
|
+
"requests>=2.26.0",
|
|
21
|
+
"certifi>=2022.12.7",
|
|
22
|
+
# GRPC client dependencies
|
|
23
|
+
"grpcio>=1.60.0",
|
|
24
|
+
"protobuf>=4.25.1",
|
|
25
|
+
"gcloud>=0.18.3",
|
|
26
|
+
"google-api-python-client>=2.108.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Documentation = "https://docs.h2o.ai/secure-store/py/initialization"
|
|
31
|
+
|
|
32
|
+
[tool.hatch.build.targets.wheel]
|
|
33
|
+
packages = ["src/h2o_secure_store"]
|
|
34
|
+
|
|
35
|
+
[tool.hatch.version]
|
|
36
|
+
path = "../../VERSION"
|
|
37
|
+
pattern = "(?P<version>.*)"
|
|
38
|
+
|
|
39
|
+
[tool.hatch.envs.lint]
|
|
40
|
+
detached = true
|
|
41
|
+
dependencies = [
|
|
42
|
+
"black==23.1.0",
|
|
43
|
+
"isort==5.12.0",
|
|
44
|
+
"autoflake==2.3.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[tool.hatch.envs.lint.scripts]
|
|
48
|
+
# TODO use flake8 and mypy
|
|
49
|
+
check = [
|
|
50
|
+
"black --check --diff .",
|
|
51
|
+
"isort --check --diff .",
|
|
52
|
+
"autoflake --check-diff ."
|
|
53
|
+
]
|
|
54
|
+
fix = [
|
|
55
|
+
"black .",
|
|
56
|
+
"isort .",
|
|
57
|
+
"autoflake ."
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.black]
|
|
61
|
+
exclude = [
|
|
62
|
+
"src/h2o_secure_store/gen",
|
|
63
|
+
"local",
|
|
64
|
+
]
|
|
65
|
+
skip-magic-trailing-comma = true
|
|
66
|
+
|
|
67
|
+
[tool.isort]
|
|
68
|
+
skip = [
|
|
69
|
+
"src/h2o_secure_store/gen",
|
|
70
|
+
"local"
|
|
71
|
+
]
|
|
72
|
+
force_single_line = true
|
|
73
|
+
known_application = ["h2o_secure_store"]
|
|
74
|
+
profile = "black"
|
|
75
|
+
|
|
76
|
+
[tool.autoflake]
|
|
77
|
+
exclude = [
|
|
78
|
+
"*/gen/*",
|
|
79
|
+
"local",
|
|
80
|
+
]
|
|
81
|
+
remove_all_unused_imports = true
|
|
82
|
+
recursive = true
|
|
83
|
+
|
|
84
|
+
[tool.hatch.envs.test]
|
|
85
|
+
dependencies = [
|
|
86
|
+
"pytest==8.2.1",
|
|
87
|
+
"psycopg2-binary==2.9.9",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[tool.hatch.envs.test.scripts]
|
|
91
|
+
e2e = "python -m pytest tests/integration/e2e"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
|
|
3
|
+
from h2o_secure_store.gen.api_client import ApiClient
|
|
4
|
+
from h2o_secure_store.gen.api_client import Configuration
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TokenApiClient(ApiClient):
|
|
8
|
+
"""Overrides update_params_for_auth method of the generated ApiClient classes"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, configuration: Configuration, token_provider: Callable[[], str]):
|
|
11
|
+
self._token_provider = token_provider
|
|
12
|
+
super().__init__(configuration=configuration)
|
|
13
|
+
|
|
14
|
+
def update_params_for_auth(
|
|
15
|
+
self,
|
|
16
|
+
headers,
|
|
17
|
+
queries,
|
|
18
|
+
auth_settings,
|
|
19
|
+
resource_path,
|
|
20
|
+
method,
|
|
21
|
+
body,
|
|
22
|
+
request_auths=None,
|
|
23
|
+
):
|
|
24
|
+
token = self._token_provider()
|
|
25
|
+
headers["Authorization"] = f"Bearer {token}"
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import ssl
|
|
2
|
+
from typing import Callable
|
|
3
|
+
from typing import NamedTuple
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
import h2o_authn
|
|
8
|
+
import h2o_discovery
|
|
9
|
+
from h2o_authn import TokenProvider
|
|
10
|
+
|
|
11
|
+
# Name of the platform client in the discovery response.
|
|
12
|
+
PLATFORM_CLIENT_NAME = "platform"
|
|
13
|
+
# Name of the Secure Store API service in the discovery response.
|
|
14
|
+
SECURE_STORE_SERVICE_NAME = "secure-store"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ConnectionConfig(NamedTuple):
|
|
18
|
+
"""Object holding connection configuration for the Secure Store API server."""
|
|
19
|
+
|
|
20
|
+
server_url: str
|
|
21
|
+
token_provider: Union[TokenProvider, Callable[[], str]]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_connection(
|
|
25
|
+
server_url: str,
|
|
26
|
+
refresh_token: str,
|
|
27
|
+
issuer_url: str,
|
|
28
|
+
client_id: str,
|
|
29
|
+
client_secret: Optional[str] = None,
|
|
30
|
+
) -> ConnectionConfig:
|
|
31
|
+
"""Creates ConnectionConfig object. Initializes and tests token provider."""
|
|
32
|
+
|
|
33
|
+
# init token provider
|
|
34
|
+
tp = h2o_authn.TokenProvider(
|
|
35
|
+
issuer_url=issuer_url,
|
|
36
|
+
refresh_token=refresh_token,
|
|
37
|
+
client_id=client_id,
|
|
38
|
+
client_secret=client_secret,
|
|
39
|
+
)
|
|
40
|
+
# test token refresh
|
|
41
|
+
tp()
|
|
42
|
+
|
|
43
|
+
return ConnectionConfig(server_url=server_url, token_provider=tp)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def discover_platform_connection(
|
|
47
|
+
environment_url: Optional[str] = None,
|
|
48
|
+
config_path: Optional[str] = None,
|
|
49
|
+
platform_token: Optional[str] = None,
|
|
50
|
+
token_provider: Optional[TokenProvider] = None,
|
|
51
|
+
ssl_context: Optional[ssl.SSLContext] = None,
|
|
52
|
+
) -> ConnectionConfig:
|
|
53
|
+
"""Creates ConnectionConfig object by discovering platform connection configuration using h2o_discovery.
|
|
54
|
+
|
|
55
|
+
:param environment_url: Override for the URL of the environment passed to the discovery service.
|
|
56
|
+
:param config_path: Override path to the h2o cli config file passed to the discovery service.
|
|
57
|
+
:param platform_token: Platform token. If not provided, the token will be discovered.
|
|
58
|
+
:param token_provider: Token provider. If not provided, the provider will be constructed from the discovered config.
|
|
59
|
+
:param ssl_context: SSL context to use for the discovery client.
|
|
60
|
+
"""
|
|
61
|
+
# Discover the Secure Store server URL
|
|
62
|
+
d = h2o_discovery.discover(environment=environment_url, config_path=config_path, ssl_context=ssl_context)
|
|
63
|
+
|
|
64
|
+
secure_store_service = d.services.get(SECURE_STORE_SERVICE_NAME)
|
|
65
|
+
if secure_store_service is None:
|
|
66
|
+
raise Exception("Secure Store API service is not registered in discovery service")
|
|
67
|
+
|
|
68
|
+
secure_store_url = secure_store_service.uri
|
|
69
|
+
if not secure_store_url:
|
|
70
|
+
raise ConnectionError("Unable to discover Secure Store server URL connection value.")
|
|
71
|
+
|
|
72
|
+
# If the token provider is provided, use it to construct the connection config.
|
|
73
|
+
if token_provider is not None:
|
|
74
|
+
# Test token refresh
|
|
75
|
+
token_provider()
|
|
76
|
+
return ConnectionConfig(server_url=secure_store_url, token_provider=token_provider)
|
|
77
|
+
|
|
78
|
+
# If the token provider is not provided, construct it from the discovered config.
|
|
79
|
+
if not platform_token:
|
|
80
|
+
platform_client_credentials = d.credentials[PLATFORM_CLIENT_NAME]
|
|
81
|
+
if platform_client_credentials is None:
|
|
82
|
+
raise Exception("Platform client credentials are not available in discovery service")
|
|
83
|
+
|
|
84
|
+
platform_token = platform_client_credentials.refresh_token
|
|
85
|
+
|
|
86
|
+
if not platform_token:
|
|
87
|
+
raise ValueError(
|
|
88
|
+
"Please set the 'platform_token' argument or configure the H2O CLI."
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Discover client id
|
|
92
|
+
platform_client = d.clients.get(PLATFORM_CLIENT_NAME)
|
|
93
|
+
if platform_client is None:
|
|
94
|
+
raise Exception("platform client is not registered in discovery service")
|
|
95
|
+
|
|
96
|
+
client_id = platform_client.oauth2_client_id
|
|
97
|
+
if not client_id:
|
|
98
|
+
raise ConnectionError(
|
|
99
|
+
"Unable to discover platform oauth2_client_id connection value."
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
tp = h2o_authn.TokenProvider(
|
|
103
|
+
issuer_url=d.environment.issuer_url,
|
|
104
|
+
client_id=client_id,
|
|
105
|
+
refresh_token=platform_token,
|
|
106
|
+
)
|
|
107
|
+
# Test token refresh
|
|
108
|
+
tp()
|
|
109
|
+
|
|
110
|
+
return ConnectionConfig(server_url=secure_store_url, token_provider=tp)
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import ssl
|
|
2
|
+
from typing import Callable
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from urllib.parse import urljoin
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
from h2o_authn import TokenProvider
|
|
8
|
+
|
|
9
|
+
from h2o_secure_store.clients.connection_config import ConnectionConfig
|
|
10
|
+
from h2o_secure_store.clients.connection_config import discover_platform_connection
|
|
11
|
+
from h2o_secure_store.clients.connection_config import get_connection
|
|
12
|
+
from h2o_secure_store.clients.oauth_client.client import OAuthClientClient
|
|
13
|
+
from h2o_secure_store.clients.secret.client import SecretClient
|
|
14
|
+
from h2o_secure_store.clients.secret_version.client import SecretVersionClient
|
|
15
|
+
from h2o_secure_store.clients.token_source.client import TokenSourceClient
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Clients:
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
oauth_client_client: OAuthClientClient,
|
|
22
|
+
token_source_client: TokenSourceClient,
|
|
23
|
+
secret_client: SecretClient,
|
|
24
|
+
secret_version_client: SecretVersionClient,
|
|
25
|
+
) -> None:
|
|
26
|
+
self.oauth_client_client = oauth_client_client
|
|
27
|
+
self.token_source_client = token_source_client
|
|
28
|
+
self.secret_client = secret_client
|
|
29
|
+
self.secret_version_client = secret_version_client
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def login(
|
|
33
|
+
environment: Optional[str] = None,
|
|
34
|
+
token_provider: Optional[TokenProvider] = None,
|
|
35
|
+
platform_token: Optional[str] = None,
|
|
36
|
+
config_path: Optional[str] = None,
|
|
37
|
+
verify_ssl: bool = True,
|
|
38
|
+
ssl_ca_cert: Optional[str] = None,
|
|
39
|
+
) -> Clients:
|
|
40
|
+
"""Initializes Secure Store clients for H2O AI Cloud.
|
|
41
|
+
|
|
42
|
+
All arguments are optional. Configuration-less login is dependent on having the H2O CLI configured.
|
|
43
|
+
See: https://docs.h2o.ai/h2o-ai-cloud/developerguide/cli#platform-token
|
|
44
|
+
The Discovery Service is used to discover the Secure Store server endpoint.
|
|
45
|
+
See: https://pypi.org/project/h2o-cloud-discovery/
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
environment (str, optional): The H2O Cloud environment URL to use (e.g. https://cloud.h2o.ai).
|
|
49
|
+
If left empty, the environment will be read from the H2O CLI configuration or environmental variables.
|
|
50
|
+
Then, h2o-cloud-discovery will be used to discover the Secure Store API server endpoint.
|
|
51
|
+
token_provider (TokenProvider, optional) = Token provider. Takes priority over platform_token argument.
|
|
52
|
+
platform_token (str, optional): H2O Platform Token.
|
|
53
|
+
If neither 'token_provider' nor 'platform_token' is provided the platform token will be read
|
|
54
|
+
from the H2O CLI configuration.
|
|
55
|
+
config_path: (str, optional): Path to the H2O AI Cloud configuration file.
|
|
56
|
+
Defaults to '~/.h2oai/h2o-cli-config.toml'.
|
|
57
|
+
verify_ssl: Set to False to disable SSL certificate verification.
|
|
58
|
+
ssl_ca_cert: Path to a CA cert bundle with certificates of trusted CAs.
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
FileNotFoundError: When the H2O CLI configuration file is needed but cannot be found.
|
|
62
|
+
TomlDecodeError: When the H2O CLI configuration file is needed but cannot be processed.
|
|
63
|
+
LookupError: When the service endpoint cannot be discovered.
|
|
64
|
+
ConnectionError: When a communication with server failed.
|
|
65
|
+
"""
|
|
66
|
+
ssl_context = ssl.create_default_context(cafile=ssl_ca_cert) # Will use system store if None
|
|
67
|
+
if not verify_ssl:
|
|
68
|
+
ssl_context.check_hostname = False
|
|
69
|
+
ssl_context.verify_mode = ssl.CERT_NONE
|
|
70
|
+
|
|
71
|
+
cfg = discover_platform_connection(
|
|
72
|
+
environment_url=environment,
|
|
73
|
+
platform_token=platform_token,
|
|
74
|
+
token_provider=token_provider,
|
|
75
|
+
config_path=config_path,
|
|
76
|
+
ssl_context=ssl_context,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return __init_clients(
|
|
80
|
+
cfg=cfg, verify_ssl=verify_ssl, ssl_ca_cert=ssl_ca_cert,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def login_custom(
|
|
85
|
+
endpoint: str,
|
|
86
|
+
refresh_token: str,
|
|
87
|
+
issuer_url: str,
|
|
88
|
+
client_id: str,
|
|
89
|
+
client_secret: Optional[str] = None,
|
|
90
|
+
verify_ssl: bool = True,
|
|
91
|
+
ssl_ca_cert: Optional[str] = None,
|
|
92
|
+
) -> Clients:
|
|
93
|
+
"""Initializes Secure store clients using h2o_authn to construct a token provider.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
endpoint (str): The Secure Store API server endpoint URL (e.g. https://secure-store.cloud.h2o.ai).
|
|
97
|
+
refresh_token (str): The OIDC refresh token.
|
|
98
|
+
issuer_url (str): The OIDC issuer URL.
|
|
99
|
+
client_id (str): The OIDC Client ID that issued the 'refresh_token'.
|
|
100
|
+
client_secret (str, optional): Optional OIDC Client Secret that issued the 'refresh_token'. Defaults to None.
|
|
101
|
+
verify_ssl: Set to False to disable SSL certificate verification.
|
|
102
|
+
ssl_ca_cert: Path to a CA cert bundle with certificates of trusted CAs.
|
|
103
|
+
"""
|
|
104
|
+
# Remove trailing slash from the URL for the generated clients
|
|
105
|
+
endpoint = endpoint.rstrip("/")
|
|
106
|
+
cfg = get_connection(
|
|
107
|
+
server_url=endpoint,
|
|
108
|
+
refresh_token=refresh_token,
|
|
109
|
+
issuer_url=issuer_url,
|
|
110
|
+
client_id=client_id,
|
|
111
|
+
client_secret=client_secret,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
return __init_clients(
|
|
115
|
+
cfg=cfg, verify_ssl=verify_ssl, ssl_ca_cert=ssl_ca_cert,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def login_custom_with_token_provider(
|
|
120
|
+
endpoint: str,
|
|
121
|
+
token_provider: Callable[[], str],
|
|
122
|
+
verify_ssl: bool = True,
|
|
123
|
+
ssl_ca_cert: Optional[str] = None,
|
|
124
|
+
) -> Clients:
|
|
125
|
+
"""Initializes Secure store clients using a custom token provider.
|
|
126
|
+
|
|
127
|
+
A token provider can be constructed using h2o_authn:
|
|
128
|
+
token_provider = h2o_authn.TokenProvider(
|
|
129
|
+
issuer_url=issuer_url,
|
|
130
|
+
refresh_token=refresh_token,
|
|
131
|
+
client_id=client_id,
|
|
132
|
+
client_secret=client_secret,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
endpoint (str): The Secure Store API server endpoint URL (e.g. https://secure-store.cloud.h2o.ai).
|
|
137
|
+
token_provider (Callable[[], str]): A callable that returns an OIDC access token.
|
|
138
|
+
verify_ssl: Set to False to disable SSL certificate verification.
|
|
139
|
+
ssl_ca_cert: Path to a CA cert bundle with certificates of trusted CAs.
|
|
140
|
+
"""
|
|
141
|
+
# Remove trailing slash from the URL for the generated clients
|
|
142
|
+
endpoint = endpoint.rstrip("/")
|
|
143
|
+
# Test token refresh
|
|
144
|
+
token_provider()
|
|
145
|
+
cfg = ConnectionConfig(server_url=endpoint, token_provider=token_provider)
|
|
146
|
+
|
|
147
|
+
return __init_clients(
|
|
148
|
+
cfg=cfg, verify_ssl=verify_ssl, ssl_ca_cert=ssl_ca_cert,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def __init_clients(
|
|
153
|
+
cfg: ConnectionConfig,
|
|
154
|
+
verify_ssl: bool,
|
|
155
|
+
ssl_ca_cert: Optional[str],
|
|
156
|
+
):
|
|
157
|
+
# Verify that the server is reachable
|
|
158
|
+
version_url = urljoin(cfg.server_url, "version")
|
|
159
|
+
resp = requests.get(version_url)
|
|
160
|
+
if not (200 <= resp.status_code <= 299):
|
|
161
|
+
raise ConnectionError(
|
|
162
|
+
f"Server is not reachable. Status code: {resp.status_code}, Response body: {resp.text}"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
oauth_client_client = OAuthClientClient(connection_config=cfg, verify_ssl=verify_ssl, ssl_ca_cert=ssl_ca_cert)
|
|
166
|
+
token_source_client = TokenSourceClient(connection_config=cfg, verify_ssl=verify_ssl, ssl_ca_cert=ssl_ca_cert)
|
|
167
|
+
secret_client = SecretClient(connection_config=cfg, verify_ssl=verify_ssl, ssl_ca_cert=ssl_ca_cert)
|
|
168
|
+
secret_version_client = SecretVersionClient(connection_config=cfg, verify_ssl=verify_ssl, ssl_ca_cert=ssl_ca_cert)
|
|
169
|
+
|
|
170
|
+
return Clients(
|
|
171
|
+
oauth_client_client=oauth_client_client,
|
|
172
|
+
token_source_client=token_source_client,
|
|
173
|
+
secret_client=secret_client,
|
|
174
|
+
secret_version_client=secret_version_client,
|
|
175
|
+
)
|