python4cpm 1.1.2__tar.gz → 1.1.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python4cpm
3
- Version: 1.1.2
3
+ Version: 1.1.3
4
4
  Summary: Python for CPM
5
5
  Author-email: Gonzalo Atienza Rela <gonatienza@gmail.com>
6
6
  License-Expression: MIT
@@ -67,7 +67,7 @@ This platform allows you to duplicate it multiple times, simply changing its set
67
67
  from python4cpm import Python4CPMHandler
68
68
 
69
69
 
70
- class MyRotator(Python4CPMHandler): # create a subclass for the Handler
70
+ class MyRotator(Python4CPMHandler):
71
71
  """
72
72
  These are the usable properties and methods from Python4CPMHandler:
73
73
 
@@ -123,64 +123,33 @@ class MyRotator(Python4CPMHandler): # create a subclass for the Handler
123
123
  When calling a signal sys.exit is invoked and the script is terminated.
124
124
  If no signal is called, and the script finishes without any exception,
125
125
  it will behave like p4cpm.close_fail(unrecoverable=True) and log an error message.
126
+
126
127
  =============================
128
+ REQUIRED METHODS
127
129
  =============================
130
+ verify(), logon(), change(), prereconcile(), reconcile()
128
131
  """
129
132
 
130
- # =============================
131
- # REQUIRED METHODS (MUST DEFINE)
132
- # =============================
133
- # verify(), logon(), change(), prereconcile(), reconcile()
134
-
135
133
  def verify(self):
136
- self._verify()
137
- self.log_info("verification successful")
134
+ # TODO: use account objects for your logic
138
135
  self.close_success()
139
136
 
140
137
  def logon(self):
138
+ # TODO: use account objects for your logic
141
139
  self.close_success()
142
140
 
143
141
  def change(self):
144
- self._change()
145
- self.log_error("something went wrong")
146
- self.close_fail()
142
+ # TODO: use account objects for your logic
143
+ self.close_success()
147
144
 
148
145
  def prereconcile(self):
149
- self._verify(from_reconcile=True)
146
+ # TODO: use account objects for your logic
150
147
  self.close_success()
151
148
 
152
149
  def reconcile(self):
153
- self._change(from_reconcile=True)
150
+ # TODO: use account objects for your logic
154
151
  self.close_success()
155
152
 
156
- def _verify(self, from_reconcile=False):
157
- if from_reconcile is False:
158
- pass
159
- # TODO: use account objects for your logic
160
- else:
161
- pass
162
- # TODO: use account objects for your logic
163
- result = True
164
- if result is True:
165
- self.log_info("verification successful")
166
- else:
167
- self.log_error("something went wrong")
168
- self.close_fail()
169
-
170
- def _change(self, from_reconcile=False):
171
- if from_reconcile is False:
172
- pass
173
- # TODO: use account objects for your logic
174
- else:
175
- pass
176
- # TODO: use account objects for your logic
177
- result = True
178
- if result is True:
179
- self.log_info("rotation successful")
180
- else:
181
- self.log_error("something went wrong")
182
- self.close_fail()
183
-
184
153
 
185
154
  if __name__ == "__main__":
186
155
  MyRotator().run() # initializes the class and calls the action that was requested from CPM/SRS.
@@ -193,9 +162,9 @@ When doing `verify`, `change` or `reconcile` from Privilege Cloud/PVWA:
193
162
  - 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)`.
194
163
  3. Reconcile -> the sciprt will be executed twice, running first the `MyRotator.prereconcile()` method and secondly the `MyRotator.reconcile()` method.
195
164
  - 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)`.
