Usage¶
To use Python UDM REST Client in a project, first get the UCS servers CA certificate (from http://FQDN.OF.UCS/ucs-root-ca.crt
).
Then use the UDM
context manager to open a HTTPS session and authenticate.
Change some properties¶
Open the session, get the current LDAP object, change some attributes and save the changes back to LDAP:
import asyncio
from udm_rest_client.udm import UDM
async def change_properties(dn, **changes):
async with UDM(
"USERNAME",
"PASSWORD",
"https://FQDN.OF.UCS/univention/udm",
ssl_ca_cert="ucs-root-ca.crt"
) as udm:
mod = udm.get("users/user")
obj = await mod.get(dn)
for property, value in changes.items():
setattr(obj.props, property, value)
await obj.save()
async def main():
await change_properties(
"uid=a.user,cn=users,BASE-DN",
firstname="newfn",
lastname="newln",
password="password123",
)
asyncio.run(main())
The class of the props
attribute also has a dict-like interface.
So the following two lines are equivalent:
obj.props.firstname = "Alice"
obj.props["firstname"] = "Alice"
The for
loop above could also have been written like this:
for property, value in changes.items():
obj.props[property] = value
Or could simply be replaced by:
obj.props.update(changes)
Move an object¶
Moving an object means changing its position in LDAP.
That happens whenever the DN changes.
The DN is created from the name of the object concatenated with the subtree in which the object is located.
So both changing a users username
(or a groups name
) attribute as well as changing an objects position
attribute initiates a move.
Behind the scenes the Python UDM REST Client will execute two modification on the UDM REST API: it will first apply the move and then any changes to the other properties in props
. But in the frontend it is sufficient to make the desired changes to the object and save()
once:
async with UDM(...) as udm:
mod = udm.get("users/user")
user_obj = await mod.get("uid=foo,cn=users,...")
user_obj.position = "ou=office,..."
user_obj.props.firstname = "bar"
await user_obj.save()
print(user_obj.dn) # new DN ("uid=foo,ou=office,...")
Options¶
The options
of an UDM object correspond approximately to LDAP objectClasses.
They are used to enable/disable attributes of LDAP objects and with that features.
For example UDM shares/share
objects support automatic creation of CIFS and NFS shares.
By default shares for both protocols will be created.
To disable the creation of an NFS share, the option
has to be disabled.
Note
In version 1.0.0 there was a breaking API change: The options
attribute of UDM objects is now a dictionary. It mirrors the UDM REST APIs options
attribute value. Before it was a list, which did not allow to disable default options.
The following example code removes the NFS feature from a share object:
async with UDM(...) as udm:
mod = udm.get("shares/share")
share_obj = await mod.get("cn=documents,cn=shares,...")
print(share_obj.options)
{'samba': True, 'nfs': True}
print(share_obj.props)
UdmObjectProperties({
...
'nfs_hosts': [],
'root_squash': True,
'sambaBlockSize': None,
...})
share_obj.options["nfs"] = False
await share_obj.save()
print(share_obj.options)
{'samba': True, 'nfs': False}
print(share_obj.props)
UdmObjectProperties({
# no more NFS properties
'sambaBlockSize': None,
...})
Correlation ID¶
A unique, random correlation ID will be sent with each request.
The value can be set, when creating the Session
object.
If not set, a random ID will be generated automatically.
The header name defaults to X-Request-ID
.
A different one can be set, by passing it with the request_id_header
argument to the Session
constructor.
The name of the header that is sent, will be in the header Access-Control-Expose-Headers
.
If an ID already exists, e.g. when inside a micro services chain, pass it on with Session(..., request_id="123abc")
.
Language Header¶
An Accept-Language
header can be sent with each request to get
localized error messages from the UDM
REST API.
The value can be set, when creating the UDM
Session object.
If not set, the Accept-Language
Header will not be sent.
When an Accept-Language
header is sent, the UDM REST API error messages
are translated into the corresponding language. (currently available
languages: German and English)
To set the Accept-Language
header, pass the language
attribute to the
UDM
constructor: UDM(..., language="de-DE")
.
It is also possible to change the Accept-Language
header within a
UDM
context using the set_language
method:
async with UDM(...) as udm:
mod = udm.get("users/user")
obj = await mod.get(...)
...
udm.set_language("de-DE")
obj = await mod.get(...)
In addition, the Accept-Language
header can be set for each request
individually by passing the language
attribute to the request method:
async with UDM(...) as udm:
mod = udm.get("users/user", language="de-DE")
Errors and exceptions¶
Detailed information about errors from the UDM REST Server are passed to
the UDM REST Client in the CreateError
and ModifyError
exceptions:
try:
await obj.save()
except CreateError as e:
# str with human readable error message
str(e)
# str with the error reason, e.g. "Unprocessable Entity"
e.reason
# None or str of the DN of the object
e.dn
# int of the HTTP status
e.status # int of the HTTP status
# None or dict with detailed information about the error, e.g.
# {'password': 'Password policy error: The password is too short, at least 8 characters needed!'}
e.error