python4cpm 1.0.27__tar.gz → 1.1.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.
@@ -0,0 +1,275 @@
1
+ Metadata-Version: 2.4
2
+ Name: python4cpm
3
+ Version: 1.1.0
4
+ Summary: Python for CPM
5
+ Author-email: Gonzalo Atienza Rela <gonatienza@gmail.com>
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Dynamic: license-file
11
+
12
+ # Python4CPM
13
+
14
+ A simple way of using python scripts with CyberArk CPM/SRS rotations. This module leverages the [Credential Management .NET SDK](https://docs.cyberark.com/privilege-cloud-standard/latest/en/content/pasimp/plug-in-netinvoker.htm) from CyberArk to securely offload a password rotation logic into a python script.
15
+
16
+ This platform allows you to duplicate it multiple times, simply changing its settings from Privilege Cloud/PVWA to point to different python scripts leveraging the module `python4cpm`.
17
+
18
+ ## Installation
19
+
20
+ ### Preparing Python
21
+
22
+ 1. Install Python along CPM or the SRS Connector Management Agent.
23
+ - **Python must be installed for all users**. Follow the custom install steps from the installation wizard to check the checkbox.
24
+ 3. Create a venv in the server, by running `py -m venv c:\venv`. If desired, use a custom location and adjust any future references.
25
+ 4. Install `python4cpm` in your venv:
26
+ - If your CPM can connect to the internet, install with `c:\venv\Scripts\pip.exe install python4cpm`.
27
+ - If your CPM cannot connect to the internet:
28
+ - Download the latest `python4cpm-*.whl` file from the [pypi project files](https://pypi.org/project/python4cpm/#files).
29
+ - Copy the file to the server into a temporary directory called `python4cpm-wheel`.
30
+ - From the parent directory of `python4cpm-wheel` run `c:\venv\Scripts\pip.exe install --no-index --find-links=.\python4cpm-wheel python4cpm`.
31
+
32
+
33
+ ### Importing the platform
34
+
35
+ #### If you are using CPM (SaaS or Self-Hosted):
36
+ 1. Download the latest [Credential Management .NET SDK](https://community.cyberark.com/marketplace/s/#a3550000000EkA0AAK-a3950000000jjoOAAQ) and place its content in the bin folder of CPM (`C:\Program Files (x86)\CyberArk\Password Manager\bin`). The files for this may already be present.
37
+ 2. Download the `python4cpm-platform-*.zip` asset from the latest [release](https://github.com/gonatienza/python4cpm/releases).
38
+ 3. Import the platform zip file into Privilege Cloud/PVWA `(Administration -> Platform Management -> Import platform)`.
39
+ 4. Craft your python script and place it within a folder in CPM (e.g., `C:\python4cpm-scripts`).
40
+ 5. Duplicate the imported platform in Privilege Cloud/PVWA `(Administration -> Platform Management -> Application -> Python for CPM)` and name it after your application (e.g., My App).
41
+ 6. Edit the duplicated platform and specify the path of your script, under `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonScriptPath -> Value` (e.g., `C:\python4cpm-scripts\myapp.py`).
42
+ 7. Also update `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonExePath -> Value` with the custom path for the venv's `python.exe` file (e.g., `c:\venv\Scripts\python.exe`).
43
+ 8. If you want to disable logging, update `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonLogging -> Value` to `no`.
44
+ 9. If you want to change the logging level to `debug`, update `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonLoggingLevel -> Value` to `debug`.
45
+ 10. For new applications repeat steps from 4 to 9.
46
+
47
+ #### If you are using SRS (SaaS only):
48
+ 1. Download the `python4cpm-platform-*.zip` asset from the latest [release](https://github.com/gonatienza/python4cpm/releases).
49
+ 2. Import the platform zip file into Privilege Cloud `(Administration -> Platform Management -> Import platform)`.
50
+ 3. Craft your python script and place it within a folder in the Cloud Connector (where the SRS Management Agent runs) (e.g., `C:\python4cpm-scripts`).
51
+ 4. Duplicate the imported platform in Privilege Cloud/PVWA `(Administration -> Platform Management -> Application -> Python for CPM)` and name it after your application (e.g., My App).
52
+ 5. Edit the duplicated platform and specify the path of your script, under `Plugin Settings -> Additional Parameters -> PythonScriptPath` (e.g., `C:\python4cpm-scripts\myapp.py`).
53
+ 6. Also update `Plugin Settings -> Additional Parameters -> PythonExePath` with the custom path for the venv's `python.exe` file (e.g., `c:\venv\Scripts\python.exe`).
54
+ 7. If you want to disable logging, update `Plugin Settings -> Additional Parameters -> PythonLogging` to `no`.
55
+ 8. If you want to change the logging level to `debug`, update `Plugin Settings -> Additional Parameters -> PythonLoggingLevel -> Value` to `debug`.
56
+ 9. For new applications repeat steps from 3 to 8.
57
+
58
+ ## Python Script
59
+
60
+ ```python
61
+ from python4cpm import Python4CPMHandler
62
+
63
+
64
+ class MyRotator(Python4CPMHandler): # create a subclass for the Handler
65
+ """
66
+ These are the usable properties and methods from Python4CPMHandler:
67
+
68
+ self.args.action
69
+ # action requested from CPM/SRS
70
+
71
+ ## Target Account
72
+
73
+ self.target_account.username
74
+ # address from account
75
+
76
+ self.target_account.address
77
+ # address from account
78
+
79
+ self.target_account.port
80
+ # port from account
81
+
82
+ self.target_account.password.get()
83
+ # get plaintext str from password object
84
+
85
+ ## Logon Account
86
+ self.logon_account.username
87
+ self.logon_account.password.get()
88
+
89
+ ## Reconcile Account
90
+ self.reconcile_account.username
91
+ self.reconcile_account.password.get()
92
+
93
+ ## Logging
94
+
95
+ self.logger.critical("this is critical message")
96
+ self.logger.error("this is an error message")
97
+ self.logger.warning("this is a warning message")
98
+ self.logger.info("this is an info message")
99
+ self.logger.debug("this is a debug message")
100
+
101
+ # logs are placed in Logs/ThirdParty/MyRotator.log
102
+
103
+ ## The logging level comes from PythonLoggingLevel (platform parameters) (default is error)
104
+
105
+ =============================
106
+ REQUIRED TERMINATION SIGNALS
107
+ =============================
108
+ Terminate signals -> MUST use one of the following three signals to terminate the script:
109
+
110
+ self.close_success()
111
+ # terminate with success state
112
+
113
+ self.close_fail()
114
+ # terminate with recoverable failed state
115
+
116
+ self.close_fail(unrecoverable=True)
117
+ # terminate with unrecoverable failed state
118
+
119
+ When calling a signal sys.exit is invoked and the script is terminated.
120
+ If no signal is called, and the script finishes without any exception,
121
+ it will behave like p4cpm.close_fail(unrecoverable=True) and log an error message.
122
+ =============================
123
+ =============================
124
+ """
125
+
126
+ # =============================
127
+ # REQUIRED METHODS (MUST DEFINE)
128
+ # =============================
129
+ # verify(), logon(), change(), prereconcile(), reconcile()
130
+
131
+ def verify(self):
132
+ self._verify()
133
+ self.log_info("verification successful")
134
+ self.close_success()
135
+
136
+ def logon(self):
137
+ self.close_success()
138
+
139
+ def change(self):
140
+ self._change()
141
+ self.log_error("something went wrong")
142
+ self.close_fail()
143
+
144
+ def prereconcile(self):
145
+ self._verify(from_reconcile=True)
146
+ self.close_success()
147
+
148
+ def reconcile(self):
149
+ self._change(from_reconcile=True)
150
+ self.close_success()
151
+
152
+ def _verify(self, from_reconcile=False):
153
+ if from_reconcile is False:
154
+ pass
155
+ # TODO: use account objects for your logic
156
+ else:
157
+ pass
158
+ # TODO: use account objects for your logic
159
+ result = True
160
+ if result is True:
161
+ self.log_info("verification successful")
162
+ else:
163
+ self.log_error("something went wrong")
164
+ self.close_fail()
165
+
166
+ def _change(self, from_reconcile=False):
167
+ if from_reconcile is False:
168
+ pass
169
+ # TODO: use account objects for your logic
170
+ else:
171
+ pass
172
+ # TODO: use account objects for your logic
173
+ result = True
174
+ if result is True:
175
+ self.log_info("rotation successful")
176
+ else:
177
+ self.log_error("something went wrong")
178
+ self.close_fail()
179
+
180
+
181
+ if __name__ == "__main__":
182
+ MyRotator().run() # initializes the class and calls the action that was requested from CPM/SRS.
183
+ ```
184
+ (*) More realistic examples can be found [here](https://github.com/gonatienza/python4cpm/blob/main/examples).
185
+
186
+ When doing `verify`, `change` or `reconcile` from Privilege Cloud/PVWA:
187
+ 1. Verify -> the sciprt will be executed once running the `MyRotator.verify()` method.
188
+ 2. Change -> the sciprt will be executed twice, running first the `MyRotator.logon()` method and secondly the `MyRotator.change()` method.
189
+ - If both actions are not terminated with `self.close_success()` and the scripts terminates without any exception, CPM/SRS will see this as a `self.close_fail(unrecoverable=True)`.
190
+ 3. Reconcile -> the sciprt will be executed twice, running first the `MyRotator.prereconcile()` method and secondly the `MyRotator.reconcile()` method.
191
+ - If both actions are not terminated with `self.close_success()` and the scripts terminates without any exception, CPM/SRS will see this as a `self.close_fail(unrecoverable=True)`.
192
+ 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.secrets.new_password.get()` will always return an empty string.
193
+ 5. If a logon account is not linked, `self.args.logon_username` and `self.secrets.logon_password.get()` will return empty strings.
194
+ 6. If a reconcile account is not linked, `self.args.reconcile_username` and `self.secrets.reconcile_password.get()` will return empty strings.
195
+
196
+
197
+ ### Installing dependencies in python venv
198
+
199
+ As with any python venv, you can install dependencies in your venv.
200
+ 1. If your CPM can connect to the internet:
201
+ - You can use regular pip install commands (e.g., `c:\venv\Scripts\pip.exe install requests`).
202
+ 2. If your CPM cannot connect to the internet:
203
+ - You can download packages for an offline install. More info [here](https://pip.pypa.io/en/stable/cli/pip_download/).
204
+
205
+
206
+ ## Dev Helper:
207
+
208
+ For dev purposes, `NETHelper` is a companion helper that simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin passes arguments and secrets to the modules.
209
+ Install this module (in a dev workstation) with:
210
+
211
+ ```bash
212
+ pip install python4cpm
213
+ ```
214
+
215
+ **Note**: As CPM runs in Windows, the plugin was built to pass secrets securely to the `Python4CPM.crypto` module using the Data Protection API (DPAPI). For dev purposes in Linux/Mac dev workstations, those secrets will appear as plaintext in the environment of the process. This is informational only, the module will use its encryption/decryption capabilities automatically in Windows and you do not have to do anything specific to enable it.
216
+
217
+ ### Example:
218
+
219
+ #### Set your arguments and secrets:
220
+
221
+ ```python
222
+ from python4cpm import NETHelper, Python4CPM, Python4CPMHandler
223
+ from getpass import getpass
224
+
225
+ # Get secrets for your password, logon account password, reconcile account password and new password
226
+ # You can use an empty string if it does not apply
227
+ target_password = getpass("password: ") # password from account
228
+ logon_password = getpass("logon_password: ") # password from linked logon account
229
+ reconcile_password = getpass("reconcile_password: ") # password from linked reconcile account
230
+ target_new_password = getpass("new_password: ") # new password for the rotation
231
+
232
+ NETHelper.set(
233
+ action=Python4CPM.ACTION_CHANGE, # use actions from Python4CPM.ACTION_*
234
+ target_username="jdoe",
235
+ target_address="myapp.corp.local",
236
+ target_port="8443",
237
+ logon_username="ldoe",
238
+ reconcile_username="rdoe",
239
+ logging_level="debug", # "critical", "error", "warning", "info" or "debug"
240
+ target_password=target_password,
241
+ logon_password=logon_password,
242
+ reconcile_password=reconcile_password,
243
+ target_new_password=target_new_password
244
+ )
245
+
246
+ class MyRotator(Python4CPMHandler):
247
+ def verify(self):
248
+ # TODO: Add your logic here
249
+ self.close_success()
250
+
251
+ def logon(self):
252
+ # TODO: Add your logic here
253
+ self.close_success()
254
+
255
+ def change(self):
256
+ # TODO: Add your logic here
257
+ self.close_success()
258
+
259
+ def prereconcile(self):
260
+ # TODO: Add your logic here
261
+ self.close_success()
262
+
263
+ def reconcile(self):
264
+ # TODO: Add your logic here
265
+ self.close_success()
266
+
267
+ MyRotator().run()
268
+ ```
269
+
270
+ #### Remember for your final script:
271
+
272
+ - Remove the import of `NETHelper`.
273
+ - Remove the `NETHelper.set()` call.
274
+ - If applicable, change the definition of `p4cpm` from `p4cpm = NETHelper.get()` to `p4cpm = Python4CPM("MyApp")`.
275
+ - Remove any secrets prompting or interactive interruptions.
@@ -0,0 +1,264 @@
1
+ # Python4CPM
2
+
3
+ A simple way of using python scripts with CyberArk CPM/SRS rotations. This module leverages the [Credential Management .NET SDK](https://docs.cyberark.com/privilege-cloud-standard/latest/en/content/pasimp/plug-in-netinvoker.htm) from CyberArk to securely offload a password rotation logic into a python script.
4
+
5
+ This platform allows you to duplicate it multiple times, simply changing its settings from Privilege Cloud/PVWA to point to different python scripts leveraging the module `python4cpm`.
6
+
7
+ ## Installation
8
+
9
+ ### Preparing Python
10
+
11
+ 1. Install Python along CPM or the SRS Connector Management Agent.
12
+ - **Python must be installed for all users**. Follow the custom install steps from the installation wizard to check the checkbox.
13
+ 3. Create a venv in the server, by running `py -m venv c:\venv`. If desired, use a custom location and adjust any future references.
14
+ 4. Install `python4cpm` in your venv:
15
+ - If your CPM can connect to the internet, install with `c:\venv\Scripts\pip.exe install python4cpm`.
16
+ - If your CPM cannot connect to the internet:
17
+ - Download the latest `python4cpm-*.whl` file from the [pypi project files](https://pypi.org/project/python4cpm/#files).
18
+ - Copy the file to the server into a temporary directory called `python4cpm-wheel`.
19
+ - From the parent directory of `python4cpm-wheel` run `c:\venv\Scripts\pip.exe install --no-index --find-links=.\python4cpm-wheel python4cpm`.
20
+
21
+
22
+ ### Importing the platform
23
+
24
+ #### If you are using CPM (SaaS or Self-Hosted):
25
+ 1. Download the latest [Credential Management .NET SDK](https://community.cyberark.com/marketplace/s/#a3550000000EkA0AAK-a3950000000jjoOAAQ) and place its content in the bin folder of CPM (`C:\Program Files (x86)\CyberArk\Password Manager\bin`). The files for this may already be present.
26
+ 2. Download the `python4cpm-platform-*.zip` asset from the latest [release](https://github.com/gonatienza/python4cpm/releases).
27
+ 3. Import the platform zip file into Privilege Cloud/PVWA `(Administration -> Platform Management -> Import platform)`.
28
+ 4. Craft your python script and place it within a folder in CPM (e.g., `C:\python4cpm-scripts`).
29
+ 5. Duplicate the imported platform in Privilege Cloud/PVWA `(Administration -> Platform Management -> Application -> Python for CPM)` and name it after your application (e.g., My App).
30
+ 6. Edit the duplicated platform and specify the path of your script, under `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonScriptPath -> Value` (e.g., `C:\python4cpm-scripts\myapp.py`).
31
+ 7. Also update `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonExePath -> Value` with the custom path for the venv's `python.exe` file (e.g., `c:\venv\Scripts\python.exe`).
32
+ 8. If you want to disable logging, update `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonLogging -> Value` to `no`.
33
+ 9. If you want to change the logging level to `debug`, update `Target Account Platform -> Automatic Platform Management -> Additional Policy Settings -> Parameters -> PythonLoggingLevel -> Value` to `debug`.
34
+ 10. For new applications repeat steps from 4 to 9.
35
+
36
+ #### If you are using SRS (SaaS only):
37
+ 1. Download the `python4cpm-platform-*.zip` asset from the latest [release](https://github.com/gonatienza/python4cpm/releases).
38
+ 2. Import the platform zip file into Privilege Cloud `(Administration -> Platform Management -> Import platform)`.
39
+ 3. Craft your python script and place it within a folder in the Cloud Connector (where the SRS Management Agent runs) (e.g., `C:\python4cpm-scripts`).
40
+ 4. Duplicate the imported platform in Privilege Cloud/PVWA `(Administration -> Platform Management -> Application -> Python for CPM)` and name it after your application (e.g., My App).
41
+ 5. Edit the duplicated platform and specify the path of your script, under `Plugin Settings -> Additional Parameters -> PythonScriptPath` (e.g., `C:\python4cpm-scripts\myapp.py`).
42
+ 6. Also update `Plugin Settings -> Additional Parameters -> PythonExePath` with the custom path for the venv's `python.exe` file (e.g., `c:\venv\Scripts\python.exe`).
43
+ 7. If you want to disable logging, update `Plugin Settings -> Additional Parameters -> PythonLogging` to `no`.
44
+ 8. If you want to change the logging level to `debug`, update `Plugin Settings -> Additional Parameters -> PythonLoggingLevel -> Value` to `debug`.
45
+ 9. For new applications repeat steps from 3 to 8.
46
+
47
+ ## Python Script
48
+
49
+ ```python
50
+ from python4cpm import Python4CPMHandler
51
+
52
+
53
+ class MyRotator(Python4CPMHandler): # create a subclass for the Handler
54
+ """
55
+ These are the usable properties and methods from Python4CPMHandler:
56
+
57
+ self.args.action
58
+ # action requested from CPM/SRS
59
+
60
+ ## Target Account
61
+
62
+ self.target_account.username
63
+ # address from account
64
+
65
+ self.target_account.address
66
+ # address from account
67
+
68
+ self.target_account.port
69
+ # port from account
70
+
71
+ self.target_account.password.get()
72
+ # get plaintext str from password object
73
+
74
+ ## Logon Account
75
+ self.logon_account.username
76
+ self.logon_account.password.get()
77
+
78
+ ## Reconcile Account
79
+ self.reconcile_account.username
80
+ self.reconcile_account.password.get()
81
+
82
+ ## Logging
83
+
84
+ self.logger.critical("this is critical message")
85
+ self.logger.error("this is an error message")
86
+ self.logger.warning("this is a warning message")
87
+ self.logger.info("this is an info message")
88
+ self.logger.debug("this is a debug message")
89
+
90
+ # logs are placed in Logs/ThirdParty/MyRotator.log
91
+
92
+ ## The logging level comes from PythonLoggingLevel (platform parameters) (default is error)
93
+
94
+ =============================
95
+ REQUIRED TERMINATION SIGNALS
96
+ =============================
97
+ Terminate signals -> MUST use one of the following three signals to terminate the script:
98
+
99
+ self.close_success()
100
+ # terminate with success state
101
+
102
+ self.close_fail()
103
+ # terminate with recoverable failed state
104
+
105
+ self.close_fail(unrecoverable=True)
106
+ # terminate with unrecoverable failed state
107
+
108
+ When calling a signal sys.exit is invoked and the script is terminated.
109
+ If no signal is called, and the script finishes without any exception,
110
+ it will behave like p4cpm.close_fail(unrecoverable=True) and log an error message.
111
+ =============================
112
+ =============================
113
+ """
114
+
115
+ # =============================
116
+ # REQUIRED METHODS (MUST DEFINE)
117
+ # =============================
118
+ # verify(), logon(), change(), prereconcile(), reconcile()
119
+
120
+ def verify(self):
121
+ self._verify()
122
+ self.log_info("verification successful")
123
+ self.close_success()
124
+
125
+ def logon(self):
126
+ self.close_success()
127
+
128
+ def change(self):
129
+ self._change()
130
+ self.log_error("something went wrong")
131
+ self.close_fail()
132
+
133
+ def prereconcile(self):
134
+ self._verify(from_reconcile=True)
135
+ self.close_success()
136
+
137
+ def reconcile(self):
138
+ self._change(from_reconcile=True)
139
+ self.close_success()
140
+
141
+ def _verify(self, from_reconcile=False):
142
+ if from_reconcile is False:
143
+ pass
144
+ # TODO: use account objects for your logic
145
+ else:
146
+ pass
147
+ # TODO: use account objects for your logic
148
+ result = True
149
+ if result is True:
150
+ self.log_info("verification successful")
151
+ else:
152
+ self.log_error("something went wrong")
153
+ self.close_fail()
154
+
155
+ def _change(self, from_reconcile=False):
156
+ if from_reconcile is False:
157
+ pass
158
+ # TODO: use account objects for your logic
159
+ else:
160
+ pass
161
+ # TODO: use account objects for your logic
162
+ result = True
163
+ if result is True:
164
+ self.log_info("rotation successful")
165
+ else:
166
+ self.log_error("something went wrong")
167
+ self.close_fail()
168
+
169
+
170
+ if __name__ == "__main__":
171
+ MyRotator().run() # initializes the class and calls the action that was requested from CPM/SRS.
172
+ ```
173
+ (*) More realistic examples can be found [here](https://github.com/gonatienza/python4cpm/blob/main/examples).
174
+
175
+ When doing `verify`, `change` or `reconcile` from Privilege Cloud/PVWA:
176
+ 1. Verify -> the sciprt will be executed once running the `MyRotator.verify()` method.
177
+ 2. Change -> the sciprt will be executed twice, running first the `MyRotator.logon()` method and secondly the `MyRotator.change()` method.
178
+ - If both actions are not terminated with `self.close_success()` and the scripts terminates without any exception, CPM/SRS will see this as a `self.close_fail(unrecoverable=True)`.
179
+ 3. Reconcile -> the sciprt will be executed twice, running first the `MyRotator.prereconcile()` method and secondly the `MyRotator.reconcile()` method.
180
+ - If both actions are not terminated with `self.close_success()` and the scripts terminates without any exception, CPM/SRS will see this as a `self.close_fail(unrecoverable=True)`.
181
+ 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.secrets.new_password.get()` will always return an empty string.
182
+ 5. If a logon account is not linked, `self.args.logon_username` and `self.secrets.logon_password.get()` will return empty strings.
183
+ 6. If a reconcile account is not linked, `self.args.reconcile_username` and `self.secrets.reconcile_password.get()` will return empty strings.
184
+
185
+
186
+ ### Installing dependencies in python venv
187
+
188
+ As with any python venv, you can install dependencies in your venv.
189
+ 1. If your CPM can connect to the internet:
190
+ - You can use regular pip install commands (e.g., `c:\venv\Scripts\pip.exe install requests`).
191
+ 2. If your CPM cannot connect to the internet:
192
+ - You can download packages for an offline install. More info [here](https://pip.pypa.io/en/stable/cli/pip_download/).
193
+
194
+
195
+ ## Dev Helper:
196
+
197
+ For dev purposes, `NETHelper` is a companion helper that simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin passes arguments and secrets to the modules.
198
+ Install this module (in a dev workstation) with:
199
+
200
+ ```bash
201
+ pip install python4cpm
202
+ ```
203
+
204
+ **Note**: As CPM runs in Windows, the plugin was built to pass secrets securely to the `Python4CPM.crypto` module using the Data Protection API (DPAPI). For dev purposes in Linux/Mac dev workstations, those secrets will appear as plaintext in the environment of the process. This is informational only, the module will use its encryption/decryption capabilities automatically in Windows and you do not have to do anything specific to enable it.
205
+
206
+ ### Example:
207
+
208
+ #### Set your arguments and secrets:
209
+
210
+ ```python
211
+ from python4cpm import NETHelper, Python4CPM, Python4CPMHandler
212
+ from getpass import getpass
213
+
214
+ # Get secrets for your password, logon account password, reconcile account password and new password
215
+ # You can use an empty string if it does not apply
216
+ target_password = getpass("password: ") # password from account
217
+ logon_password = getpass("logon_password: ") # password from linked logon account
218
+ reconcile_password = getpass("reconcile_password: ") # password from linked reconcile account
219
+ target_new_password = getpass("new_password: ") # new password for the rotation
220
+
221
+ NETHelper.set(
222
+ action=Python4CPM.ACTION_CHANGE, # use actions from Python4CPM.ACTION_*
223
+ target_username="jdoe",
224
+ target_address="myapp.corp.local",
225
+ target_port="8443",
226
+ logon_username="ldoe",
227
+ reconcile_username="rdoe",
228
+ logging_level="debug", # "critical", "error", "warning", "info" or "debug"
229
+ target_password=target_password,
230
+ logon_password=logon_password,
231
+ reconcile_password=reconcile_password,
232
+ target_new_password=target_new_password
233
+ )
234
+
235
+ class MyRotator(Python4CPMHandler):
236
+ def verify(self):
237
+ # TODO: Add your logic here
238
+ self.close_success()
239
+
240
+ def logon(self):
241
+ # TODO: Add your logic here
242
+ self.close_success()
243
+
244
+ def change(self):
245
+ # TODO: Add your logic here
246
+ self.close_success()
247
+
248
+ def prereconcile(self):
249
+ # TODO: Add your logic here
250
+ self.close_success()
251
+
252
+ def reconcile(self):
253
+ # TODO: Add your logic here
254
+ self.close_success()
255
+
256
+ MyRotator().run()
257
+ ```
258
+
259
+ #### Remember for your final script:
260
+
261
+ - Remove the import of `NETHelper`.
262
+ - Remove the `NETHelper.set()` call.
263
+ - If applicable, change the definition of `p4cpm` from `p4cpm = NETHelper.get()` to `p4cpm = Python4CPM("MyApp")`.
264
+ - Remove any secrets prompting or interactive interruptions.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python4cpm"
7
- version = "1.0.27"
7
+ version = "1.1.0"
8
8
  description = "Python for CPM"
9
9
  authors = [
10
10
  { name = "Gonzalo Atienza Rela", email = "gonatienza@gmail.com" }
@@ -0,0 +1,70 @@
1
+ from python4cpm.secret import Secret
2
+
3
+
4
+ class BaseAccount:
5
+ def __init__(
6
+ self: str,
7
+ username: str,
8
+ password: str
9
+ ) -> None:
10
+ self._username = username
11
+ self._password = Secret(password)
12
+
13
+ @property
14
+ def username(self) -> str:
15
+ return self._username
16
+
17
+ @property
18
+ def password(self) -> Secret:
19
+ return self._password
20
+
21
+
22
+ class TargetAccount(BaseAccount):
23
+ ENV_VARS = (
24
+ "target_username",
25
+ "target_password",
26
+ "target_address",
27
+ "target_port",
28
+ "target_new_password"
29
+ )
30
+ def __init__(
31
+ self: str,
32
+ username: str,
33
+ password: str,
34
+ address: str,
35
+ port: str,
36
+ new_password: str
37
+ ) -> None:
38
+ super().__init__(
39
+ username,
40
+ password
41
+ )
42
+ self._address = address
43
+ self._port = port
44
+ self._new_password = Secret(new_password)
45
+
46
+ @property
47
+ def address(self) -> str:
48
+ return self._address
49
+
50
+ @property
51
+ def port(self) -> str:
52
+ return self._port
53
+
54
+ @property
55
+ def new_password(self) -> Secret:
56
+ return self._new_password
57
+
58
+
59
+ class LogonAccount(BaseAccount):
60
+ ENV_VARS = (
61
+ "logon_username",
62
+ "logon_password"
63
+ )
64
+
65
+
66
+ class ReconcileAccount(BaseAccount):
67
+ ENV_VARS = (
68
+ "reconcile_username",
69
+ "reconcile_password"
70
+ )
@@ -0,0 +1,21 @@
1
+ class Args:
2
+ ARGS = (
3
+ "action",
4
+ "logging_level"
5
+ )
6
+
7
+ def __init__(
8
+ self: str,
9
+ action: str,
10
+ logging_level: str
11
+ ) -> None:
12
+ self._action = action
13
+ self._logging_level = logging_level
14
+
15
+ @property
16
+ def action(self) -> str:
17
+ return self._action
18
+
19
+ @property
20
+ def logging_level(self) -> str:
21
+ return self._logging_level
@@ -5,21 +5,21 @@ from logging.handlers import RotatingFileHandler
5
5
 
6
6
  class Logger:
7
7
  _LOGS_DIR = os.path.join("Logs", "ThirdParty")
8
- _LOGGING_ENABLED_VALUE = "yes"
9
8
  _LOGGING_LEVELS = {
9
+ "critical": logging.CRITICAL,
10
+ "error": logging.ERROR,
11
+ "warning": logging.WARNING,
10
12
  "info": logging.INFO,
11
13
  "debug": logging.DEBUG
12
14
  }
15
+ _DEFAULT_LEVEL = _LOGGING_LEVELS["error"]
13
16
 
14
17
  @classmethod
15
18
  def get_logger(
16
19
  cls,
17
20
  name: str,
18
- args_logging: str,
19
21
  args_logging_level: str
20
22
  ) -> logging.Logger:
21
- if args_logging.lower() != cls._LOGGING_ENABLED_VALUE:
22
- return None
23
23
  os.makedirs(cls._LOGS_DIR, exist_ok=True)
24
24
  logs_file = os.path.join(cls._LOGS_DIR, f"{__name__}-{name}.log")
25
25
  _id = os.urandom(4).hex()
@@ -27,7 +27,7 @@ class Logger:
27
27
  if args_logging_level.lower() in cls._LOGGING_LEVELS:
28
28
  logger.setLevel(cls._LOGGING_LEVELS[args_logging_level.lower()])
29
29
  else:
30
- logger.setLevel(cls._LOGGING_LEVELS["info"])
30
+ logger.setLevel(cls._DEFAULT_LEVEL)
31
31
  handler = RotatingFileHandler(
32
32
  filename=logs_file,
33
33
  maxBytes=1024 ** 2,