196
- 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.target_account.new_password.get()` will always return an empty string.
197
- 5. If a logon account is not linked, `self.logon_account.username` and `self.logon_account.password.get()` will return empty strings.
198
- 6. If a reconcile account is not linked, `self.reconcile_account.username` and `self.reconcile_account.password.get()` will return empty strings.
165
+ 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.target_account.new_password` will always return `None`.
166
+ 5. If a logon account is not linked, `self.logon_account` will return `None`.
167
+ 6. If a reconcile account is not linked, `self.reconcile_account` will return `None`.
199
168
  7. The python `Logger` places its logs in the `Logs/ThirdParty` directory. The filename will be based on the name of the subclass created (e.g., `MyRotator`).
200
169
 
201
170
 
@@ -210,7 +179,7 @@ As with any python venv, you can install dependencies in your venv.
210
179
 
211
180
  ## Dev Helper:
212
181
 
213
- For dev purposes, `NETHelper` is a companion helper to test your scripts before shipping to CPM/SRS. It simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin creates the environment context for the python module.
182
+ For dev purposes, `NETHelper` is a companion helper to test your scripts without CPM/SRS. It simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin creates the environment context for the python module.
214
183
 
215
184
  **Note**: As CPM and the SRS management agent run in Windows, the plugin was built to encrypt secrets using DPAPI (a windows only library). For dev purposes in Linux/Mac dev workstations, those secrets put in the environment context by `NETHelper` will be in plaintext. In windows dev workstations, `NETHelper` encrypts the secrets as the .NET plugin does. This is informational only, **the module will use its encryption/decryption capabilities automatically based on the platform** it is running on and you do not have to do anything specific to enable it.
216
185
 
@@ -223,7 +192,7 @@ from python4cpm import NETHelper, Python4CPM, Python4CPMHandler
223
192
  from getpass import getpass
224
193
 
225
194
  # 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
195
+ # You may set to None any argument that does not apply or simply leaving it to its default None value.
227
196
  target_password = getpass("password: ") # password from account
228
197
  logon_password = getpass("logon_password: ") # password from linked logon account
229
198
  reconcile_password = getpass("reconcile_password: ") # password from linked reconcile account
@@ -271,5 +240,4 @@ MyRotator().run()
271
240
 
272
241
  - Remove the import of `NETHelper`.
273
242
  - Remove the `NETHelper.set()` call.
274
- - If applicable, change the definition of `p4cpm` from `p4cpm = NETHelper.get()` to `p4cpm = Python4CPM("MyApp")`.
275
243
  - Remove any secrets prompting or interactive interruptions.
@@ -56,7 +56,7 @@ This platform allows you to duplicate it multiple times, simply changing its set
56
56
  from python4cpm import Python4CPMHandler
57
57
 
58
58
 
59
- class MyRotator(Python4CPMHandler): # create a subclass for the Handler
59
+ class MyRotator(Python4CPMHandler):
60
60
  """
61
61
  These are the usable properties and methods from Python4CPMHandler:
62
62
 
@@ -112,64 +112,33 @@ class MyRotator(Python4CPMHandler): # create a subclass for the Handler
112
112
  When calling a signal sys.exit is invoked and the script is terminated.
113
113
  If no signal is called, and the script finishes without any exception,
114
114
  it will behave like p4cpm.close_fail(unrecoverable=True) and log an error message.
115
+
115
116
  =============================
117
+ REQUIRED METHODS
116
118
  =============================
119
+ verify(), logon(), change(), prereconcile(), reconcile()
117
120
  """
118
121
 
119
- # =============================
120
- # REQUIRED METHODS (MUST DEFINE)
121
- # =============================
122
- # verify(), logon(), change(), prereconcile(), reconcile()
123
-
124
122
  def verify(self):
125
- self._verify()
126
- self.log_info("verification successful")
123
+ # TODO: use account objects for your logic
127
124
  self.close_success()
128
125
 
129
126
  def logon(self):
127
+ # TODO: use account objects for your logic
130
128
  self.close_success()
131
129
 
132
130
  def change(self):
133
- self._change()
134
- self.log_error("something went wrong")
135
- self.close_fail()
131
+ # TODO: use account objects for your logic
132
+ self.close_success()
136
133
 
