beyondtrust-bips-library 1.0.2__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.
- beyondtrust_bips_library-1.0.2/LICENSE +21 -0
- beyondtrust_bips_library-1.0.2/PKG-INFO +169 -0
- beyondtrust_bips_library-1.0.2/README.md +129 -0
- beyondtrust_bips_library-1.0.2/pyproject.toml +30 -0
- beyondtrust_bips_library-1.0.2/setup.cfg +4 -0
- beyondtrust_bips_library-1.0.2/src/beyondtrust_bips_library.egg-info/PKG-INFO +169 -0
- beyondtrust_bips_library-1.0.2/src/beyondtrust_bips_library.egg-info/SOURCES.txt +18 -0
- beyondtrust_bips_library-1.0.2/src/beyondtrust_bips_library.egg-info/dependency_links.txt +1 -0
- beyondtrust_bips_library-1.0.2/src/beyondtrust_bips_library.egg-info/requires.txt +4 -0
- beyondtrust_bips_library-1.0.2/src/beyondtrust_bips_library.egg-info/top_level.txt +3 -0
- beyondtrust_bips_library-1.0.2/src/managed_account_client.py +87 -0
- beyondtrust_bips_library-1.0.2/src/secret_client.py +94 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/__init__.py +2 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/authentication.py +215 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/cert_util.py +81 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/exceptions.py +36 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/managed_account.py +232 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/secrets.py +26 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/secrets_safe.py +221 -0
- beyondtrust_bips_library-1.0.2/src/secrets_safe_library/utils.py +102 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 BeyondTrust Corporation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: beyondtrust-bips-library
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: Password Safe API integration written in Python, Abstract complexity of managing secrets with the API.
|
|
5
|
+
Author: BeyondTrust Corporation
|
|
6
|
+
Author-email: support@beyondtrust.com
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2023 BeyondTrust Corporation
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Project-URL: support, https://www.beyondtrust.com/docs/index.htm#support
|
|
30
|
+
Keywords: beyondtrust,devops,secrets,secretssafe,security
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Requires-Python: >=3.11
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
License-File: LICENSE
|
|
36
|
+
Requires-Dist: requests==2.32.3
|
|
37
|
+
Requires-Dist: retry-requests==2.0.0
|
|
38
|
+
Requires-Dist: cryptography==43.0.1
|
|
39
|
+
Requires-Dist: Cerberus==1.3.5
|
|
40
|
+
|
|
41
|
+
# Password Safe API integration
|
|
42
|
+
[](LICENSE)
|
|
43
|
+
|
|
44
|
+
Password Safe API integration written in Python, Abstract complexity of managing secrets with the API
|
|
45
|
+
|
|
46
|
+
## Python version compatibility
|
|
47
|
+
|
|
48
|
+
This library is compatible with Python >= v3.11.
|
|
49
|
+
|
|
50
|
+
## Install Package
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
# PyPI
|
|
54
|
+
pip install secrets-safe-library
|
|
55
|
+
```
|
|
56
|
+
## Arguments
|
|
57
|
+
|
|
58
|
+
### Retrieve Secrets
|
|
59
|
+
- api_url:
|
|
60
|
+
- description: BeyondTrust Password Safe API URL.
|
|
61
|
+
- type: string
|
|
62
|
+
- required: True
|
|
63
|
+
- client_id:
|
|
64
|
+
- description: API OAuth Client ID.
|
|
65
|
+
- type: string
|
|
66
|
+
- required: True
|
|
67
|
+
- client_secret:
|
|
68
|
+
- description: API OAuth Client Secret.
|
|
69
|
+
- type: string
|
|
70
|
+
- required: True
|
|
71
|
+
- secret_list:
|
|
72
|
+
- description: List of secrets ["path/title","path/title"] or managed accounts ["ms/ma","ms/ma"] to be retrieved, separated by a comma.
|
|
73
|
+
- type: list
|
|
74
|
+
- required: True
|
|
75
|
+
- certificate_path:
|
|
76
|
+
- description: Password Safe API pfx Certificate Path. For use when authenticating using a Client Certificate.
|
|
77
|
+
- type: string
|
|
78
|
+
- required: False
|
|
79
|
+
- certificate_password:
|
|
80
|
+
- description: Password Safe API pfx Certificate Password. For use when authenticating using a Client Certificate.
|
|
81
|
+
- type: string
|
|
82
|
+
- required: False
|
|
83
|
+
- verify_ca:
|
|
84
|
+
- description: Indicates whether to verify the certificate authority on the Secrets Safe instance.
|
|
85
|
+
- type: boolean
|
|
86
|
+
- default: True
|
|
87
|
+
- required: False
|
|
88
|
+
|
|
89
|
+
## Methods
|
|
90
|
+
- get_secrets(self, paths)
|
|
91
|
+
- Invoked for Managed Account or Secrets Safe secrets.
|
|
92
|
+
- Returns a list of secrets in the requested order.
|
|
93
|
+
- get_secret(self, path)
|
|
94
|
+
- Invoked for Managed Account or Secrets Safe secrets.
|
|
95
|
+
- Returns the requested secret.
|
|
96
|
+
|
|
97
|
+
## Example of usage
|
|
98
|
+
|
|
99
|
+
We strongly recommend you to use a virtual environment and install dependences from requirements.txt file.
|
|
100
|
+
|
|
101
|
+
Import `secrets_safe_library`
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
pip install -r ~/requirements.txt
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
script example using library:
|
|
108
|
+
```python
|
|
109
|
+
import os
|
|
110
|
+
import logging
|
|
111
|
+
from secrets_safe_library import secrets_safe, authentication, utils, managed_account
|
|
112
|
+
import requests
|
|
113
|
+
from retry_requests import retry
|
|
114
|
+
|
|
115
|
+
env = os.environ
|
|
116
|
+
LOGGER_NAME = "custom_logger"
|
|
117
|
+
|
|
118
|
+
logging.basicConfig(format = '%(asctime)-5s %(name)-15s %(levelname)-8s %(message)s',
|
|
119
|
+
|
|
120
|
+
level = logging.DEBUG)
|
|
121
|
+
|
|
122
|
+
# logger object is optional but is strongly recommended
|
|
123
|
+
logger = logging.getLogger(LOGGER_NAME)
|
|
124
|
+
|
|
125
|
+
TIMEOUT_CONNECTION_SECONDS = 30
|
|
126
|
+
TIMEOUT_REQUEST_SECONDS = 30
|
|
127
|
+
|
|
128
|
+
CERTIFICATE = env['CERTIFICATE']
|
|
129
|
+
CERTIFICATE_KEY = env['CERTIFICATE_KEY']
|
|
130
|
+
|
|
131
|
+
def main():
|
|
132
|
+
try:
|
|
133
|
+
with requests.Session() as session:
|
|
134
|
+
req = retry(session, retries=3, backoff_factor=0.2, status_to_retry=(400,408,500,502,503,504))
|
|
135
|
+
|
|
136
|
+
certificate, certificate_key = utils.prepare_certificate_info(CERTIFICATE, CERTIFICATE_KEY)
|
|
137
|
+
|
|
138
|
+
authentication_obj = authentication.Authentication(
|
|
139
|
+
req,
|
|
140
|
+
TIMEOUT_CONNECTION_SECONDS,
|
|
141
|
+
TIMEOUT_REQUEST_SECONDS,
|
|
142
|
+
"https://example.com:443/BeyondTrust/api/public/v3",
|
|
143
|
+
"<client_id>",
|
|
144
|
+
"<client_secret>",
|
|
145
|
+
certificate,
|
|
146
|
+
certificate_key,
|
|
147
|
+
True,
|
|
148
|
+
None)
|
|
149
|
+
|
|
150
|
+
# sign app in password safe API
|
|
151
|
+
get_api_access_response = authentication_obj.get_api_access()
|
|
152
|
+
|
|
153
|
+
if get_api_access_response.status_code == 200:
|
|
154
|
+
# instantiate secrets safe object
|
|
155
|
+
secrets_safe_obj = secrets_safe.SecretsSafe(authentication_obj, logger)
|
|
156
|
+
|
|
157
|
+
get_secrets_response = secrets_safe_obj.get_secrets(["oagrp/text,oagrp/credential"])
|
|
158
|
+
utils.print_log(logger, f"=> Retrive secrets: {get_secrets_response}", logging.DEBUG)
|
|
159
|
+
else:
|
|
160
|
+
print(f"Please check credentials, error {get_api_access_response.text}")
|
|
161
|
+
|
|
162
|
+
authentication_obj.sign_app_out()
|
|
163
|
+
|
|
164
|
+
except Exception as e:
|
|
165
|
+
utils.print_log(logger, f"Error: {e}", logging.ERROR)
|
|
166
|
+
|
|
167
|
+
# calling main method
|
|
168
|
+
main()
|
|
169
|
+
```
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Password Safe API integration
|
|
2
|
+
[](LICENSE)
|
|
3
|
+
|
|
4
|
+
Password Safe API integration written in Python, Abstract complexity of managing secrets with the API
|
|
5
|
+
|
|
6
|
+
## Python version compatibility
|
|
7
|
+
|
|
8
|
+
This library is compatible with Python >= v3.11.
|
|
9
|
+
|
|
10
|
+
## Install Package
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
# PyPI
|
|
14
|
+
pip install secrets-safe-library
|
|
15
|
+
```
|
|
16
|
+
## Arguments
|
|
17
|
+
|
|
18
|
+
### Retrieve Secrets
|
|
19
|
+
- api_url:
|
|
20
|
+
- description: BeyondTrust Password Safe API URL.
|
|
21
|
+
- type: string
|
|
22
|
+
- required: True
|
|
23
|
+
- client_id:
|
|
24
|
+
- description: API OAuth Client ID.
|
|
25
|
+
- type: string
|
|
26
|
+
- required: True
|
|
27
|
+
- client_secret:
|
|
28
|
+
- description: API OAuth Client Secret.
|
|
29
|
+
- type: string
|
|
30
|
+
- required: True
|
|
31
|
+
- secret_list:
|
|
32
|
+
- description: List of secrets ["path/title","path/title"] or managed accounts ["ms/ma","ms/ma"] to be retrieved, separated by a comma.
|
|
33
|
+
- type: list
|
|
34
|
+
- required: True
|
|
35
|
+
- certificate_path:
|
|
36
|
+
- description: Password Safe API pfx Certificate Path. For use when authenticating using a Client Certificate.
|
|
37
|
+
- type: string
|
|
38
|
+
- required: False
|
|
39
|
+
- certificate_password:
|
|
40
|
+
- description: Password Safe API pfx Certificate Password. For use when authenticating using a Client Certificate.
|
|
41
|
+
- type: string
|
|
42
|
+
- required: False
|
|
43
|
+
- verify_ca:
|
|
44
|
+
- description: Indicates whether to verify the certificate authority on the Secrets Safe instance.
|
|
45
|
+
- type: boolean
|
|
46
|
+
- default: True
|
|
47
|
+
- required: False
|
|
48
|
+
|
|
49
|
+
## Methods
|
|
50
|
+
- get_secrets(self, paths)
|
|
51
|
+
- Invoked for Managed Account or Secrets Safe secrets.
|
|
52
|
+
- Returns a list of secrets in the requested order.
|
|
53
|
+
- get_secret(self, path)
|
|
54
|
+
- Invoked for Managed Account or Secrets Safe secrets.
|
|
55
|
+
- Returns the requested secret.
|
|
56
|
+
|
|
57
|
+
## Example of usage
|
|
58
|
+
|
|
59
|
+
We strongly recommend you to use a virtual environment and install dependences from requirements.txt file.
|
|
60
|
+
|
|
61
|
+
Import `secrets_safe_library`
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
pip install -r ~/requirements.txt
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
script example using library:
|
|
68
|
+
```python
|
|
69
|
+
import os
|
|
70
|
+
import logging
|
|
71
|
+
from secrets_safe_library import secrets_safe, authentication, utils, managed_account
|
|
72
|
+
import requests
|
|
73
|
+
from retry_requests import retry
|
|
74
|
+
|
|
75
|
+
env = os.environ
|
|
76
|
+
LOGGER_NAME = "custom_logger"
|
|
77
|
+
|
|
78
|
+
logging.basicConfig(format = '%(asctime)-5s %(name)-15s %(levelname)-8s %(message)s',
|
|
79
|
+
|
|
80
|
+
level = logging.DEBUG)
|
|
81
|
+
|
|
82
|
+
# logger object is optional but is strongly recommended
|
|
83
|
+
logger = logging.getLogger(LOGGER_NAME)
|
|
84
|
+
|
|
85
|
+
TIMEOUT_CONNECTION_SECONDS = 30
|
|
86
|
+
TIMEOUT_REQUEST_SECONDS = 30
|
|
87
|
+
|
|
88
|
+
CERTIFICATE = env['CERTIFICATE']
|
|
89
|
+
CERTIFICATE_KEY = env['CERTIFICATE_KEY']
|
|
90
|
+
|
|
91
|
+
def main():
|
|
92
|
+
try:
|
|
93
|
+
with requests.Session() as session:
|
|
94
|
+
req = retry(session, retries=3, backoff_factor=0.2, status_to_retry=(400,408,500,502,503,504))
|
|
95
|
+
|
|
96
|
+
certificate, certificate_key = utils.prepare_certificate_info(CERTIFICATE, CERTIFICATE_KEY)
|
|
97
|
+
|
|
98
|
+
authentication_obj = authentication.Authentication(
|
|
99
|
+
req,
|
|
100
|
+
TIMEOUT_CONNECTION_SECONDS,
|
|
101
|
+
TIMEOUT_REQUEST_SECONDS,
|
|
102
|
+
"https://example.com:443/BeyondTrust/api/public/v3",
|
|
103
|
+
"<client_id>",
|
|
104
|
+
"<client_secret>",
|
|
105
|
+
certificate,
|
|
106
|
+
certificate_key,
|
|
107
|
+
True,
|
|
108
|
+
None)
|
|
109
|
+
|
|
110
|
+
# sign app in password safe API
|
|
111
|
+
get_api_access_response = authentication_obj.get_api_access()
|
|
112
|
+
|
|
113
|
+
if get_api_access_response.status_code == 200:
|
|
114
|
+
# instantiate secrets safe object
|
|
115
|
+
secrets_safe_obj = secrets_safe.SecretsSafe(authentication_obj, logger)
|
|
116
|
+
|
|
117
|
+
get_secrets_response = secrets_safe_obj.get_secrets(["oagrp/text,oagrp/credential"])
|
|
118
|
+
utils.print_log(logger, f"=> Retrive secrets: {get_secrets_response}", logging.DEBUG)
|
|
119
|
+
else:
|
|
120
|
+
print(f"Please check credentials, error {get_api_access_response.text}")
|
|
121
|
+
|
|
122
|
+
authentication_obj.sign_app_out()
|
|
123
|
+
|
|
124
|
+
except Exception as e:
|
|
125
|
+
utils.print_log(logger, f"Error: {e}", logging.ERROR)
|
|
126
|
+
|
|
127
|
+
# calling main method
|
|
128
|
+
main()
|
|
129
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=42",
|
|
4
|
+
"wheel"
|
|
5
|
+
]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
7
|
+
[project]
|
|
8
|
+
name = "beyondtrust-bips-library"
|
|
9
|
+
version = "1.0.2"
|
|
10
|
+
authors = [
|
|
11
|
+
{email = "support@beyondtrust.com"},
|
|
12
|
+
{name = "BeyondTrust Corporation"}
|
|
13
|
+
]
|
|
14
|
+
license = {file = "LICENSE"}
|
|
15
|
+
requires-python = ">= 3.11"
|
|
16
|
+
description = "Password Safe API integration written in Python, Abstract complexity of managing secrets with the API."
|
|
17
|
+
readme = "README.md"
|
|
18
|
+
keywords = ["beyondtrust", "devops", "secrets", "secretssafe", "security"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"License :: OSI Approved :: MIT License"
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"requests==2.32.3",
|
|
25
|
+
"retry-requests==2.0.0",
|
|
26
|
+
"cryptography==43.0.1",
|
|
27
|
+
"Cerberus==1.3.5"
|
|
28
|
+
]
|
|
29
|
+
[project.urls]
|
|
30
|
+
support = "https://www.beyondtrust.com/docs/index.htm#support"
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: beyondtrust-bips-library
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: Password Safe API integration written in Python, Abstract complexity of managing secrets with the API.
|
|
5
|
+
Author: BeyondTrust Corporation
|
|
6
|
+
Author-email: support@beyondtrust.com
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2023 BeyondTrust Corporation
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Project-URL: support, https://www.beyondtrust.com/docs/index.htm#support
|
|
30
|
+
Keywords: beyondtrust,devops,secrets,secretssafe,security
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Requires-Python: >=3.11
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
License-File: LICENSE
|
|
36
|
+
Requires-Dist: requests==2.32.3
|
|
37
|
+
Requires-Dist: retry-requests==2.0.0
|
|
38
|
+
Requires-Dist: cryptography==43.0.1
|
|
39
|
+
Requires-Dist: Cerberus==1.3.5
|
|
40
|
+
|
|
41
|
+
# Password Safe API integration
|
|
42
|
+
[](LICENSE)
|
|
43
|
+
|
|
44
|
+
Password Safe API integration written in Python, Abstract complexity of managing secrets with the API
|
|
45
|
+
|
|
46
|
+
## Python version compatibility
|
|
47
|
+
|
|
48
|
+
This library is compatible with Python >= v3.11.
|
|
49
|
+
|
|
50
|
+
## Install Package
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
# PyPI
|
|
54
|
+
pip install secrets-safe-library
|
|
55
|
+
```
|
|
56
|
+
## Arguments
|
|
57
|
+
|
|
58
|
+
### Retrieve Secrets
|
|
59
|
+
- api_url:
|
|
60
|
+
- description: BeyondTrust Password Safe API URL.
|
|
61
|
+
- type: string
|
|
62
|
+
- required: True
|
|
63
|
+
- client_id:
|
|
64
|
+
- description: API OAuth Client ID.
|
|
65
|
+
- type: string
|
|
66
|
+
- required: True
|
|
67
|
+
- client_secret:
|
|
68
|
+
- description: API OAuth Client Secret.
|
|
69
|
+
- type: string
|
|
70
|
+
- required: True
|
|
71
|
+
- secret_list:
|
|
72
|
+
- description: List of secrets ["path/title","path/title"] or managed accounts ["ms/ma","ms/ma"] to be retrieved, separated by a comma.
|
|
73
|
+
- type: list
|
|
74
|
+
- required: True
|
|
75
|
+
- certificate_path:
|
|
76
|
+
- description: Password Safe API pfx Certificate Path. For use when authenticating using a Client Certificate.
|
|
77
|
+
- type: string
|
|
78
|
+
- required: False
|
|
79
|
+
- certificate_password:
|
|
80
|
+
- description: Password Safe API pfx Certificate Password. For use when authenticating using a Client Certificate.
|
|
81
|
+
- type: string
|
|
82
|
+
- required: False
|
|
83
|
+
- verify_ca:
|
|
84
|
+
- description: Indicates whether to verify the certificate authority on the Secrets Safe instance.
|
|
85
|
+
- type: boolean
|
|
86
|
+
- default: True
|
|
87
|
+
- required: False
|
|
88
|
+
|
|
89
|
+
## Methods
|
|
90
|
+
- get_secrets(self, paths)
|
|
91
|
+
- Invoked for Managed Account or Secrets Safe secrets.
|
|
92
|
+
- Returns a list of secrets in the requested order.
|
|
93
|
+
- get_secret(self, path)
|
|
94
|
+
- Invoked for Managed Account or Secrets Safe secrets.
|
|
95
|
+
- Returns the requested secret.
|
|
96
|
+
|
|
97
|
+
## Example of usage
|
|
98
|
+
|
|
99
|
+
We strongly recommend you to use a virtual environment and install dependences from requirements.txt file.
|
|
100
|
+
|
|
101
|
+
Import `secrets_safe_library`
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
pip install -r ~/requirements.txt
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
script example using library:
|
|
108
|
+
```python
|
|
109
|
+
import os
|
|
110
|
+
import logging
|
|
111
|
+
from secrets_safe_library import secrets_safe, authentication, utils, managed_account
|
|
112
|
+
import requests
|
|
113
|
+
from retry_requests import retry
|
|
114
|
+
|
|
115
|
+
env = os.environ
|
|
116
|
+
LOGGER_NAME = "custom_logger"
|
|
117
|
+
|
|
118
|
+
logging.basicConfig(format = '%(asctime)-5s %(name)-15s %(levelname)-8s %(message)s',
|
|
119
|
+
|
|
120
|
+
level = logging.DEBUG)
|
|
121
|
+
|
|
122
|
+
# logger object is optional but is strongly recommended
|
|
123
|
+
logger = logging.getLogger(LOGGER_NAME)
|
|
124
|
+
|
|
125
|
+
TIMEOUT_CONNECTION_SECONDS = 30
|
|
126
|
+
TIMEOUT_REQUEST_SECONDS = 30
|
|
127
|
+
|
|
128
|
+
CERTIFICATE = env['CERTIFICATE']
|
|
129
|
+
CERTIFICATE_KEY = env['CERTIFICATE_KEY']
|
|
130
|
+
|
|
131
|
+
def main():
|
|
132
|
+
try:
|
|
133
|
+
with requests.Session() as session:
|
|
134
|
+
req = retry(session, retries=3, backoff_factor=0.2, status_to_retry=(400,408,500,502,503,504))
|
|
135
|
+
|
|
136
|
+
certificate, certificate_key = utils.prepare_certificate_info(CERTIFICATE, CERTIFICATE_KEY)
|
|
137
|
+
|
|
138
|
+
authentication_obj = authentication.Authentication(
|
|
139
|
+
req,
|
|
140
|
+
TIMEOUT_CONNECTION_SECONDS,
|
|
141
|
+
TIMEOUT_REQUEST_SECONDS,
|
|
142
|
+
"https://example.com:443/BeyondTrust/api/public/v3",
|
|
143
|
+
"<client_id>",
|
|
144
|
+
"<client_secret>",
|
|
145
|
+
certificate,
|
|
146
|
+
certificate_key,
|
|
147
|
+
True,
|
|
148
|
+
None)
|
|
149
|
+
|
|
150
|
+
# sign app in password safe API
|
|
151
|
+
get_api_access_response = authentication_obj.get_api_access()
|
|
152
|
+
|
|
153
|
+
if get_api_access_response.status_code == 200:
|
|
154
|
+
# instantiate secrets safe object
|
|
155
|
+
secrets_safe_obj = secrets_safe.SecretsSafe(authentication_obj, logger)
|
|
156
|
+
|
|
157
|
+
get_secrets_response = secrets_safe_obj.get_secrets(["oagrp/text,oagrp/credential"])
|
|
158
|
+
utils.print_log(logger, f"=> Retrive secrets: {get_secrets_response}", logging.DEBUG)
|
|
159
|
+
else:
|
|
160
|
+
print(f"Please check credentials, error {get_api_access_response.text}")
|
|
161
|
+
|
|
162
|
+
authentication_obj.sign_app_out()
|
|
163
|
+
|
|
164
|
+
except Exception as e:
|
|
165
|
+
utils.print_log(logger, f"Error: {e}", logging.ERROR)
|
|
166
|
+
|
|
167
|
+
# calling main method
|
|
168
|
+
main()
|
|
169
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/managed_account_client.py
|
|
5
|
+
src/secret_client.py
|
|
6
|
+
src/beyondtrust_bips_library.egg-info/PKG-INFO
|
|
7
|
+
src/beyondtrust_bips_library.egg-info/SOURCES.txt
|
|
8
|
+
src/beyondtrust_bips_library.egg-info/dependency_links.txt
|
|
9
|
+
src/beyondtrust_bips_library.egg-info/requires.txt
|
|
10
|
+
src/beyondtrust_bips_library.egg-info/top_level.txt
|
|
11
|
+
src/secrets_safe_library/__init__.py
|
|
12
|
+
src/secrets_safe_library/authentication.py
|
|
13
|
+
src/secrets_safe_library/cert_util.py
|
|
14
|
+
src/secrets_safe_library/exceptions.py
|
|
15
|
+
src/secrets_safe_library/managed_account.py
|
|
16
|
+
src/secrets_safe_library/secrets.py
|
|
17
|
+
src/secrets_safe_library/secrets_safe.py
|
|
18
|
+
src/secrets_safe_library/utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import logging
|
|
3
|
+
import requests
|
|
4
|
+
from retry_requests import retry
|
|
5
|
+
from secrets_safe_library import managed_account, authentication, utils, cert_util
|
|
6
|
+
|
|
7
|
+
env = os.environ
|
|
8
|
+
|
|
9
|
+
CLIENT_ID = env["CLIENT_ID"] if 'CLIENT_ID' in env else None
|
|
10
|
+
CLIENT_SECRET = env["CLIENT_SECRET"] if 'CLIENT_SECRET' in env else None
|
|
11
|
+
API_URL = env["API_URL"] if 'API_URL' in env else None
|
|
12
|
+
VERIFY_CA = False if 'VERIFY_CA' in env and env['VERIFY_CA'].lower() == 'false' else True
|
|
13
|
+
MANAGED_ACCOUNT = env['MANAGED_ACCOUNT'].strip() if 'MANAGED_ACCOUNT' in env else None
|
|
14
|
+
MANAGED_ACCOUNT_LIST = env['MANAGED_ACCOUNT_LIST'].strip().split(",") if 'MANAGED_ACCOUNT_LIST' in env and env['MANAGED_ACCOUNT_LIST'].strip() != "" else None
|
|
15
|
+
|
|
16
|
+
API_KEY = env.get("API_KEY")
|
|
17
|
+
|
|
18
|
+
LOGGER_NAME = "custom_logger"
|
|
19
|
+
|
|
20
|
+
TIMEOUT_CONNECTION_SECONDS = 30
|
|
21
|
+
TIMEOUT_REQUEST_SECONDS = 30
|
|
22
|
+
|
|
23
|
+
logging.basicConfig(
|
|
24
|
+
format = '%(asctime)-5s %(name)-15s %(levelname)-8s %(message)s',
|
|
25
|
+
level = logging.DEBUG
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(LOGGER_NAME)
|
|
29
|
+
|
|
30
|
+
CERTIFICATE_PATH = None
|
|
31
|
+
if 'CERTIFICATE_PATH' in env and len(env['CERTIFICATE_PATH']) > 0:
|
|
32
|
+
CERTIFICATE_PATH = env['CERTIFICATE_PATH']
|
|
33
|
+
|
|
34
|
+
CERTIFICATE_PASSWORD = env['CERTIFICATE_PASSWORD'] if 'CERTIFICATE_PASSWORD' in env and CERTIFICATE_PATH else ""
|
|
35
|
+
|
|
36
|
+
def main():
|
|
37
|
+
try:
|
|
38
|
+
decrypt_obj = cert_util.CertUtil(CERTIFICATE_PATH, CERTIFICATE_PASSWORD, logger)
|
|
39
|
+
|
|
40
|
+
certificate = decrypt_obj.get_certificate()
|
|
41
|
+
certificate_key = decrypt_obj.get_certificate_key()
|
|
42
|
+
|
|
43
|
+
with requests.Session() as session:
|
|
44
|
+
req = retry(session, retries=3, backoff_factor=0.2, status_to_retry=(400,408,500,502,503,504))
|
|
45
|
+
|
|
46
|
+
certificate, certificate_key = utils.prepare_certificate_info(certificate, certificate_key)
|
|
47
|
+
|
|
48
|
+
authentication_obj = authentication.Authentication(
|
|
49
|
+
req=req,
|
|
50
|
+
timeout_connection=TIMEOUT_CONNECTION_SECONDS,
|
|
51
|
+
timeout_request=TIMEOUT_REQUEST_SECONDS,
|
|
52
|
+
api_url=API_URL,
|
|
53
|
+
certificate=certificate,
|
|
54
|
+
certificate_key=certificate_key,
|
|
55
|
+
verify_ca=VERIFY_CA,
|
|
56
|
+
logger=logger,
|
|
57
|
+
api_key=API_KEY
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
get_api_access_response = authentication_obj.get_api_access()
|
|
61
|
+
|
|
62
|
+
if get_api_access_response.status_code != 200:
|
|
63
|
+
utils.print_log(logger, f"Please check credentials, error {get_api_access_response.text}", logging.ERROR)
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
if not MANAGED_ACCOUNT and not MANAGED_ACCOUNT_LIST:
|
|
67
|
+
utils.print_log(logger, f"Nothing to do, MANAGED_ACCOUNT and MANAGED_ACCOUNT_LIST parameters are empty!", logging.ERROR)
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
managed_account_obj = managed_account.ManagedAccount(authentication=authentication_obj, logger=logger, separator="*")
|
|
71
|
+
|
|
72
|
+
if MANAGED_ACCOUNT:
|
|
73
|
+
get_secret_response = managed_account_obj.get_secret(MANAGED_ACCOUNT)
|
|
74
|
+
utils.print_log(logger, f"=> Retrive managed account: {get_secret_response}", logging.DEBUG)
|
|
75
|
+
if MANAGED_ACCOUNT_LIST:
|
|
76
|
+
get_secrets_response = managed_account_obj.get_secrets(MANAGED_ACCOUNT_LIST)
|
|
77
|
+
utils.print_log(logger, f"=> Retrive managed accounts: {get_secrets_response}", logging.DEBUG)
|
|
78
|
+
|
|
79
|
+
authentication_obj.sign_app_out()
|
|
80
|
+
|
|
81
|
+
del session
|
|
82
|
+
|
|
83
|
+
except Exception as e:
|
|
84
|
+
utils.print_log(logger, e, logging.ERROR)
|
|
85
|
+
|
|
86
|
+
# calling main method
|
|
87
|
+
main()
|