Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6873636
build: update .gitignore
tombosmansibm Jan 22, 2026
267c524
build: update python versions test
tombosmansibm Jan 22, 2026
a1178fa
fix: format to f-strings
tombosmansibm Jan 22, 2026
1641ec2
fix: format to f-strings
tombosmansibm Jan 22, 2026
39e14f9
fix: format to f-strings
tombosmansibm Jan 22, 2026
5974bd0
fix: format to f-strings
tombosmansibm Jan 22, 2026
c9d90d7
fix: format to f-strings (2nd run)
tombosmansibm Jan 22, 2026
2f14ff0
fix: format to f-strings
tombosmansibm Jan 22, 2026
f165bd4
fix: format to f-strings
tombosmansibm Jan 22, 2026
5ebeb5e
fix: format to f-strings
tombosmansibm Jan 22, 2026
ea3e02c
fix: allow handling of stanza's that look like [stanza:/] (specifical…
tombosmansibm Jan 22, 2026
2e3358b
fix: allow handling of entries (specifically request-log-format and s…
tombosmansibm Jan 23, 2026
0733f80
test: tests for reverse proxy config
tombosmansibm Jan 23, 2026
79b6b4c
test: add restarts to the reverse proxies after changing stanza or en…
tombosmansibm Jan 23, 2026
2a20558
docs: update changelog
tombosmansibm Jan 23, 2026
91617d3
test: trivial
tombosmansibm Jan 23, 2026
728e515
build: version update
tombosmansibm Jan 23, 2026
6dc25fb
test: don't fail on pytest
tombosmansibm Jan 23, 2026
e3040b2
fix: remove requires_model
tombosmansibm Jan 23, 2026
56db63c
test: tiny updates
tombosmansibm Jan 23, 2026
523d1bb
fix: simpler check for existing runtime configuration
tombosmansibm Jan 23, 2026
82c2c3d
docs: update changelog
tombosmansibm Jan 23, 2026
b43026d
test: rollback change
tombosmansibm Jan 23, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11"]
python-version: ["3.11", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ celerybeat-schedule
venv/
ENV/
*.venv/
.venv*/

# Spyder project settings
.spyderproject
Expand Down
1 change: 1 addition & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def iviaServer():
print('\n')
return returnValue


# ibmsecurity
def pytest_runtest_setup(item):
print("setting up function:", item.name)
Expand Down
7 changes: 7 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Latest

## 2026.1.23.0

- fix: web/reverse_proxy/configuration/stanza.py - urlencode stanza id names (specifically to handle junction stanzas, eg [jwt:/])
- fix: web/reverse_proxy/configuration/entry.py - urlencode stanza ids, entry names and some values (specifically to handle junction stanzas, eg [jwt:/],
and values that contain url unsafe characters eg. request-log-format)
- fix: web/runtime/process.py - remove unnecessary `requires_model` (applicable to all current models)

## 2026.1.22.0

- fix: base/dsc.py - add missing parameters for Docker DSC config (#468)
Expand Down
6 changes: 2 additions & 4 deletions ibmsecurity/isam/web/reverse_proxy/aac_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def config(
else:
return isamAppliance.invoke_post(
" Authentication and Context based access configuration for a reverse proxy instance",
"/wga/reverseproxy/{}/authsvc_config".format(instance_id),
f"/wga/reverseproxy/{instance_id}/authsvc_config",
json_data,
warnings=warnings,
requires_modules=requires_modules,
Expand All @@ -90,9 +90,7 @@ def _check_config(isamAppliance, instance_id, junction):
for j in ret_obj["data"]:
if j["id"] == junction:
logger.info(
"Junction {} was found - hence aac config must have already executed.".format(
junction
)
f"Junction {junction} was found - hence aac config must have already executed."
)
return True

Expand Down
6 changes: 3 additions & 3 deletions ibmsecurity/isam/web/reverse_proxy/common_configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def get_all(isamAppliance, reverseproxy_id, check_mode=False, force=False):
Retrieving all common configuration for reverse proxy
"""
return isamAppliance.invoke_get("Retrieving the all common configuration for reverse proxy",
"{0}/{1}".format(uri, reverseproxy_id),
f"{uri}/{reverseproxy_id}",
requires_modules=requires_modules,
requires_version=requires_version)

Expand All @@ -23,13 +23,13 @@ def get(isamAppliance, reverseproxy_id, configuration_id, check_mode=False, forc
"""
ret_object = get_all(isamAppliance, reverseproxy_id, check_mode, force)

logger.debug("Looking for {0} value in reverse proxy {1}".format(configuration_id, reverseproxy_id))
logger.debug(f"Looking for {configuration_id} value in reverse proxy {reverseproxy_id}")

ret_obj = isamAppliance.create_return_object()

try:
ret_obj['data'] = ret_object['data'][configuration_id]
except:
logger.error("Invalid configuration_id: {0}".format(configuration_id))
logger.error(f"Invalid configuration_id: {configuration_id}")

return ret_obj
4 changes: 2 additions & 2 deletions ibmsecurity/isam/web/reverse_proxy/common_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def delete(isamAppliance, file_id, check_mode=False, force=False):
else:
return isamAppliance.invoke_delete(
"Clearing a common log file",
"{0}/{1}".format(uri, file_id), requires_model=requires_model)
f"{uri}/{file_id}", requires_model=requires_model)

return isamAppliance.create_return_object(warnings=ret_obj['warnings'])

Expand All @@ -64,7 +64,7 @@ def export_file(isamAppliance, file_id, filename, check_mode=False, force=False)
if check_mode is False: # No point downloading a file if in check_mode
return isamAppliance.invoke_get_file(
"Exporting a common log file",
"{0}/{1}?export".format(uri, file_id),
f"{uri}/{file_id}?export",
filename, requires_model=requires_model)

return isamAppliance.create_return_object(warnings=ret_obj['warnings'])
134 changes: 47 additions & 87 deletions ibmsecurity/isam/web/reverse_proxy/configuration/entry.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from urllib.parse import quote_plus
from urllib.parse import unquote_plus

import logging
import ibmsecurity.utilities.tools
from ibmsecurity.utilities.tools import jsonSortedListEncoder
Expand All @@ -18,11 +21,10 @@ def get_all(isamAppliance, reverseproxy_id, stanza_id, check_mode=False, force=F
"""
Retrieving all configuration entries for a stanza - Reverse Proxy
"""
stanza_id = quote_plus(stanza_id)
try:
ret_obj = isamAppliance.invoke_get("Retrieving all configuration entries for a stanza - Reverse Proxy",
"{0}/{1}/configuration/stanza/{2}".format(uri,
reverseproxy_id,
stanza_id))
f"{uri}/{reverseproxy_id}/configuration/stanza/{stanza_id}")
logger.debug(f"Get All {stanza_id}:\n {ret_obj}")
except:
# Return empty array - exception thrown if stanza has no entries or does not exist
Expand All @@ -37,20 +39,10 @@ def get(isamAppliance, reverseproxy_id, stanza_id, entry_id, check_mode=False, f
Retrieving a specific configuration entry - Reverse Proxy
"""
# URL being encoded primarily to handle request-log-format that has "%" values in them
f_uri = "{0}/{1}/configuration/stanza/{2}/entry_name/{3}".format(uri, reverseproxy_id,
stanza_id, entry_id)
# Replace % with %25 if it is not encoded already
import re
ruri = re.sub("%(?![0-9a-fA-F]{2})", "%25", f_uri)
# URL encode
try:
# Assume Python3 and import package
from urllib.parse import quote
except ImportError:
# Now try to import Python2 package
from urllib import quote
stanza_id = quote_plus(stanza_id)
entry_id = quote_plus(entry_id)
full_uri = f"{uri}/{reverseproxy_id}/configuration/stanza/{stanza_id}/entry_name/{entry_id}"

full_uri = quote(ruri)
return isamAppliance.invoke_get("Retrieving a specific configuration entry - Reverse Proxy",
full_uri)

Expand All @@ -65,21 +57,20 @@ def add(isamAppliance, reverseproxy_id, stanza_id, entries, check_mode=False, fo

add_required = False

if force is False:
if not force:
add_entries = []
for entry in entries:
exists, update_required, value = _check(isamAppliance, reverseproxy_id, stanza_id, entry[0], entry[1])
if exists is True:
if exists:
logger.debug(
'Entries exists {0}/{1}/{2}/{3}! Will be ignored.'.format(reverseproxy_id, stanza_id, entry[0],
entry[1]))
f'Entries exists {reverseproxy_id}/{stanza_id}/{entry[0]}/{entry[1]}! Will be ignored.')
else:
add_entries.append(entry)
add_required = True
entries = add_entries

if force is True or add_required is True:
if check_mode is True:
if force or add_required:
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
return _add(isamAppliance, reverseproxy_id, stanza_id, entries)
Expand All @@ -88,9 +79,10 @@ def add(isamAppliance, reverseproxy_id, stanza_id, entries, check_mode=False, fo


def _add(isamAppliance, reverseproxy_id, stanza_id, entries):
stanza_id = quote_plus(stanza_id)
return isamAppliance.invoke_post(
"Adding a configuration entry or entries by stanza - Reverse Proxy",
"{0}/{1}/configuration/stanza/{2}/entry_name".format(uri, reverseproxy_id, stanza_id),
f"{uri}/{reverseproxy_id}/configuration/stanza/{stanza_id}/entry_name",
{"entries": entries})


Expand Down Expand Up @@ -124,8 +116,9 @@ def set(isamAppliance, reverseproxy_id, stanza_id, entries, check_mode=False, fo
if force or (newEntriesJSON != currentEntriesJSON):
for entry in entries:
logger.info(f"Deleting entry, will be re-added: {reverseproxy_id}/{stanza_id}/{entry[0]}")
delete_all(isamAppliance, reverseproxy_id, stanza_id, entry[0], check_mode, True)
if check_mode is True:
if not check_mode:
delete_all(isamAppliance, reverseproxy_id, stanza_id, entry[0], check_mode, True)
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
return _add(isamAppliance, reverseproxy_id, stanza_id, entries)
Expand Down Expand Up @@ -175,29 +168,20 @@ def delete(isamAppliance, reverseproxy_id, stanza_id, entry_id, value_id='', che
exists, update_required, value = _check(isamAppliance, reverseproxy_id, stanza_id, entry_id, value_id)

if force or exists:
if check_mode is True:
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
# URL being encoded primarily to handle request-log-format that has "%" values in them
f_uri = "{0}/{1}/configuration/stanza/{2}/entry_name/{3}/value/{4}".format(uri, reverseproxy_id, stanza_id,
entry_id, value_id)
# Replace % with %25 if it is not encoded already
import re
ruri = re.sub("%(?![0-9a-fA-F]{2})", "%25", f_uri)
# URL encode
try:
# Assume Python3 and import package
from urllib.parse import quote
except ImportError:
# Now try to import Python2 package
from urllib import quote

full_uri = quote(ruri)
stanza_id = quote_plus(stanza_id)
entry_id = quote_plus(entry_id)
value_id = quote_plus(value_id)
full_uri = f"{uri}/{reverseproxy_id}/configuration/stanza/{stanza_id}/entry_name/{entry_id}/value/{value_id}"

# Workaround for value_id encoding in 9.0.7.1
if ibmsecurity.utilities.tools.version_compare(isamAppliance.facts['version'], '9.0.7.1') >= 0:
uri_parts = full_uri.split('/value/')
uri_parts[1] = uri_parts[1].replace('/', '%2F')
full_uri = '/value/'.join(uri_parts)
#if ibmsecurity.utilities.tools.version_compare(isamAppliance.facts['version'], '9.0.7.1') >= 0:
# uri_parts = full_uri.split('/value/')
# uri_parts[1] = uri_parts[1].replace('/', '%2F')
# full_uri = '/value/'.join(uri_parts)
return isamAppliance.invoke_delete(
"Deleting a value from a configuration entry - Reverse Proxy", full_uri)

Expand All @@ -209,34 +193,22 @@ def delete_all(isamAppliance, reverseproxy_id, stanza_id, entry_id, check_mode=F
Deleting all values from a configuration entry - Reverse Proxy
"""
delete_required = False
if force is False:
if not force:
try:
ret_obj = get(isamAppliance, reverseproxy_id, stanza_id, entry_id)
if ret_obj['data'] != {}:
delete_required = True
except:
except Exception:
pass

if force is True or delete_required is True:
if check_mode is True:
if force or delete_required:
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
# URL being encoded primarily to handle request-log-format that has "%" values in them
f_uri = "{0}/{1}/configuration/stanza/{2}/entry_name/{3}".format(uri, reverseproxy_id, stanza_id, entry_id)

# Replace % with %25 if it is not encoded already
import re
ruri = re.sub("%(?![0-9a-fA-F]{2})", "%25", f_uri)
# URL encode
try:
# Assume Python3 and import package
from urllib.parse import quote
except ImportError:
# Now try to import Python2 package
from urllib import quote

full_uri = quote(ruri)

stanza_id = quote_plus(stanza_id)
entry_id = quote_plus(entry_id)
full_uri = f"{uri}/{reverseproxy_id}/configuration/stanza/{stanza_id}/entry_name/{entry_id}"
return isamAppliance.invoke_delete(
"Deleting all values from a configuration entry - Reverse Proxy", full_uri)

Expand All @@ -247,28 +219,19 @@ def update(isamAppliance, reverseproxy_id, stanza_id, entry_id, value_id, check_
"""
Updating a configuration entry or entries by stanza - Reverse Proxy
"""
if force is False:
if not force:
exists, update_required, cur_value = _check(isamAppliance, reverseproxy_id, stanza_id, entry_id, value_id)

if force is True or update_required is True:
if check_mode is True:
if force or update_required:
if check_mode:
return isamAppliance.create_return_object(changed=True)
else:
# URL being encoded primarily to handle request-log-format that has "%" values in them
f_uri = "{0}/{1}/configuration/stanza/{2}/entry_name/{3}".format(uri, reverseproxy_id,
stanza_id, entry_id)
# Replace % with %25 if it is not encoded already
import re
ruri = re.sub("%(?![0-9a-fA-F]{2})", "%25", f_uri)
# URL encode
try:
# Assume Python3 and import package
from urllib.parse import quote
except ImportError:
# Now try to import Python2 package
from urllib import quote

full_uri = quote(ruri)
# make sure stanza_id and entry_id are url safe
stanza_id = quote_plus(stanza_id)
entry_id = quote_plus(entry_id)
full_uri = f"{uri}/{reverseproxy_id}/configuration/stanza/{stanza_id}/entry_name/{entry_id}"

return isamAppliance.invoke_put(
"Updating a configuration entry or entries by stanza - Reverse Proxy",
full_uri,
Expand All @@ -291,12 +254,9 @@ def _check(isamAppliance, reverseproxy_id, stanza_id, entry_id, value_id):
except:
return False, True, None # Exception means entry / stanza not found

logger.info("Entry found in rp:{0}, stanza:{1}, entryid:{2}, value:{3}".format(reverseproxy_id,
stanza_id,
entry_id,
value))
logger.debug("Existing Value(s): {0}".format(value))
logger.debug("Value to update : {0}".format(value_id))
logger.info(f"Entry found in rp:{reverseproxy_id}, stanza:{stanza_id}, entryid:{entry_id}, value:{value}")
logger.debug(f"Existing Value(s): {value}")
logger.debug(f"Value to update : {value_id}")

if isinstance(value_id, list):
if value != value_id: # Comparing list with no sorting... sequence of values is of importance
Expand All @@ -305,7 +265,7 @@ def _check(isamAppliance, reverseproxy_id, stanza_id, entry_id, value_id):
else: # assuming base string provided for value_id
if len(value) == 1:
if str(value_id) != str(value[0]):
logger.debug("Single value do not match!")
logger.debug("Single value does not match!")
update_required = True
exists = False # to satisfy delete call
else: # base string will not match a zero length array or multiple values in it
Expand Down
Loading