137
134
  def prereconcile(self):
138
- self._verify(from_reconcile=True)
135
+ # TODO: use account objects for your logic
139
136
  self.close_success()
140
137
 
141
138
  def reconcile(self):
142
- self._change(from_reconcile=True)
139
+ # TODO: use account objects for your logic
143
140
  self.close_success()
144
141
 
145
- def _verify(self, from_reconcile=False):
146
- if from_reconcile is False:
147
- pass
148
- # TODO: use account objects for your logic
149
- else:
150
- pass
151
- # TODO: use account objects for your logic
152
- result = True
153
- if result is True:
154
- self.log_info("verification successful")
155
- else:
156
- self.log_error("something went wrong")
157
- self.close_fail()
158
-
159
- def _change(self, from_reconcile=False):
160
- if from_reconcile is False:
161
- pass
162
- # TODO: use account objects for your logic
163
- else:
164
- pass
165
- # TODO: use account objects for your logic
166
- result = True
167
- if result is True:
168
- self.log_info("rotation successful")
169
- else:
170
- self.log_error("something went wrong")
171
- self.close_fail()
172
-
173
142
 
174
143
  if __name__ == "__main__":
175
144
  MyRotator().run() # initializes the class and calls the action that was requested from CPM/SRS.
@@ -182,9 +151,9 @@ When doing `verify`, `change` or `reconcile` from Privilege Cloud/PVWA:
182
151
  - 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)`.
183
152
  3. Reconcile -> the sciprt will be executed twice, running first the `MyRotator.prereconcile()` method and secondly the `MyRotator.reconcile()` method.
184
153
  - 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)`.
185
- 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.target_account.new_password.get()` will always return an empty string.
186
- 5. If a logon account is not linked, `self.logon_account.username` and `self.logon_account.password.get()` will return empty strings.
187
- 6. If a reconcile account is not linked, `self.reconcile_account.username` and `self.reconcile_account.password.get()` will return empty strings.
154
+ 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.target_account.new_password` will always return `None`.
155
+ 5. If a logon account is not linked, `self.logon_account` will return `None`.
156
+ 6. If a reconcile account is not linked, `self.reconcile_account` will return `None`.
188
157
  7. The python `Logger` places its logs in the `Logs/ThirdParty` directory. The filename will be based on the name of the subclass created (e.g., `MyRotator`).
189
158
 
190
159
 
@@ -199,7 +168,7 @@ As with any python venv, you can install dependencies in your venv.
199
168
 
200
169
  ## Dev Helper:
201
170
 
202
- For dev purposes, `NETHelper` is a companion helper to test your scripts before shipping to CPM/SRS. It simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin creates the environment context for the python module.
171
+ For dev purposes, `NETHelper` is a companion helper to test your scripts without CPM/SRS. It simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin creates the environment context for the python module.
203
172
 
204
173
  **Note**: As CPM and the SRS management agent run in Windows, the plugin was built to encrypt secrets using DPAPI (a windows only library). For dev purposes in Linux/Mac dev workstations, those secrets put in the environment context by `NETHelper` will be in plaintext. In windows dev workstations, `NETHelper` encrypts the secrets as the .NET plugin does. This is informational only, **the module will use its encryption/decryption capabilities automatically based on the platform** it is running on and you do not have to do anything specific to enable it.
205
174
 
@@ -212,7 +181,7 @@ from python4cpm import NETHelper, Python4CPM, Python4CPMHandler
212
181
  from getpass import getpass
213
182
 
214
183
  # 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
184
+ # You may set to None any argument that does not apply or simply leaving it to its default None value.
216
185
  target_password = getpass("password: ") # password from account
217
186
  logon_password = getpass("logon_password: ") # password from linked logon account
218
187
  reconcile_password = getpass("reconcile_password: ") # password from linked reconcile account
@@ -260,5 +229,4 @@ MyRotator().run()
260
229
 
