Skip to content
Closed
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
cb091c7
BugFix: 2x + Feature: 1x aac\runtime_template
svetterIO Jan 28, 2019
6b28c75
Feature: handle isam 9.0.5 extProperties client attributes properly
svetterIO Jan 28, 2019
ffebd15
+1 Function: Compare LTPA files for idempotency on junction creation
svetterIO May 15, 2019
1165780
+1 function: compare zip file contents
svetterIO May 15, 2019
eb626e4
+1 function: check runtime template root for idempotency
svetterIO May 15, 2019
a1d4579
+1 function: check management root on import_zip for idempotency
svetterIO May 15, 2019
d30f928
Merge branch 'master' into master
svetterIO May 15, 2019
6607024
Merge branch 'master' into master
svetterIO Jul 1, 2019
32abfc4
BuFix: aac runtime templates parameter correction
svetterIO Jul 1, 2019
9942ea8
BugFix: Skip compare for missing zip files
Jul 1, 2019
78e2c85
+1 function: set_all
Jul 1, 2019
aed1a08
BugFix: server_connections jdbc id parameter missing
Jul 1, 2019
34155b2
BugFix: server_connections ldap id parameter missing
Jul 1, 2019
1950bc4
BugFix: server_connections smtp id parameter missing
Jul 1, 2019
b0a40ea
+1 Feature: add local_ip as possible junction parameter
Jul 1, 2019
a481576
BigFix: load of signer certificates not possible (network or firewall…
Jul 1, 2019
9e1fd07
Typo: entry.py comment for set entries
svetterIO Jul 8, 2019
664d2c0
+1 feature: set EmailMessage, ScimConfig, CI server connections prope…
svetterIO Jul 9, 2019
dcfa6f5
BugFix: logger info with manual field specification and automatic fie…
svetterIO Jul 9, 2019
a58204b
+1 feature: Compare server connections content + BugFix on CI server …
svetterIO Jul 12, 2019
0da0a6c
BugFix: mappging_rule filename check added
svetterIO Aug 15, 2019
967f7de
Merge conflict pre-work for server_connections
svetterIO Aug 15, 2019
f6e7db3
Merge remote-tracking branch 'upstream/master'
svetterIO Aug 15, 2019
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
1 change: 0 additions & 1 deletion ibmsecurity/isam/aac/api_protection/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ def set(isamAppliance, name, definitionName, companyName, redirectUri=None, comp
requirePkce=requirePkce, encryptionDb=encryptionDb, encryptionCert=encryptionCert,
jwksUri=jwksUri, extProperties=extProperties, check_mode=check_mode, force=force)


def compare(isamAppliance1, isamAppliance2):
"""
Compare API Protection Definitions between two appliances
Expand Down
31 changes: 31 additions & 0 deletions ibmsecurity/isam/aac/authentication/mechanisms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import logging
from ibmsecurity.utilities import tools
from ibmsecurity.isam.aac.authentication import mechanism_types
from ibmsecurity.isam.aac.server_connections import smtp
from ibmsecurity.isam.aac.server_connections import ci
from ibmsecurity.isam.aac.server_connections import ws

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -99,6 +102,20 @@ def add(isamAppliance, name, uri, description="", attributes=None, properties=No
if attributes is not None:
json_data['attributes'] = attributes
if properties is not None:
logger.info("Searching for keys to substitute value with uuids")
id = {}
for property in properties:
if property['key'] == "EmailMessage.serverConnection":
id = smtp._get_id(isamAppliance, property['value'])['data']
logger.info("Found EmailMessage.serverConnection by name[{}] with uuid[{}]".format(property['value'], id))
elif property['key'] == "ScimConfig.serverConnection":
id = ws.search(isamAppliance, property['value'])['data']
logger.info("Found ScimConfig.serverConnection by name[{}] with uuid[{}]".format(property['value'], id))
elif property['key'] == "CI.serverConnection":
id = ci._get_id(isamAppliance, property['value'])['data']
logger.info("Found CI.serverConnection by name[{}] with uuid[{}]".format(property['value'], id))
if id != {}:
property['value'] = id
json_data['properties'] = properties
return isamAppliance.invoke_post(
"Create a new federation", module_uri, json_data,
Expand Down Expand Up @@ -197,6 +214,20 @@ def _check(isamAppliance, name, description, attributes, properties, predefined,
except:
pass
if properties is not None:
logger.info("Searching for keys to substitute value with uuids")
id = {}
for property in properties:
if property['key'] == "EmailMessage.serverConnection":
id = smtp._get_id(isamAppliance, property['value'])['data']
logger.info("Found EmailMessage.serverConnection by name[{}] with uuid[{}]".format(property['value'], id))
elif property['key'] == "ScimConfig.serverConnection":
id = ws.search(isamAppliance, property['value'])['data']
logger.info("Found ScimConfig.serverConnection by name[{}] with uuid[{}]".format(property['value'], id))
elif property['key'] == "CI.serverConnection":
id = ci._get_id(isamAppliance, property['value'])['data']
logger.info("Found CI.serverConnection by name[{}] with uuid[{}]".format(property['value'], id))
if id != {}:
property['value'] = id
json_data['properties'] = properties
else:
# May not exist so skip any exceptions when deleting
Expand Down
15 changes: 9 additions & 6 deletions ibmsecurity/isam/aac/mapping_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ def set(isamAppliance, name, category, filename=None, content=None, upload_filen
else:
filename = _extract_filename(upload_filename)
if _check(isamAppliance, name=name) is False:
# Force the add - we already know connection does not exist
# need to check for duplicate filename constraint violations on add
return add(isamAppliance, name=name, filename=filename, content=content, category=category,
check_mode=check_mode, force=True)
check_mode=check_mode, force=force)
else:
# Update request
return update(isamAppliance, name=name, content=content, check_mode=check_mode, force=force)
Expand All @@ -90,7 +90,7 @@ def add(isamAppliance, name, filename=None, content=None, category="OAUTH", chec
"""
Add a mapping rule
"""
if force is True or _check(isamAppliance, name) is False:
if force is True or _check(isamAppliance, name=name, filename=filename) is False:
if check_mode is True:
return isamAppliance.create_return_object(changed=True)
else:
Expand All @@ -106,7 +106,7 @@ def add(isamAppliance, name, filename=None, content=None, category="OAUTH", chec
"category": category
})

return isamAppliance.create_return_object()
return isamAppliance.create_return_object(rc=1, warnings=["mapping rule {} could not be added.".format(name)])


def delete(isamAppliance, name, check_mode=False, force=False):
Expand Down Expand Up @@ -245,15 +245,18 @@ def import_file(isamAppliance, name, filename, check_mode=False, force=False):
return isamAppliance.create_return_object()


def _check(isamAppliance, name):
def _check(isamAppliance, name, filename=None):
"""
Check if Mapping Rules already exists
Check if Mapping Rules already exists based on the name and filename
"""
ret_obj = get_all(isamAppliance)

for obj in ret_obj['data']:
if obj['name'] == name:
return True
if filename is not None and obj['fileName'] == filename:
logger.warning("Found mapping rule [{}] with same filename[{}]. This filename violates duplicate key value unique constraint. Choose another filename for [{}] or delete corresponding mapping rule [{}] to solve this".format(obj['name'],filename,filename,obj['name']))
return True

return False

Expand Down
34 changes: 34 additions & 0 deletions ibmsecurity/isam/aac/runtime_template/directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,40 @@ def create(isamAppliance, path, name, check_mode=False, force=False):

return isamAppliance.create_return_object(warnings=warnings)

def create(isamAppliance, id, check_mode=False, force=False):
"""
Creating a directory in the runtime template files directory

:param isamAppliance:
:param id:
:param name:
:param check_mode:
:param force:
:return:
"""
warnings = []

path = os.path.dirname(id)
name = os.path.basename(id)

check_dir = _check(isamAppliance, id)
if check_dir != None:
warnings.append("Directory {0} exists. Ignoring create.".format(id))

if force is True or check_dir == None:
if check_mode is True:
return isamAppliance.create_return_object(changed=True, warnings=warnings)
else:
return isamAppliance.invoke_post(
"Creating a directory in the runtime template files directory",
"/mga/template_files/{0}".format(path),
{
'dir_name': name,
'type': 'dir'
})

return isamAppliance.create_return_object(warnings=warnings)


def delete(isamAppliance, id, check_mode=False, force=False):
"""
Expand Down
129 changes: 102 additions & 27 deletions ibmsecurity/isam/aac/runtime_template/root.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import logging
import os.path
import ibmsecurity.utilities.tools
import zipfile
import difflib
import hashlib
import shutil
from ibmsecurity.isam.aac.runtime_template import directory
from ibmsecurity.isam.aac.runtime_template import file

from ibmsecurity.utilities.tools import get_random_temp_dir, files_same_zip_content
logger = logging.getLogger(__name__)

uri = "/mga/template_files"
Expand All @@ -28,42 +33,108 @@ def export_file(isamAppliance, filename, check_mode=False, force=False):
return isamAppliance.create_return_object()


def import_file(isamAppliance, filename, check_mode=False, force=False):
def import_file(isamAppliance, filename, delete_missing=False, check_mode=False, force=False):
"""
Replace all Runtime Template Files
Import all Runtime Template Files
"""
if check_mode is True:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_post_files(
"Replace all Runtime Template Files",
uri,
[
warnings = []

if force is True or _check_import(isamAppliance, filename):
if delete_missing is True:
tempdir = get_random_temp_dir()
tempfilename = "template_files.zip"
tempfile = os.path.join(tempdir, tempfilename)
export_file(isamAppliance, tempfile)

zServerFile = zipfile.ZipFile(tempfile)
zClientFile = zipfile.ZipFile(filename)

files_on_server = [];
for info in zServerFile.infolist():
files_on_server.append(info.filename)
files_on_client = [];
for info in zClientFile.infolist():
files_on_client.append(info.filename)
missing_client_files = [x for x in files_on_server if x not in files_on_client]

if missing_client_files != []:
logger.info("list all missing files in {}, which will be deleted on the server: {}.".format(filename, missing_client_files))

for x in missing_client_files:
if x.endswith('/'):
search_dir= os.path.dirname(x[:-1]) + '/'
if search_dir not in missing_client_files:
logger.debug("delete directory on the server: {0}.".format(x))
delete(isamAppliance, x, "directory", check_mode=check_mode)
else:
search_dir= os.path.dirname(x) + '/'
if search_dir not in missing_client_files:
logger.debug("delete file on the server: {0}.".format(x))
delete(isamAppliance, x, "file", check_mode=check_mode)
shutil.rmtree(tempdir)

if check_mode is True:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_post_files(
"Replace all Runtime Template Files",
uri,
[
{
'file_formfield': 'file',
'filename': filename,
'mimetype': 'application/octet-stream'
}
],
{
'file_formfield': 'file',
'filename': filename,
'mimetype': 'application/octet-stream'
}
],
{
"force": force
}, json_response=False, requires_modules=requires_modules,
requires_version=requires_version)
"force": force
}, json_response=False)

