Skip to content

Commit e68760c

Browse files
Fix/policy attachment (#449)
* fix: don't use policyCombining algoritm for application * fix: update test * fix: update scim test * documentation: wip * feature: also support cert as a string * fix: trivial typo * feature: import signer cert as string * feature: test signer certs * fix: change test * build: don't include test directory * documentation: update changelog * documentation: update changelog * build: exclude test * build: exclude test, in MANIFEST.in (does not work for me in pyproject nor setup)
1 parent a12df3b commit e68760c

File tree

12 files changed

+546
-50
lines changed

12 files changed

+546
-50
lines changed

.gitignore

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

9999
# Test Script
100100
test.py
101+
/test/scripts/
101102

102103
# Read the docs
103104
_readthedocs/

MANIFEST.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
include LICENSE.txt
1+
include LICENSE
2+
prune test

docs/changelog.md

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

33
## Latest
44

5+
## 2025.9.26.0
6+
7+
- fix: policy attachments application can take 2 formats, /uri or urn:x:y
8+
- fix: Update scim test
9+
- fix: fed/federations.py - handle exception when retrieving existing mapping rules (#448)
10+
- build: exclude test folder from build
11+
- feature: signer cert support for string (in addition to file)
12+
513
## 2025.7.14.0
614

715
- fix: certificate_databases : python syntax (indentation)

ibmsecurity/isam/aac/access_control/policy_attachments.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,12 @@ def config(
158158

159159
json_data["policies"] = _convert_policy_name_to_id(isamAppliance, policies)
160160
if policyCombiningAlgorithm is not None:
161-
json_data["policyCombiningAlgorithm"] = policyCombiningAlgorithm
161+
if policyType is not None and policyType == "application":
162+
warnings.append(
163+
"Do not set policy combining algorithm for application type"
164+
)
165+
else:
166+
json_data["policyCombiningAlgorithm"] = policyCombiningAlgorithm
162167
if cache is not None:
163168
if tools.version_compare(isamAppliance.facts["version"], "9.0.3.0") < 0:
164169
warnings.append(
@@ -325,7 +330,8 @@ def publish(isamAppliance, server, resourceUri, check_mode=False, force=False):
325330
ret_obj = get(isamAppliance, server, resourceUri)
326331

327332
deploy_required = False
328-
if ret_obj.get("data", {}).get("deployrequired", False) or not ret_obj.get("data", {}).get("deployed", False):
333+
# skip application type for deployment.
334+
if (ret_obj.get("data", {}).get("type", "reverse_proxy") == "reverse_proxy") and (ret_obj.get("data", {}).get("deployrequired", False) or not ret_obj.get("data", {}).get("deployed", False)):
329335
deploy_required = True
330336

331337
logger.debug(f"\n\nDeploy required: {deploy_required}\n\n")

ibmsecurity/isam/base/ssl_certificates/signer_certificate.py

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ def _check_load(isamAppliance, kdb_id, label, server, port):
8585
cert_id = cert_data['id']
8686
cert_pem = get(isamAppliance, kdb_id, cert_id)['data']['contents']
8787
if cert_id == label: # label exists on appliance already
88-
logger.debug(f"Comparing certificates: appliance[{cert_pem}] remote[{remote_cert_pem}].")
89-
if cert_pem == remote_cert_pem: # certificate data is the same
88+
if cert_pem == remote_cert_pem:
9089
logger.debug("The certificate already exits on the appliance with the same label name and same content.")
9190
return True # both the labels and certificates match
9291
else:
@@ -136,7 +135,7 @@ def export_cert(isamAppliance, kdb_id, cert_id, filename, check_mode=False, forc
136135
"""
137136
import os.path
138137

139-
if force is True or _check(isamAppliance, kdb_id, cert_id) is True:
138+
if force or _check(isamAppliance, kdb_id, cert_id):
140139
if check_mode is False: # No point downloading a file if in check_mode
141140
return isamAppliance.invoke_get_file(
142141
"Export a certificate database",
@@ -149,36 +148,55 @@ def export_cert(isamAppliance, kdb_id, cert_id, filename, check_mode=False, forc
149148
def import_cert(isamAppliance, kdb_id, cert, label, preserve_label='false', check_mode=False, force=False):
150149
"""
151150
Importing a signer certificate into a certificate database
151+
cert can be a file or a string
152152
"""
153-
if force is True or _check_import(isamAppliance, kdb_id, label, cert, check_mode=check_mode):
154-
if check_mode is True:
155-
return isamAppliance.create_return_object(changed=True)
156-
else:
157-
if version_compare(isamAppliance.facts['version'], "10.0.5.0") < 0:
158-
return isamAppliance.invoke_post_files(
159-
"Importing a signer certificate into a certificate database",
160-
f"/isam/ssl_certificates/{kdb_id}/signer_cert",
161-
[
162-
{
163-
'file_formfield': 'cert',
164-
'filename': cert,
165-
'mimetype': 'application/octet-stream'
166-
}
167-
],
168-
{'label': label})
169-
else:
170-
return isamAppliance.invoke_post_files(
171-
"Importing a signer certificate into a certificate database",
172-
f"/isam/ssl_certificates/{kdb_id}/signer_cert",
173-
[
174-
{
175-
'file_formfield': 'cert',
176-
'filename': cert,
177-
'mimetype': 'application/octet-stream'
178-
}
179-
],
180-
{'label': label,
181-
'preserve_label': preserve_label})
153+
# Let's do some simple check
154+
# check if the string begins with -----BEGIN CERTIFICATE-----
155+
# so simply check if it's a long string
156+
if cert.startswith('-----BEGIN CERTIFICATE-----'):
157+
if force or _check_import_string(isamAppliance, kdb_id, label, cert, check_mode=check_mode):
158+
if check_mode:
159+
return isamAppliance.create_return_object(changed=True)
160+
else:
161+
json_data = {}
162+
json_data['label'] = label
163+
json_data['cert'] = cert
164+
json_data['operation'] = "import" # this is missing from the documentation.
165+
if version_compare(isamAppliance.facts['version'], "10.0.5.0") >= 0:
166+
json_data['preserve_label'] = preserve_label
167+
return isamAppliance.invoke_post("Create signer cert from certificate string",
168+
f"/isam/ssl_certificates/{kdb_id}/signer_cert",
169+
json_data)
170+
else:
171+
if force or _check_import(isamAppliance, kdb_id, label, cert, check_mode=check_mode):
172+
if check_mode:
173+
return isamAppliance.create_return_object(changed=True)
174+
else:
175+
if version_compare(isamAppliance.facts['version'], "10.0.5.0") < 0:
176+
return isamAppliance.invoke_post_files(
177+
"Importing a signer certificate into a certificate database",
178+
f"/isam/ssl_certificates/{kdb_id}/signer_cert",
179+
[
180+
{
181+
'file_formfield': 'cert',
182+
'filename': cert,
183+
'mimetype': 'application/octet-stream'
184+
}
185+
],
186+
{'label': label})
187+
else:
188+
return isamAppliance.invoke_post_files(
189+
"Importing a signer certificate into a certificate database",
190+
f"/isam/ssl_certificates/{kdb_id}/signer_cert",
191+
[
192+
{
193+
'file_formfield': 'cert',
194+
'filename': cert,
195+
'mimetype': 'application/octet-stream'
196+
}
197+
],
198+
{'label': label,
199+
'preserve_label': preserve_label})
182200

183201
return isamAppliance.create_return_object()
184202

@@ -196,6 +214,16 @@ def _check(isamAppliance, kdb_id, cert_id):
196214
return False
197215

198216

217+
def _check_import_string(isamAppliance, kdb_id, label, certstring, check_mode=False):
218+
# TODO: DO SOMETHING
219+
cert_pem = get(isamAppliance, kdb_id, label)['data']['contents']
220+
if cert_pem.replace("\n", "") == certstring.replace("\n", ""):
221+
logger.debug(f"Certificate already exists with same label {label}")
222+
return False
223+
else:
224+
return True
225+
226+
199227
def _check_import(isamAppliance, kdb_id, cert_id, filename, check_mode=False):
200228
"""
201229
Checks if certificate on the Appliance exists and if so, whether it is different from

pyproject.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
77

88
[project]
99
name = "ibmsecurity"
10-
version = "2025.7.14.0"
10+
version = "2025.9.26.0"
1111
authors = [
1212
{ name="IBM", email="[email protected]" },
1313
]
@@ -34,6 +34,13 @@ dependencies = {file = [".config/requirements.in"]}
3434
optional-dependencies.docs = {file = [".config/requirements-docs.in"]}
3535
optional-dependencies.test = {file = [".config/requirements-test.in"]}
3636

37+
[tool.setuptools.packages.find]
38+
exclude = [
39+
"test",
40+
"test.*"
41+
]
42+
namespaces = false
43+
3744
[tool.pytest]
3845
env_files = ".env"
3946

setup.py

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

33
setup(
44
name="ibmsecurity",
5-
packages=find_packages(),
5+
packages=find_packages(exclude=["test.*","test"]),
66
# Date of release used for version - please be sure to use YYYY.MM.DD.seq#, MM and DD should be two digits e.g. 2017.02.05.0
77
# seq# will be zero unless there are multiple release on a given day - then increment by one for additional release for that date
8-
version="2025.7.14.0",
8+
version="2025.9.26.0",
99
description="Idempotent functions for IBM Security Appliance REST APIs",
1010
author="IBM",
1111
author_email="[email protected]",

test/test_aac_access_control.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,8 @@ def getPolicyAttachmentData():
167167
"cache": 0
168168
},
169169
{"server": "mobileApp",
170-
"resourceUri": "/somethingelseApp",
171-
"policyCombiningAlgorithm": "denyOverrides",
172-
"policies": [
173-
{"name": "Test Access Control Policy",
174-
"type": "policy"
175-
}
176-
],
170+
"resourceUri": "urn:isbn:0-486-27557-4",
171+
"policies": [],
177172
"type": "application",
178173
"cache": 0
179174
},

0 commit comments

Comments
 (0)