261
230
  - Remove the import of `NETHelper`.
262
231
  - Remove the `NETHelper.set()` call.
263
- - If applicable, change the definition of `p4cpm` from `p4cpm = NETHelper.get()` to `p4cpm = Python4CPM("MyApp")`.
264
232
  - 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.1.2"
7
+ version = "1.1.3"
8
8
  description = "Python for CPM"
9
9
  authors = [
10
10
  { name = "Gonzalo Atienza Rela", email = "gonatienza@gmail.com" }
@@ -7,11 +7,18 @@ class BaseAccount(EnvHandler):
7
7
 
8
8
  def __init__(
9
9
  self,
10
- username: str,
11
- password: str
10
+ username: str | None,
11
+ password: str | None
12
12
  ) -> None:
13
13
  self._username = username
14
- self._password = Secret(password)
14
+ self._password = Secret.from_env_var(password)
15
+
16
+ @classmethod
17
+ def get(cls) -> object | None:
18
+ kwargs = cls.get_kwargs()
19
+ if all(value is None for value in kwargs.values()):
20
+ return None
21
+ return cls(**kwargs)
15
22
 
16
23
  @property
17
24
  def username(self) -> str:
@@ -28,11 +35,11 @@ class TargetAccount(BaseAccount):
28
35
 
29
36
  def __init__(
30
37
  self,
31
- username: str,
32
- password: str,
33
- address: str,
34
- port: str,
35
- new_password: str
38
+ username: str | None,
39
+ password: str | None,
40
+ address: str | None,
41
+ port: str | None,
42
+ new_password: str | None
36
43
  ) -> None:
37
44
  super().__init__(
38
45
  username,
@@ -40,14 +47,14 @@ class TargetAccount(BaseAccount):
40
47
  )
41
48
  self._address = address
42
49
  self._port = port
43
- self._new_password = Secret(new_password)
50
+ self._new_password = Secret.from_env_var(new_password)
44
51
 
45
52
  @property
46
- def address(self) -> str:
53
+ def address(self) -> str | None:
47
54
  return self._address
48
55
 
49
56
  @property
50
- def port(self) -> str:
57
+ def port(self) -> str | None:
51
58
  return self._port
52
59
 
53
60
  @property
@@ -7,8 +7,8 @@ class Args(EnvHandler):
7
7
 
8
8
  def __init__(
9
9
  self,
10
- action: str,
11
- logging_level: str
10
+ action: str | None,
11
+ logging_level: str | None
12
12
  ) -> None:
13
13
  self._action = action
14
14
  self._logging_level = logging_level
@@ -18,5 +18,5 @@ class Args(EnvHandler):
18
18
  return self._action
19
19
 
20
20
  @property
21
- def logging_level(self) -> str:
21
+ def logging_level(self) -> str | None:
22
22
  return self._logging_level
@@ -20,10 +20,13 @@ class EnvHandler:
20
20
  env_key = f"{cls.PREFIX}{cls.OBJ_PREFIX}{key}"
21
21
  return env_key.upper()
22
22
 
23
+ @classmethod
24
+ def get_kwargs(cls) -> dict:
25
+ return {
26
+ prop: os.environ.get(cls.get_key(prop))
27
+ for prop in cls.PROPS
28
+ }
29
+
23
30
  @classmethod
24
31
  def get(cls) -> object:
25
- kwargs = {}
26
- for prop in cls.PROPS:
27
- value = os.environ.get(cls.get_key(prop))
28
- kwargs[prop] = value if value is not None else ""
29
- return cls(**kwargs)
32
+ return cls(**cls.get_kwargs())
@@ -18,13 +18,14 @@ class Logger:
18
18
  def get_logger(
19
19
  cls,
20
20
  name: str,
21
- logging_level: str
21
+ logging_level: str | None
22
22
  ) -> logging.Logger:
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()
26
26
  logger = logging.getLogger(_id)
27
- if logging_level.lower() in cls._LOGGING_LEVELS:
27
+ is_logging_level_str = isinstance(logging_level, str)
28
+ if is_logging_level_str and logging_level.lower() in cls._LOGGING_LEVELS:
28
29
  logger.setLevel(cls._LOGGING_LEVELS[logging_level.lower()])
29
30
  else:
30
31
  logger.setLevel(cls._DEFAULT_LEVEL)
@@ -9,17 +9,17 @@ class NETHelper:
9
9
  @classmethod
10
10
  def set(
11
11
  cls,
12
- action: str = "",
13
- logging_level: str = "",
14
- target_username: str = "",
15
- target_address: str = "",
16
- target_port: str = "",
17
- logon_username: str = "",
18
- reconcile_username: str = "",
19
- target_password: str = "",
20
- logon_password: str = "",
21
- reconcile_password: str = "",
22
- target_new_password: str = ""
12
+ action: str | None = None,
13
+ logging_level: str | None = None,
14
+ target_username: str | None = None,
15
+ target_address: str | None = None,
16
+ target_port: str | None = None,
17
+ logon_username: str | None = None,
18
+ reconcile_username: str | None = None,
19
+ target_password: str | None = None,
20
+ logon_password: str | None = None,
21
+ reconcile_password: str | None = None,
22
+ target_new_password: str | None = None
23
23
  ) -> None:
24
24
  if Crypto.ENABLED:
25
25
  target_password = Crypto.encrypt(target_password)
@@ -53,7 +53,8 @@ class NETHelper:
53
53
  target_new_password
54
54
  )