return isamAppliance.create_return_object(warnings=warnings)


def _check_import(isamAppliance, filename):
"""
Checks if runtime template zip from server and client differ
:param isamAppliance:
:param filename:
:return:
"""

tempdir = get_random_temp_dir()
tempfilename = "template_files.zip"
tempfile = os.path.join(tempdir, tempfilename)
export_file(isamAppliance, tempfile)

if os.path.exists(tempfile):
identical = files_same_zip_content(filename,tempfile)

shutil.rmtree(tempdir)
if identical:
logger.info("runtime template files {} are identical with the server content. No update necessary.".format(filename))
return False
else:
logger.info("runtime template files {} differ from the server content. Updating runtime template files necessary.".format(filename))
return True
else:
logger.info("missing zip file from server. Comparison skipped.")
return False



def check(isamAppliance, id, type, check_mode=False, force=False):
ret_obj = None

name = os.path.basename(id)
path = os.path.dirname(id)

if (type.lower() == 'directory'):
ret_obj = directory._check(isamAppliance, id)
elif (type.lower() == 'file'):
ret_obj = file._check(isamAppliance, id)
ret_obj = file._check(isamAppliance, path, name)
else:
type = 'unknown'

name = os.path.basename(id)
path = os.path.dirname(id)

data = {
'id': ret_obj,
'path': path,
Expand All @@ -85,7 +156,11 @@ def delete(isamAppliance, id, type, check_mode=False, force=False):
:param force:
:return:
"""
if (type.lower() == 'directory'):
return directory.delete(isamAppliance, id)
elif (type.lower() == 'file'):
return file.delete(isamAppliance, id)

name = os.path.basename(id)
path = os.path.dirname(id)

if(type.lower() == 'directory'):
return directory.delete(isamAppliance, id, check_mode, force)
elif(type.lower() == 'file'):
return file.delete(isamAppliance, path, name, check_mode, force)
34 changes: 34 additions & 0 deletions ibmsecurity/isam/aac/scim.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from ibmsecurity.utilities import tools

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -63,3 +64,36 @@ def update_isam_user(isamAppliance, isam_domain, update_native_users, ldap_conne
"Update SCIM ISAM user settings",
"/mga/scim/configuration/urn:ietf:params:scim:schemas:extension:isam:1.0:User",
ret_obj)

def set_all(isamAppliance, scim_configuration, check_mode=False, force=False):
"""
Update entire SCIM settings
"""
if scim_configuration is None or scim_configuration == '':
return isamAppliance.create_return_object(
warnings="Need to pass content for scim configuration")
else:
if force is True or _check(isamAppliance, scim_configuration) is False :
if check_mode is True:
return isamAppliance.create_return_object(changed=True)
else:
return isamAppliance.invoke_put(
"Update SCIM settings",
"/mga/scim/configuration",
scim_configuration )

return isamAppliance.create_return_object()

def _check(isamAppliance, scim_configuration):
"""
Check if scim configuration is identical with server
"""
ret_obj = get_all(isamAppliance)
logger.debug("Comparing server scim configuration with desired configuration.")
logger.debug("Server JSON: {0}".format(tools.json_sort(ret_obj['data'])))
logger.debug("Desired JSON: {0}".format(tools.json_sort(scim_configuration)))
if tools.json_sort(scim_configuration) != tools.json_sort(ret_obj['data']):
return False

logger.debug("Server configuration is identical with desired configuration. No change necessary.")
return True
Loading