Skip to content

Commit 1afa889

Browse files
Feature/incoming changes (#445)
* fix: incoming change * documentation: update chnagelog * feature: add version check * feature: update test configuration (publish parameter) * feature: add publish parameter (new in 10.0.8.0) * fix: format -> f-strings, remove explicit boolean comparisons * fix: format -> f-strings, remove explicit boolean comparisons * feature: set multiple runtime tuning parameters in 1 call * feature: json_equals function (wrapper around comparing 2 strings from json.dumps) * feature: use new json_equals function * documentation: update changelog * fix: new parameter. Incomplete. * fix: update smtp server connection * feature: export keytab kerberos * feature: test export keytab kerberos * documentation: update changelog * fix: format -> f-strings, remove explicit boolean comparisons * fix: format -> f-strings, remove explicit boolean comparisons * feature: get all audit configurations * documentation: update changelog * fix: small updates * fix: network ssl database (hsm) update * fix: trivial * documentation: version bump * documentation: update version * build: add readthedocs to gitignore
1 parent 221b871 commit 1afa889

File tree

23 files changed

+611
-176
lines changed

23 files changed

+611
-176
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,6 @@ ENV/
9898

9999
# Test Script
100100
test.py
101+
102+
# Read the docs
103+
_readthedocs/

conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ def iviaServer():
2222
# Create an ISAM appliance with above credential
2323
isam_server = ISAMAppliance(hostname=_host, user=u, lmi_port=_port)
2424
yield isam_server
25-
returnValue = ibmsecurity.isam.appliance.commit(isamAppliance=isam_server)
26-
print('\nCommit result')
25+
returnValue = ibmsecurity.isam.appliance.commit(isamAppliance=isam_server, publish=True)
26+
print('\nCommit result and publish')
2727
print( returnValue )
2828
print('\n')
2929
return returnValue

docs/changelog.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Latest
44

5+
## 2025.6.3.0
6+
57
- feature: base/management_authentication.py - type federation
68
- build: test setup
79
- feature: web/reverse_proxy/oauth_configuration.py - add new parameters in 10.0.8
@@ -10,6 +12,14 @@
1012
- fix: base/admin_ssh_keys.py - Ignore error when same ssh key exists under different name
1113
- pylint: change format() to f-strings
1214
- feature: base/tracing.py - Get tracing configuration (new in 10.0.8)
15+
- fix: add ignore_errors to cli.py - incoming change
16+
- feature: add publish parameter (for use in containers) (new in 10.0.8)
17+
- feature: new function in tools `json_equals`
18+
- feature: tuning_parameters.py - set multiple runtime parameters in 1 call
19+
- fix: new parameter includeIssInAuthResp for oidc definitions (new in 10.0.8)
20+
- feature: export a kerberos keytab file (new in 10.0.8)
21+
- feature: get all audit configurations (new in 10.0.8)
22+
- feature: update network certificate database (WIP)
1323

1424
## 2025.3.28.0
1525

ibmsecurity/isam/aac/api_protection/definitions.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,12 @@ def add(isamAppliance, name, description="", accessPolicyName=None, grantTypes=[
138138
if tools.version_compare(isamAppliance.facts["version"], "9.0.5.0") < 0:
139139
warnings.append(
140140
f"Appliance at version: {isamAppliance.facts['version']}, issueSecret: {json_data['oidc']['issueSecret']} is not supported. Needs 9.0.5.0 or higher. Ignoring issueSecret for this call.")
141-
del json_data['oidc']['issueSecret']
141+
json_data['oidc'].pop('issueSecret', None)
142+
if 'includeIssInAuthResp' in json_data['oidc']:
143+
if tools.version_compare(isamAppliance.facts["version"], "10.0.8.0") < 0:
144+
warnings.append(
145+
f"Appliance at version: {isamAppliance.facts['version']}, issueSecret: {json_data['oidc']['includeIssInAuthResp']} is not supported. Needs 10.0.8.0 or higher. Ignoring includeIssInAuthResp for this call.")
146+
json_data['oidc'].pop('includeIssInAuthResp', None)
142147

143148
return isamAppliance.invoke_post(
144149
"Create an API protection definition", uri,
@@ -234,16 +239,12 @@ def update(isamAppliance, name, description="", accessPolicyName=None, grantType
234239
oidc['attributeSources'] = _map_oidc_attributeSources(isamAppliance, oidc['attributeSources'], check_mode, force)
235240
json_data["oidc"] = oidc
236241

237-
if force is not True:
242+
if not force:
238243

239-
if 'datecreated' in ret_obj['data']:
240-
del ret_obj['data']['datecreated']
241-
if 'id' in ret_obj['data']:
242-
del ret_obj['data']['id']
243-
if 'lastmodified' in ret_obj['data']:
244-
del ret_obj['data']['lastmodified']
245-
if 'mappingRules' in ret_obj['data']:
246-
del ret_obj['data']['mappingRules']
244+
ret_obj['data'].pop('datecreated', None)
245+
ret_obj['data'].pop('id', None)
246+
ret_obj['data'].pop('lastmodified', None)
247+
ret_obj['data'].pop('mappingRules', None)
247248

248249
# Inspecting oidcConfig and remove missing or None attributes in returned object
249250
if oidc is not None and 'oidc' in ret_obj['data']:

ibmsecurity/isam/aac/risk_profiles.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def _check(isamAppliance, name, active, description, attributes, predefined):
160160
logger.warning("Risk Profile not found, returning no update required.")
161161
return None, update_required, json_data
162162
else:
163-
if ret_obj['data']['predefined'] is True:
163+
if ret_obj['data']['predefined']:
164164
logger.warning("Predefined Risk Profiles can NOT be updated, returning no update required.")
165165
return ret_obj['data']['id'], update_required, {}
166166
else:
@@ -181,11 +181,7 @@ def _check(isamAppliance, name, active, description, attributes, predefined):
181181
id = ret_obj['data']['id']
182182
del ret_obj['data']['id']
183183

184-
sorted_json_data = json.dumps(json_data, skipkeys=True, sort_keys=True)
185-
logger.debug("Sorted input: {0}".format(sorted_json_data))
186-
sorted_ret_obj = json.dumps(ret_obj['data'], skipkeys=True, sort_keys=True)
187-
logger.debug("Sorted existing data: {0}".format(sorted_ret_obj))
188-
if sorted_ret_obj != sorted_json_data:
184+
if not tools.json_equals(ret_obj, json_data):
189185
logger.info("Changes detected, update needed.")
190186
update_required = True
191187

ibmsecurity/isam/aac/scim/scim.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,15 +282,15 @@ def set_all(isamAppliance, settings, check_mode=False, force=False):
282282
"""
283283
if settings is None or settings == '':
284284
return isamAppliance.create_return_object(
285-
warnings="Need to pass content for scim configuration")
285+
warnings=["Need to pass content for scim configuration"])
286286
else:
287287
# Feature: Converting python string to dict (if required)
288288
# Attention: JSON strings must use " quotes according to RFC 8259
289289
# Example: '{"a":1, "b": 2, "c": 3}'
290290
if isinstance(settings, str):
291291
settings = json.loads(settings)
292-
if force is True or _check(isamAppliance, settings) is False:
293-
if check_mode is True:
292+
if force or not _check(isamAppliance, settings):
293+
if check_mode:
294294
return isamAppliance.create_return_object(changed=True)
295295
else:
296296
return isamAppliance.invoke_put(

ibmsecurity/isam/aac/server_connections/smtp.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,10 @@ def update(isamAppliance, name, connection, description='', locked=False, connec
113113
warnings.append("Request made to ignore password for idempotency check.")
114114
connection.pop('password', None)
115115

116-
sorted_ret_obj = tools.json_sort(ret_obj['data'])
117-
sorted_json_data = tools.json_sort(json_data)
118-
logger.debug(f"Sorted Existing Data:{sorted_ret_obj}")
119-
logger.debug(f"Sorted Desired Data:{sorted_json_data}")
120-
121-
if sorted_ret_obj != sorted_json_data:
116+
if not tools.json_equals(ret_obj, json_data):
122117
needs_update = True
123118

124-
if force is True or needs_update is True:
119+
if force or needs_update:
125120
if check_mode is True:
126121
return isamAppliance.create_return_object(changed=True, warnings=warnings)
127122
else:

ibmsecurity/isam/appliance.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def reboot(isamAppliance, check_mode=False, force=False):
1111
"""
1212
Restart the appliance
1313
"""
14-
if check_mode is True:
14+
if check_mode:
1515
return isamAppliance.create_return_object(changed=True)
1616
else:
1717
return isamAppliance.invoke_post("Restart the appliance",
@@ -23,7 +23,7 @@ def shutdown(isamAppliance, check_mode=False, force=False):
2323
"""
2424
Shutdown the appliance
2525
"""
26-
if check_mode is True:
26+
if check_mode:
2727
return isamAppliance.create_return_object(changed=True)
2828
else:
2929
return isamAppliance.invoke_post("Shutting down appliance",
@@ -56,15 +56,23 @@ def _changes_available(isamAppliance):
5656
return False
5757

5858

59-
def commit(isamAppliance, check_mode=False, force=False):
59+
def commit(isamAppliance, publish=False, check_mode=False, force=False):
6060
"""
6161
Commit the current pending changes.
6262
"""
63-
if force is True or _changes_available(isamAppliance) is True:
64-
if check_mode is True:
63+
if force or _changes_available(isamAppliance):
64+
if check_mode:
6565
return isamAppliance.create_return_object(changed=True)
6666
else:
67-
return isamAppliance.invoke_put("Committing the changes",
67+
iviaVersion = isamAppliance.facts['version']
68+
if publish and ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.8.0") >= 0:
69+
logger.debug("Commit: commit and publish")
70+
return isamAppliance.invoke_put("Committing the changes (containers)",
71+
f"/isam/pending_changes?publish={publish}",
72+
{})
73+
else:
74+
logger.debug("Commit: simple commit")
75+
return isamAppliance.invoke_put("Committing the changes",
6876
"/isam/pending_changes",
6977
{})
7078

@@ -79,8 +87,8 @@ def commit_and_restart(isamAppliance, check_mode=False, force=False):
7987
:param force:
8088
:return:
8189
"""
82-
if force is True or _changes_available(isamAppliance) is True:
83-
if check_mode is True:
90+
if force or _changes_available(isamAppliance):
91+
if check_mode:
8492
return isamAppliance.create_return_object(changed=True)
8593
else:
8694
return isamAppliance.invoke_post("Commit and Restart",
@@ -127,11 +135,10 @@ def reboot_and_wait(isamAppliance, wait_time=300, check_freq=5, check_mode=False
127135
time.sleep(check_freq)
128136
sec += check_freq
129137
logger.debug(
130-
"Server is not responding yet. Waited for {0} secs, next check in {1} secs.".format(sec,
131-
check_freq))
138+
f"Server is not responding yet. Waited for {sec} secs, next check in {check_freq} secs.")
132139

133140
if sec >= wait_time:
134-
warnings.append("Server reboot not detected or completed, exiting... after {0} seconds".format(sec))
141+
warnings.append(f"Server reboot not detected or completed, exiting... after {sec} seconds")
135142
break
136143

137144
return isamAppliance.create_return_object(warnings=warnings)
@@ -148,7 +155,7 @@ def commit_and_restart_and_wait(isamAppliance, wait_time=300, check_freq=5, chec
148155
:return:
149156
"""
150157
warnings = []
151-
if check_mode is True:
158+
if check_mode:
152159
return isamAppliance.create_return_object(changed=True)
153160
else:
154161
lmi = ibmsecurity.isam.base.lmi.get(isamAppliance, check_mode=check_mode, force=force)
@@ -171,12 +178,11 @@ def commit_and_restart_and_wait(isamAppliance, wait_time=300, check_freq=5, chec
171178
else:
172179
time.sleep(check_freq)
173180
sec += check_freq
174-
logger.debug("LMI is not responding yet. Waited for {0} secs, next check in {1} secs.".format(sec,
175-
check_freq))
181+
logger.debug(f"LMI is not responding yet. Waited for {sec} secs, next check in {check_freq} secs.")
176182

177183
if sec >= wait_time:
178184
warnings.append(
179-
"The LMI restart not detected or completed, exiting... after {0} seconds".format(sec))
185+
f"The LMI restart not detected or completed, exiting... after {sec} seconds")
180186
break
181187

182188
return isamAppliance.create_return_object(warnings=warnings)
@@ -186,7 +192,7 @@ def rollback(isamAppliance, check_mode=False, force=False):
186192
"""
187193
Rollback the current pending changes.
188194
"""
189-
if force is True or _changes_available(isamAppliance) is True:
195+
if force or _changes_available(isamAppliance):
190196
if check_mode is True:
191197
return isamAppliance.create_return_object(changed=True)
192198
else:

ibmsecurity/isam/base/admin.py

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
import ibmsecurity.utilities.tools
2+
import ibmsecurity.utilities.tools as _tools
33
import json
44

55
logger = logging.getLogger(__name__)
@@ -29,13 +29,13 @@ def set_pw(isamAppliance, oldPassword, newPassword, sessionTimeout="30", httpsPo
2929
"sessionTimeout": sessionTimeout
3030
}
3131
if httpsPort is not None:
32-
if ibmsecurity.utilities.tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
32+
if _tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
3333
warnings.append(
3434
"Appliance at version: {0}, httpsPort not supported. Needs 9.0.1.0 or higher. Ignoring httpsPort for this call.")
3535
else:
3636
json_data['httpsPort'] = httpsPort
3737
else:
38-
if ibmsecurity.utilities.tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
38+
if _tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
3939
pass # Can safely ignore httpsPort
4040
else:
4141
warnings.append("Default httpsPort of 443 will be set on the appliance.")
@@ -168,67 +168,56 @@ def _check(isamAppliance,
168168
json_data["confirmPassword"] = v
169169
if k in ["minHeapSize", "maxHeapSize", "httpPort", "httpsPort", "minThreads", "maxThreads", "maxPoolSize", "maxFiles", "maxFileSize", "sshdPort", "sessionCachePurge", "sessionInactivityTimeout", "sshdClientAliveInterval", "baSessionTimeout"]:
170170
# int values
171-
if k == "sshdPort" and ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.3.0") < 0:
171+
if k == "sshdPort" and _tools.version_compare(iviaVersion, "9.0.3.0") < 0:
172172
warnings.append(f"Appliance at version: {iviaVersion}, sshdPort: {v} is not supported. Needs 9.0.3.0 or higher. Ignoring sshdPort for this call.")
173173
continue
174-
if k in ["sessionCachePurge", "sessionInactivityTimeout", "sshdClientAliveInterval"] and ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.5.0") < 0:
174+
if k in ["sessionCachePurge", "sessionInactivityTimeout", "sshdClientAliveInterval"] and _tools.version_compare(iviaVersion, "9.0.5.0") < 0:
175175
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 9.0.5.0 or higher. Ignoring.")
176176
continue
177-
if k in ["baSessionTimeout"] and ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.2.0") < 0:
177+
if k in ["baSessionTimeout"] and _tools.version_compare(iviaVersion, "10.0.2.0") < 0:
178178
warnings.append(
179179
f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.2.0 or higher. Ignoring.")
180180
continue
181181
json_data[k] = int(v)
182182
continue
183183
if k == "enableSSLv3":
184-
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.3.0") >= 0:
184+
if _tools.version_compare(iviaVersion, "10.0.3.0") >= 0:
185185
warnings.append(f"Appliance at version: {iviaVersion}, enableSSLv3: {v} is not supported. Needs max. 10.0.2.0. Ignoring for this call.")
186186
continue
187187
if k == "consoleLogLevel":
188188
if 'consoleLogLevel' in ret_obj['data'] and ret_obj['data']['consoleLogLevel'] == 'OFF':
189189
ret_obj['data']['consoleLogLevel'] = 'OFF'
190190
if k == "enabledTLS":
191-
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.4.0") < 0:
191+
if _tools.version_compare(iviaVersion, "9.0.4.0") < 0:
192192
warnings.append(f"Appliance at version: {iviaVersion}, enabledTLS: {v} is not supported. Needs 9.0.4.0 or higher. Ignoring enabledTLS for this call.")
193193
continue
194194
if k in ["swapFileSize", "httpProxy"]:
195-
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.5.0") < 0:
195+
if _tools.version_compare(iviaVersion, "9.0.5.0") < 0:
196196
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 9.0.5.0 or higher. Ignoring.")
197197
continue
198198
if k in ["enabledServerProtocols", "loginHeader", "loginMessage", "pendingChangesLifetime", "httpsProxy"]:
199-
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.7.0") < 0:
199+
if _tools.version_compare(iviaVersion, "9.0.7.0") < 0:
200200
warnings.append(
201201
f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 9.0.7.0 or higher. Ignoring.")
202202
continue
203203
if k in ["accessLogFormat"]:
204-
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.0.0") < 0:
204+
if _tools.version_compare(iviaVersion, "10.0.0.0") < 0:
205205
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.0.0 or higher. Ignoring.")
206206
continue
207207
if k in ["lmiMessageTimeout", "validVerifyDomains"]:
208-
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.2.0") < 0:
208+
if _tools.version_compare(iviaVersion, "10.0.2.0") < 0:
209209
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.0.0 or higher. Ignoring.")
210210
continue
211211
if k == "jsVersion":
212-
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.9.0") < 0:
212+
if _tools.version_compare(iviaVersion, "10.0.9.0") < 0:
213213
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.9.0 or higher. Ignoring.")
214214
continue
215215

216216
# Add to the json_data dict
217217
json_data[k] = v
218218

219-
# Remove keys from ret_obj that are not in json_data
220-
fCurrentEntries = {k: v for k, v in ret_obj["data"].items() if k in json_data.keys()}
221-
#
222-
sorted_ret_obj = json.dumps(fCurrentEntries, skipkeys=True, sort_keys=True)
223-
sorted_json_data = json.dumps(json_data, skipkeys=True, sort_keys=True)
224-
logger.debug(f"Sorted Existing Data:\n\n{sorted_ret_obj}")
225-
logger.debug(f"Sorted Desired Data:\n\n{sorted_json_data}")
226-
if sorted_ret_obj != sorted_json_data:
219+
if not _tools.json_equals(ret_obj, json_data):
227220
logger.debug("Admin Settings are found to be different. See above JSON for difference.")
228-
# Ensure users know how REST API handles httpsPort default value - I think everybody should know this by now
229-
# if json_data.get("httpsPort", "") == "" and ibmsecurity.utilities.tools.version_compare(isamAppliance.facts['version'],
230-
# "9.0.1.0") >= 0:
231-
# warnings.append("Default httpsPort of 443 will be set on the appliance.")
232221
return True, warnings, json_data
233222
else: # No changes required
234223
return False, warnings, json_data
@@ -241,4 +230,4 @@ def compare(isamAppliance1, isamAppliance2):
241230
ret_obj1 = get(isamAppliance1)
242231
ret_obj2 = get(isamAppliance2)
243232

244-
return ibmsecurity.utilities.tools.json_compare(ret_obj1, ret_obj2)
233+
return _tools.json_compare(ret_obj1, ret_obj2)

ibmsecurity/isam/base/audit/configuration.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@
1414
requires_version = None
1515

1616

17-
def get(isamAppliance, check_mode=False, force=False):
17+
def get(isamAppliance, id=None, check_mode=False, force=False):
1818
"""
1919
Retrieve audit configuration
20+
id is optional
2021
"""
21-
return isamAppliance.invoke_get("Retrieve audit configuration", uri, requires_modules=requires_modules,
22+
if id is None:
23+
return isamAppliance.invoke_get("Retrieve current audit configuration", uri, requires_modules=requires_modules,
2224
requires_version=requires_version)
25+
else:
26+
return isamAppliance.invoke_get("Retrieve {id} audit configuration",
27+
f"{uri}/{id}", requires_modules=requires_modules,
28+
requires_version=requires_version)
2329

2430

2531
def set(isamAppliance, id, config, enabled=True, type='Syslog', verbose=True, check_mode=False, force=False, use_json=False, components=None):

0 commit comments

Comments
 (0)