55
55
  for i, key in enumerate(keys):
56
- os.environ.update({key: values[i]})
56
+ if values[i] is not None:
57
+ os.environ.update({key: values[i]})
57
58
 
58
59
  @classmethod
59
60
  def get(cls) -> Python4CPM:
@@ -3,7 +3,6 @@ import atexit
3
3
  import logging
4
4
  from python4cpm.secret import Secret
5
5
  from python4cpm.args import Args
6
- from python4cpm.crypto import Crypto
7
6
  from python4cpm.logger import Logger
8
7
  from python4cpm.accounts import TargetAccount, LogonAccount, ReconcileAccount
9
8
 
@@ -65,20 +64,18 @@ class Python4CPM:
65
64
  if self._args.action not in self._VALID_ACTIONS:
66
65
  self._logger.warning(f"Unkonwn action -> '{self._args.action}'")
67
66
 
68
- def _log_obj(self, obj: object) -> None:
69
- for key, value in vars(obj).items():
70
- _key = f"{obj.__class__.__name__}.{key.strip('_')}"
71
- if value:
72
- if not isinstance(value, Secret):
73
- logging_value = f"'{value}'"
74
- else:
75
- if Crypto.ENABLED is True:
76
- logging_value = "[ENCRYPTED]"
67
+ def _log_obj(self, obj: object | None) -> None:
68
+ if obj is not None:
69
+ for key, value in vars(obj).items():
70
+ _key = f"{obj.__class__.__name__}.{key.removeprefix('_')}"
71
+ if value is not None:
72
+ if not isinstance(value, Secret):
73
+ logging_value = f"'{value}'"
77
74
  else:
78
- logging_value = "[SET]"
79
- else:
80
- logging_value = "[NOT SET]"
81
- self._logger.debug(f"{_key} -> {logging_value}")
75
+ logging_value = str(value)
76
+ else:
77
+ logging_value = "[NOT SET]"
78
+ self._logger.debug(f"{_key} -> {logging_value}")
82
79
 
83
80
  def close_fail(self, unrecoverable: bool = False) -> None:
84
81
  if unrecoverable is False:
@@ -18,7 +18,7 @@ class Python4CPMHandler(ABC, Python4CPM):
18
18
  if action is not None:
19
19
  action()
20
20
  else:
