Introduction
IBM Security Identity Manager (ISIM) is a powerful and complex Identity Management tool. It currently lives along IBM Security Identity Governance and Intelligence (now rebranded as IBM Security Verify Governance) in IBM’s IdM family. As far as I know, it is one of the oldest and most used products of this kind, however, there is not much online community around it (probably because it is an enterprise product, and enterprises are not know for their great sharing spirit).
Motivation
I’ve been working with ISIMv7 (the closed system version) for around two years by now, and at least during the first one, all the development, testing and quality assurance work was done manually on the administration console. That means, if an approval workflow had 3 approval activities and one work order, and I wanted to test that it works, I’d have to manually request the access, then go manually over every activity (and it’s justification) and then check the request to see if it worked. If my workflow had an error in any of it’s scripts, then I would have to repeat this process all over again until I fixed the error. All of this got annoying quickly, and now that I know that it can be faster, I am even more annoyed at those times.
I started to work on this around April this year, and I decided to publish it on PyPi and Github a couple of weeks ago, because I think I might be useful to some people. You are encouraged and welcome to collaborate and add features to the library on github if you’d like too.
Some of the issues I faced were resolved by checking this great sources:
- ISIM SOAP Web Services example by IBM
- ISIM REST API example by IBM
- Sample ISIM REST Requests by Ayoub Bahar
Thanks!
However, for some others I had to do some digging on the Java APIs (you can check it out here), and the SOAP API sample Java code - which is actually the best documentation available, since the official document is not very useful.
Features
Documentation is now up at Read the docs!
Currently, the library consists of 7 modules for the ISIM application server and an inner package for working with ISIM7 Virtual Appliance. However, from the 7 modules you (most likely) will only interact with the authorization, search and entities API.
The library uses Requests and Zeep extensively for communication with ISIM APIs.
The following are the currently (as of January 10, 2020) available features in it for the ISIM Application Server. Authorization (login) is clearly also available.
Entities\Operations | Search | DN Lookup | Add | Delete | Suspend | Restore | Modify |
---|---|---|---|---|---|---|---|
People | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Dynamic Roles | ✓ | ✓ | ✓ | ✓ | ✓ | ||
Static Roles | ✓ | ✓ | ✓ | ✓ | ✓ | ||
Provisioning Policies | ✓ | ✓ | ✓ | ✓ | |||
Activities | ✓ | (Complete) | |||||
Organizational Containers | ✓ | ✓ | |||||
Services | ✓ | ||||||
Access | ✓ | (Request) | |||||
Groups | ✓ | ||||||
Accounts | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ (and orphan) |
The following are the currently (as of October 6, 2020) available features in it for the ISIM7 Virtual Appliance. Authorization (login) is clearly also available.
- Search system properties
- Create system properties
- Modify system properties
You can contribute more to the project on Github if you’d like (some of the older code is in spanish, since it started as an internal project and we are based in Colombia)
Usage
Currently, the only documentation available is this article and the project’s README file. However, it is my plan to make a more complete set of documentation available, just so it is easier to use.
UPDATE: Documentation is now available at Read the docs!
Installation
You can install the library from PyPi using the following command:
pip install pyisim
Or from source using:
git clone https://github.com/cazdlt/pyisim.git
cd pyisim
python setup.py install
Application API Examples
- Authorization (login)
from pyisim.auth import Session
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
- Obtaining the currently logged in person and modifying it’s email
from pyisim.auth import Session
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
me=s.current_person()
me.modify(s,"my justification",changes={"mail":"cazdlt@gmail.com"})
- Creating a new person
from pyisim.auth import Session
from pyisim.entities import Person
from pyisim import search
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
person_attrs={
"cn":"Andrés Zamora",
"employeenumber":12345,
"title":"Specialist",
"mail":"cazdlt@gmail.com"
}
p=Person(s,person_attrs=person_attrs)
parent = search.organizational_container(s, "organizations", "My Organization")[0]
p.add(s,parent,"my justification")
- Getting the created person from ISIM, requesting an access for it and approving it.
from pyisim.auth import Session
from pyisim import search
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
person=search.people(s,by="employeenumber",filter=12345,limit=1)[0]
access=search.access(s,filter="Active Directory",limit=2)
response=person.request_access(s,access,"justification")
request_id=response.request.id
activity=search.activities(s,by="requestId",filter=request_id)[0]
activity.complete(s,"Approve","OK")
- Getting the created person from ISIM, modifying it’s title and then deleting it.
- Entity modification can be done changing the object’s attributes (as seen here) or passing the changes dictionary (as seen in the second example).
from pyisim.auth import Session
from pyisim import search
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
persona=search.people(s,by="employeenumber",filter=12345,limit=1)[0]
persona.title="Analyst"
persona.modify(s,"modifying the title")
persona.delete(s," deleting person :(")
- Suspend and restore operations are done in the same way, through the
person.suspend()
andperson.restore()
methods. - Creating dynamic roles
from pyisim.auth import Session
from pyisim import search
from pysim.entities import DynamicRole
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
parent = search.organizational_container(s, "organizations", "My Organization")[0]
owners = search.people(s, by="employeenumber", filter="1015463230")
owners_roles = search.roles(s, filter="ITIM Administrators")
# creación
name="dynrol_prueba"
rolinfo = {
"name": name,
"description": "dynrol_prueba",
"parent": parent,
"classification": "role.classification.business",
"access_option": 2,
"access_category": "Role",
"owners": [o.dn for o in owners] + [o.dn for o in owners_roles],
"rule": "(title=ROLETEST)",
}
rol = DynamicRole(s, role_attrs=rolinfo)
rol.add(s)
{% endhighlight %}
- Searching, modifying and then deleting static roles
{% highlight python %}
from pyisim.auth import Session
from pyisim import search
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
rol=search.roles(s,filter="My Role")
#can modify using the object attributes
rol.description = "new description"
rol.modify(s)
#can also modify using a changes dictionary
changes={"description":"newer description"}
rol.modify(s,changes)
rol.delete(s)
- Static and Dynamic role can use the same methods, but some attributes (like the rule) are specific to dynamic roles.
- Creating provisioning policies
- Modification and deletion are done the same way as the other entities (with
policy.modify()
andpolicy.delete()
)
- Modification and deletion are done the same way as the other entities (with
from pyisim.auth import Session
from pyisim import search
from pysim.entities import ProvisioningPolicy
s=Session(url, "cazdlt", "secretpw", "my_certificate.cer")
name="test"
parent = search.organizational_container(s, "organizations", test_org)[0]
service = search.service(s, parent, filter="Directorio Activo")[0]
#I know this can get very complex, so the library is also very flexible
entitlements = {
service.dn: {
"automatic": False,
"workflow": None,
"parameters": {
"ercompany": [
{
"enforcement": "Default",
"type": "script",
"values": "return 'test';",
},
{
"enforcement": "Excluded",
"type": "null",
},
{
"enforcement": "Allowed",
"type": "constant",
"values": ["test1", "test2"],
},
{
"enforcement": "Allowed",
"type": "Constant",
"values": ["test3"],
},
{
"enforcement": "Allowed",
"type": "REGEX",
"values": r"^[sw]+$",
},
],
"eradfax": [
{
"enforcement": "Allowed",
"type": "constant",
"values": ["1018117"],
}
],
},
},
"*": {"automatic": False, "workflow": None, "parameters": {}},
}
policy = {
"description": "test",
"name": name,
"parent": parent,
"priority": 10000,
"memberships": [x.dn for x in search.roles(s, filter="Auditor")],
"enabled": False,
"entitlements": entitlements,
}
pp = ProvisioningPolicy(s, policy_attrs=policy)
pp.add(s)
The Future
This project is clearly still in it’s infancy, and a lot of things can be improved upon. These are my plans to get better usability of the library:
- Service operations
- To programatically create and modify services
- Improve search filtering
Most methods are annotated in the code, so you get code completion while writing code on an IDE or text editor. There are also a bunch of examples in the tests/
folder in github, you can check those out or contact me if you have any doubts, requests or ideas on this.
Consider buying me a (colombian) coffee or contacting me on twitter!