Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
664e3e5
fix: incoming change
tombosmansibm Jun 2, 2025
426face
documentation: update chnagelog
tombosmansibm Jun 2, 2025
d94d559
feature: add version check
tombosmansibm Jun 2, 2025
639781b
feature: update test configuration (publish parameter)
tombosmansibm Jun 2, 2025
781945a
feature: add publish parameter (new in 10.0.8.0)
tombosmansibm Jun 2, 2025
382217f
fix: format -> f-strings, remove explicit boolean comparisons
tombosmansibm Jun 2, 2025
2ec18fc
fix: format -> f-strings, remove explicit boolean comparisons
tombosmansibm Jun 2, 2025
9a69ec6
feature: set multiple runtime tuning parameters in 1 call
tombosmansibm Jun 2, 2025
0b3a0c0
feature: json_equals function (wrapper around comparing 2 strings fro…
tombosmansibm Jun 2, 2025
23104e2
feature: use new json_equals function
tombosmansibm Jun 2, 2025
f676b7d
documentation: update changelog
tombosmansibm Jun 2, 2025
8c99568
fix: new parameter. Incomplete.
tombosmansibm Jun 2, 2025
e5bcfb2
fix: update smtp server connection
tombosmansibm Jun 2, 2025
c71a39f
feature: export keytab kerberos
tombosmansibm Jun 2, 2025
c521be9
feature: test export keytab kerberos
tombosmansibm Jun 2, 2025
181b455
documentation: update changelog
tombosmansibm Jun 2, 2025
b78fb8d
fix: format -> f-strings, remove explicit boolean comparisons
tombosmansibm Jun 2, 2025
09816fe
fix: format -> f-strings, remove explicit boolean comparisons
tombosmansibm Jun 2, 2025
f978f54
feature: get all audit configurations
tombosmansibm Jun 2, 2025
8d104bd
documentation: update changelog
tombosmansibm Jun 2, 2025
ca73da6
fix: small updates
tombosmansibm Jun 2, 2025
8ea675c
fix: network ssl database (hsm) update
tombosmansibm Jun 2, 2025
2f75fd1
fix: trivial
tombosmansibm Jun 3, 2025
59c5772
documentation: version bump
tombosmansibm Jun 3, 2025
a91264b
documentation: update version
tombosmansibm Jun 3, 2025
5c600a8
build: add readthedocs to gitignore
tombosmansibm Jun 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,6 @@ ENV/

# Test Script
test.py

# Read the docs
_readthedocs/
4 changes: 2 additions & 2 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def iviaServer():
# Create an ISAM appliance with above credential
isam_server = ISAMAppliance(hostname=_host, user=u, lmi_port=_port)
yield isam_server
returnValue = ibmsecurity.isam.appliance.commit(isamAppliance=isam_server)
print('\nCommit result')
returnValue = ibmsecurity.isam.appliance.commit(isamAppliance=isam_server, publish=True)
print('\nCommit result and publish')
print( returnValue )
print('\n')
return returnValue
Expand Down
10 changes: 10 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Latest

## 2025.6.3.0

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

## 2025.3.28.0

Expand Down
21 changes: 11 additions & 10 deletions ibmsecurity/isam/aac/api_protection/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,12 @@ def add(isamAppliance, name, description="", accessPolicyName=None, grantTypes=[
if tools.version_compare(isamAppliance.facts["version"], "9.0.5.0") < 0:
warnings.append(
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.")
del json_data['oidc']['issueSecret']
json_data['oidc'].pop('issueSecret', None)
if 'includeIssInAuthResp' in json_data['oidc']:
if tools.version_compare(isamAppliance.facts["version"], "10.0.8.0") < 0:
warnings.append(
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.")
json_data['oidc'].pop('includeIssInAuthResp', None)

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

if force is not True:
if not force:

if 'datecreated' in ret_obj['data']:
del ret_obj['data']['datecreated']
if 'id' in ret_obj['data']:
del ret_obj['data']['id']
if 'lastmodified' in ret_obj['data']:
del ret_obj['data']['lastmodified']
if 'mappingRules' in ret_obj['data']:
del ret_obj['data']['mappingRules']
ret_obj['data'].pop('datecreated', None)
ret_obj['data'].pop('id', None)
ret_obj['data'].pop('lastmodified', None)
ret_obj['data'].pop('mappingRules', None)

# Inspecting oidcConfig and remove missing or None attributes in returned object
if oidc is not None and 'oidc' in ret_obj['data']:
Expand Down
8 changes: 2 additions & 6 deletions ibmsecurity/isam/aac/risk_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def _check(isamAppliance, name, active, description, attributes, predefined):
logger.warning("Risk Profile not found, returning no update required.")
return None, update_required, json_data
else:
if ret_obj['data']['predefined'] is True:
if ret_obj['data']['predefined']:
logger.warning("Predefined Risk Profiles can NOT be updated, returning no update required.")
return ret_obj['data']['id'], update_required, {}
else:
Expand All @@ -181,11 +181,7 @@ def _check(isamAppliance, name, active, description, attributes, predefined):
id = ret_obj['data']['id']
del ret_obj['data']['id']

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

Expand Down
6 changes: 3 additions & 3 deletions ibmsecurity/isam/aac/scim/scim.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,15 @@ def set_all(isamAppliance, settings, check_mode=False, force=False):
"""
if settings is None or settings == '':
return isamAppliance.create_return_object(
warnings="Need to pass content for scim configuration")
warnings=["Need to pass content for scim configuration"])
else:
# Feature: Converting python string to dict (if required)
# Attention: JSON strings must use " quotes according to RFC 8259
# Example: '{"a":1, "b": 2, "c": 3}'
if isinstance(settings, str):
settings = json.loads(settings)
if force is True or _check(isamAppliance, settings) is False:
if check_mode is True:
if force or not _check(isamAppliance, settings):
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_put(
Expand Down
9 changes: 2 additions & 7 deletions ibmsecurity/isam/aac/server_connections/smtp.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,10 @@ def update(isamAppliance, name, connection, description='', locked=False, connec
warnings.append("Request made to ignore password for idempotency check.")
connection.pop('password', None)

sorted_ret_obj = tools.json_sort(ret_obj['data'])
sorted_json_data = tools.json_sort(json_data)
logger.debug(f"Sorted Existing Data:{sorted_ret_obj}")
logger.debug(f"Sorted Desired Data:{sorted_json_data}")

if sorted_ret_obj != sorted_json_data:
if not tools.json_equals(ret_obj, json_data):
needs_update = True

if force is True or needs_update is True:
if force or needs_update:
if check_mode is True:
return isamAppliance.create_return_object(changed=True, warnings=warnings)
else:
Expand Down
38 changes: 22 additions & 16 deletions ibmsecurity/isam/appliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def reboot(isamAppliance, check_mode=False, force=False):
"""
Restart the appliance
"""
if check_mode is True:
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_post("Restart the appliance",
Expand All @@ -23,7 +23,7 @@ def shutdown(isamAppliance, check_mode=False, force=False):
"""
Shutdown the appliance
"""
if check_mode is True:
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_post("Shutting down appliance",
Expand Down Expand Up @@ -56,15 +56,23 @@ def _changes_available(isamAppliance):
return False


def commit(isamAppliance, check_mode=False, force=False):
def commit(isamAppliance, publish=False, check_mode=False, force=False):
"""
Commit the current pending changes.
"""
if force is True or _changes_available(isamAppliance) is True:
if check_mode is True:
if force or _changes_available(isamAppliance):
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_put("Committing the changes",
iviaVersion = isamAppliance.facts['version']
if publish and ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.8.0") >= 0:
logger.debug("Commit: commit and publish")
return isamAppliance.invoke_put("Committing the changes (containers)",
f"/isam/pending_changes?publish={publish}",
{})
else:
logger.debug("Commit: simple commit")
return isamAppliance.invoke_put("Committing the changes",
"/isam/pending_changes",
{})

Expand All @@ -79,8 +87,8 @@ def commit_and_restart(isamAppliance, check_mode=False, force=False):
:param force:
:return:
"""
if force is True or _changes_available(isamAppliance) is True:
if check_mode is True:
if force or _changes_available(isamAppliance):
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_post("Commit and Restart",
Expand Down Expand Up @@ -127,11 +135,10 @@ def reboot_and_wait(isamAppliance, wait_time=300, check_freq=5, check_mode=False
time.sleep(check_freq)
sec += check_freq
logger.debug(
"Server is not responding yet. Waited for {0} secs, next check in {1} secs.".format(sec,
check_freq))
f"Server is not responding yet. Waited for {sec} secs, next check in {check_freq} secs.")

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

return isamAppliance.create_return_object(warnings=warnings)
Expand All @@ -148,7 +155,7 @@ def commit_and_restart_and_wait(isamAppliance, wait_time=300, check_freq=5, chec
:return:
"""
warnings = []
if check_mode is True:
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
lmi = ibmsecurity.isam.base.lmi.get(isamAppliance, check_mode=check_mode, force=force)
Expand All @@ -171,12 +178,11 @@ def commit_and_restart_and_wait(isamAppliance, wait_time=300, check_freq=5, chec
else:
time.sleep(check_freq)
sec += check_freq
logger.debug("LMI is not responding yet. Waited for {0} secs, next check in {1} secs.".format(sec,
check_freq))
logger.debug(f"LMI is not responding yet. Waited for {sec} secs, next check in {check_freq} secs.")

if sec >= wait_time:
warnings.append(
"The LMI restart not detected or completed, exiting... after {0} seconds".format(sec))
f"The LMI restart not detected or completed, exiting... after {sec} seconds")
break

return isamAppliance.create_return_object(warnings=warnings)
Expand All @@ -186,7 +192,7 @@ def rollback(isamAppliance, check_mode=False, force=False):
"""
Rollback the current pending changes.
"""
if force is True or _changes_available(isamAppliance) is True:
if force or _changes_available(isamAppliance):
if check_mode is True:
return isamAppliance.create_return_object(changed=True)
else:
Expand Down
41 changes: 15 additions & 26 deletions ibmsecurity/isam/base/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
import ibmsecurity.utilities.tools
import ibmsecurity.utilities.tools as _tools
import json

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -29,13 +29,13 @@ def set_pw(isamAppliance, oldPassword, newPassword, sessionTimeout="30", httpsPo
"sessionTimeout": sessionTimeout
}
if httpsPort is not None:
if ibmsecurity.utilities.tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
if _tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
warnings.append(
"Appliance at version: {0}, httpsPort not supported. Needs 9.0.1.0 or higher. Ignoring httpsPort for this call.")
else:
json_data['httpsPort'] = httpsPort
else:
if ibmsecurity.utilities.tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
if _tools.version_compare(isamAppliance.facts['version'], "9.0.1.0") < 0:
pass # Can safely ignore httpsPort
else:
warnings.append("Default httpsPort of 443 will be set on the appliance.")
Expand Down Expand Up @@ -168,67 +168,56 @@ def _check(isamAppliance,
json_data["confirmPassword"] = v
if k in ["minHeapSize", "maxHeapSize", "httpPort", "httpsPort", "minThreads", "maxThreads", "maxPoolSize", "maxFiles", "maxFileSize", "sshdPort", "sessionCachePurge", "sessionInactivityTimeout", "sshdClientAliveInterval", "baSessionTimeout"]:
# int values
if k == "sshdPort" and ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.3.0") < 0:
if k == "sshdPort" and _tools.version_compare(iviaVersion, "9.0.3.0") < 0:
warnings.append(f"Appliance at version: {iviaVersion}, sshdPort: {v} is not supported. Needs 9.0.3.0 or higher. Ignoring sshdPort for this call.")
continue
if k in ["sessionCachePurge", "sessionInactivityTimeout", "sshdClientAliveInterval"] and ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.5.0") < 0:
if k in ["sessionCachePurge", "sessionInactivityTimeout", "sshdClientAliveInterval"] and _tools.version_compare(iviaVersion, "9.0.5.0") < 0:
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 9.0.5.0 or higher. Ignoring.")
continue
if k in ["baSessionTimeout"] and ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.2.0") < 0:
if k in ["baSessionTimeout"] and _tools.version_compare(iviaVersion, "10.0.2.0") < 0:
warnings.append(
f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.2.0 or higher. Ignoring.")
continue
json_data[k] = int(v)
continue
if k == "enableSSLv3":
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.3.0") >= 0:
if _tools.version_compare(iviaVersion, "10.0.3.0") >= 0:
warnings.append(f"Appliance at version: {iviaVersion}, enableSSLv3: {v} is not supported. Needs max. 10.0.2.0. Ignoring for this call.")
continue
if k == "consoleLogLevel":
if 'consoleLogLevel' in ret_obj['data'] and ret_obj['data']['consoleLogLevel'] == 'OFF':
ret_obj['data']['consoleLogLevel'] = 'OFF'
if k == "enabledTLS":
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.4.0") < 0:
if _tools.version_compare(iviaVersion, "9.0.4.0") < 0:
warnings.append(f"Appliance at version: {iviaVersion}, enabledTLS: {v} is not supported. Needs 9.0.4.0 or higher. Ignoring enabledTLS for this call.")
continue
if k in ["swapFileSize", "httpProxy"]:
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.5.0") < 0:
if _tools.version_compare(iviaVersion, "9.0.5.0") < 0:
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 9.0.5.0 or higher. Ignoring.")
continue
if k in ["enabledServerProtocols", "loginHeader", "loginMessage", "pendingChangesLifetime", "httpsProxy"]:
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "9.0.7.0") < 0:
if _tools.version_compare(iviaVersion, "9.0.7.0") < 0:
warnings.append(
f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 9.0.7.0 or higher. Ignoring.")
continue
if k in ["accessLogFormat"]:
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.0.0") < 0:
if _tools.version_compare(iviaVersion, "10.0.0.0") < 0:
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.0.0 or higher. Ignoring.")
continue
if k in ["lmiMessageTimeout", "validVerifyDomains"]:
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.2.0") < 0:
if _tools.version_compare(iviaVersion, "10.0.2.0") < 0:
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.0.0 or higher. Ignoring.")
continue
if k == "jsVersion":
if ibmsecurity.utilities.tools.version_compare(iviaVersion, "10.0.9.0") < 0:
if _tools.version_compare(iviaVersion, "10.0.9.0") < 0:
warnings.append(f"Appliance at version: {iviaVersion}, {k}: {v} is not supported. Needs 10.0.9.0 or higher. Ignoring.")
continue

# Add to the json_data dict
json_data[k] = v

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

return ibmsecurity.utilities.tools.json_compare(ret_obj1, ret_obj2)
return _tools.json_compare(ret_obj1, ret_obj2)
10 changes: 8 additions & 2 deletions ibmsecurity/isam/base/audit/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@
requires_version = None


def get(isamAppliance, check_mode=False, force=False):
def get(isamAppliance, id=None, check_mode=False, force=False):
"""
Retrieve audit configuration
id is optional
"""
return isamAppliance.invoke_get("Retrieve audit configuration", uri, requires_modules=requires_modules,
if id is None:
return isamAppliance.invoke_get("Retrieve current audit configuration", uri, requires_modules=requires_modules,
requires_version=requires_version)
else:
return isamAppliance.invoke_get("Retrieve {id} audit configuration",
f"{uri}/{id}", requires_modules=requires_modules,
requires_version=requires_version)


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