21
- raise ValueError(f"Unknown action: {self._args.action}")
21
+ raise ValueError(f"Unknown action: '{self._args.action}'")
22
22
 
23
23
  @abstractmethod
24
24
  def verify(self) -> None:
@@ -0,0 +1,24 @@
1
+ from python4cpm.crypto import Crypto
2
+
3
+
4
+ class Secret:
5
+ def __init__(self, secret: str) -> None:
6
+ self._secret = secret
7
+
8
+ @classmethod
9
+ def from_env_var(cls, secret: str | None) -> object | None:
10
+ if secret is not None:
11
+ return cls(secret)
12
+ return None
13
+
14
+ def __str__(self) -> str:
15
+ if Crypto.ENABLED:
16
+ return "[ENCRYPTED]"
17
+ else:
18
+ return "[SET]"
19
+
20
+ def get(self) -> str:
21
+ if Crypto.ENABLED:
22
+ return Crypto.decrypt(self._secret)
23
+ else:
24
+ return self._secret
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python4cpm
3
- Version: 1.1.2
3
+ Version: 1.1.3
4
4
  Summary: Python for CPM
5
5
  Author-email: Gonzalo Atienza Rela <gonatienza@gmail.com>
6
6
  License-Expression: MIT
@@ -67,7 +67,7 @@ This platform allows you to duplicate it multiple times, simply changing its set
67
67
  from python4cpm import Python4CPMHandler
68
68
 
69
69
 
70
- class MyRotator(Python4CPMHandler): # create a subclass for the Handler
70
+ class MyRotator(Python4CPMHandler):
71
71
  """
72
72
  These are the usable properties and methods from Python4CPMHandler:
73
73
 
@@ -123,64 +123,33 @@ class MyRotator(Python4CPMHandler): # create a subclass for the Handler
123
123
  When calling a signal sys.exit is invoked and the script is terminated.
124
124
  If no signal is called, and the script finishes without any exception,
125
125
  it will behave like p4cpm.close_fail(unrecoverable=True) and log an error message.
126
+
126
127
  =============================
128
+ REQUIRED METHODS
127
129
  =============================
130
+ verify(), logon(), change(), prereconcile(), reconcile()
128
131
  """
129
132
 
130
- # =============================
131
- # REQUIRED METHODS (MUST DEFINE)
132
- # =============================
133
- # verify(), logon(), change(), prereconcile(), reconcile()
134
-
135
133
  def verify(self):
136
- self._verify()
137
- self.log_info("verification successful")
134
+ # TODO: use account objects for your logic
138
135
  self.close_success()
139
136
 
140
137
  def logon(self):
138
+ # TODO: use account objects for your logic
141
139
  self.close_success()
142
140
 
143
141
  def change(self):
144
- self._change()
145
- self.log_error("something went wrong")
146
- self.close_fail()
142
+ # TODO: use account objects for your logic
143
+ self.close_success()
147
144
 
148
145
  def prereconcile(self):
149
- self._verify(from_reconcile=True)
146
+ # TODO: use account objects for your logic
150
147
  self.close_success()
151
148
 
152
149
  def reconcile(self):
153
- self._change(from_reconcile=True)
150
+ # TODO: use account objects for your logic
154
151
  self.close_success()
155
152
 
156
- def _verify(self, from_reconcile=False):
157
- if from_reconcile is False:
158
- pass
159
- # TODO: use account objects for your logic
160
- else:
161
- pass
162
- # TODO: use account objects for your logic
163
- result = True
164
- if result is True:
165
- self.log_info("verification successful")
166
- else:
167
- self.log_error("something went wrong")
168
- self.close_fail()
169
-
170
- def _change(self, from_reconcile=False):
171
- if from_reconcile is False:
172
- pass
173
- # TODO: use account objects for your logic
174
- else:
175
- pass
176
- # TODO: use account objects for your logic
177
- result = True
178
- if result is True:
179
- self.log_info("rotation successful")
180
- else:
181
- self.log_error("something went wrong")
182
- self.close_fail()
183
-
184
153
 
185
154
  if __name__ == "__main__":
186
155
  MyRotator().run() # initializes the class and calls the action that was requested from CPM/SRS.
@@ -193,9 +162,9 @@ When doing `verify`, `change` or `reconcile` from Privilege Cloud/PVWA:
193
162
  - 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)`.
194
163
  3. Reconcile -> the sciprt will be executed twice, running first the `MyRotator.prereconcile()` method and secondly the `MyRotator.reconcile()` method.
195
164
  - 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)`.
196
- 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.target_account.new_password.get()` will always return an empty string.
197
- 5. If a logon account is not linked, `self.logon_account.username` and `self.logon_account.password.get()` will return empty strings.
198
- 6. If a reconcile account is not linked, `self.reconcile_account.username` and `self.reconcile_account.password.get()` will return empty strings.
165
+ 4. When calling `MyRotator.verify()`, `MyRotator.logon()` or `MyRotator.prereconcile()`: `self.target_account.new_password` will always return `None`.
166
+ 5. If a logon account is not linked, `self.logon_account` will return `None`.
167
+ 6. If a reconcile account is not linked, `self.reconcile_account` will return `None`.
199
168
  7. The python `Logger` places its logs in the `Logs/ThirdParty` directory. The filename will be based on the name of the subclass created (e.g., `MyRotator`).
200
169
 
201
170
 
@@ -210,7 +179,7 @@ As with any python venv, you can install dependencies in your venv.
210
179
 
211
180
  ## Dev Helper:
212
181
 
213
- For dev purposes, `NETHelper` is a companion helper to test your scripts before shipping to CPM/SRS. It simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin creates the environment context for the python module.
182
+ For dev purposes, `NETHelper` is a companion helper to test your scripts without CPM/SRS. It simplifies the instantiation of the `Python4CPM` or `Python4CPMHandler` objects by simulating how the plugin creates the environment context for the python module.
214
183
 
215
184
  **Note**: As CPM and the SRS management agent run in Windows, the plugin was built to encrypt secrets using DPAPI (a windows only library). For dev purposes in Linux/Mac dev workstations, those secrets put in the environment context by `NETHelper` will be in plaintext. In windows dev workstations, `NETHelper` encrypts the secrets as the .NET plugin does. This is informational only, **the module will use its encryption/decryption capabilities automatically based on the platform** it is running on and you do not have to do anything specific to enable it.
216
185
 
@@ -223,7 +192,7 @@ from python4cpm import NETHelper, Python4CPM, Python4CPMHandler
223
192
  from getpass import getpass
224
193
 
225
194
  # 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
195
+ # You may set to None any argument that does not apply or simply leaving it to its default None value.
227
196
  target_password = getpass("password: ") # password from account
228
197
  logon_password = getpass("logon_password: ") # password from linked logon account
229
198
  reconcile_password = getpass("reconcile_password: ") # password from linked reconcile account
@@ -271,5 +240,4 @@ MyRotator().run()
271
240
 
272
241
  - Remove the import of `NETHelper`.
273
242
  - Remove the `NETHelper.set()` call.
274
- - If applicable, change the definition of `p4cpm` from `p4cpm = NETHelper.get()` to `p4cpm = Python4CPM("MyApp")`.
275
243
  - Remove any secrets prompting or interactive interruptions.
@@ -1,15 +0,0 @@
1
- from python4cpm.crypto import Crypto
2
-
3
-
4
- class Secret:
5
- def __init__(self, secret: str) -> None:
6
- self._secret = secret
7
-
8
- def __bool__(self) -> bool:
9
- return bool(self._secret)
10
-
11
- def get(self) -> str:
12
- if Crypto.ENABLED and self._secret:
13
- return Crypto.decrypt(self._secret)
14
- else:
15
- return self._secret
File without changes
File without changes