Coder Social home page Coder Social logo

ipa-tuura's Introduction

ipa-tuura

Docker Repository on Quay

ipa-tuura is a bridge service that offers multiple Django apps for managing integration domains. Integration domains encompass identity and authentication realms, facilitating Create, Read, Update, and Delete (CRUD) operations for user and group identities, as well as user identity authentication methods. These apps provide REST API endpoints for various purposes:

  • Administrative Endpoint (domains app): This app allows you to add and remove integration domains and perform client enrollment of the bridge service in the integration domain. It supports integration with FreeIPA, LDAP and Active Directory.

  • SCIM v2 Endpoint (scim app): This app exposes endpoints following the SCIMv2 specification and it is based on the django-scimv2 project and enables you to read and write user and group identities from/to an integration domain.

  • Authentication Endpoint: ipa-tuura exposes endpoints for performing both GSSAPI-based authentication (/bridge/login_kerberos) and password-based authentication (/bridge/login_password), using identities provided provided by the integration domain. These endpoints return a session cookie that can be used for further operations that require authentication.

  • Credentials Validation (creds app): This app validates the presence and authenticity of specific user credentials from the enrolled integration domain.

Quick Start

The service is deployed as a systemd container. You can build a container image based on CentOS Stream by following these commands:

podman build -t centos-bridge -f Containerfile .

Alternatively, you can also build a production-ready RHEL image based on the same source code. Note that you need a Red Hat Developers account for building the image, or any other RHEL subscription if you have one:

subscription-manager register --username <username> --password <password>
podman build -t rhel-bridge --build-arg="BASE_IMAGE=registry.access.redhat.com/ubi9:latest" -f Containerfile .

You can also opt for pre-built image from Quay.io: quay.io/freeipa/ipa-tuura

Usage

The service can be deployed on a host using the following commands:

setsebool -P container_manage_cgroup true
podman run --name=bridge -d --privileged --dns <IP address> --add-host <host>:<IP address> -p 8000:8000 -p 3500:3500 -p 81:81 -p 443:443 --hostname <hostname> quay.io/freeipa/ipa-tuura
  • Where you need to provide host details such as:
  • DNS IP address: --dns <IP address>
  • The integration domain host, so that the bridge service can resolve the name: --add-host <host>:<IP address>
  • The hostname where the bridge is going to be deployed: --hostname <hostname>
  • The container image: quay.io/freeipa/ipa-tuura, updated on every release.

To enroll with an existing FreeIPA server, you can use the following CURL command:

curl -k -X POST "https://bridge.ipa.test/domains/v1/domain/" -H "accept: application/json" -H "Content-Type: application/json" -H "X-CSRFToken: x1yU9RGPKs4mJdWIOzEc7wKbwbnJ0B6iTHuW6ja0gdBpEOBVacK1vIhSSYlfsnRw" -d @freeipa_integration_domain.json"
  • Where freeipa_integration_domain.json is:
    {
    "name": "ipa.test",
    "description": "IPA Integration Domain",
    "integration_domain_url": "https://master.ipa.test",
    "client_id": "admin",
    "client_secret": "Secret123",
    "id_provider": "ipa",
    "user_extra_attrs": "mail:mail, sn:sn, givenname:givenname",
    "user_object_classes": "",
    "users_dn": "ou=people,dc=ipa,dc=test",
    "ldap_tls_cacert": "/etc/openldap/certs/cacert.pem"
    }

To un-enroll from an integration domain you can type:

curl -k -X DELETE "https://bridge.ipa.test/domains/v1/domain/1/" -H "accept: application/json" -H "X-CSRFToken: x1yU9RGPKs4mJdWIOzEc7wKbwbnJ0B6iTHuW6ja0gdBpEOBVacK1vIhSSYlfsnRw"

The project also supports 389ds server:

curl -k -X POST "https://bridge.ipa.test/domains/v1/domain/" -H "accept: application/json" -H "Content-Type: application/json" -H "X-CSRFToken: x1yU9RGPKs4mJdWIOzEc7wKbwbnJ0B6iTHuW6ja0gdBpEOBVacK1vIhSSYlfsnRw" -d @rhds_integration_domain.json"
  • Where rhds_integration_domain.json is:
    {
    "name": "ldap.test",
    "description": "LDAP Integration Domain",
    "integration_domain_url": "https://rhds.ldap.test",
    "client_id": "admin",
    "client_secret": "cn=Directory Manager",
    "id_provider": "ldap",
    "user_extra_attrs": "mail:mail, sn:sn, givenname:givenname",
    "user_object_classes": "",
    "users_dn": "ou=people,dc=ldap,dc=test",
    "ldap_tls_cacert": "/etc/openldap/certs/cacert.pem"
    }

and Active Directory:

curl -k -X POST "https://bridge.ipa.test/domains/v1/domain/" -H "accept: application/json" -H "Content-Type: application/json" -H "X-CSRFToken: x1yU9RGPKs4mJdWIOzEc7wKbwbnJ0B6iTHuW6ja0gdBpEOBVacK1vIhSSYlfsnRw" -d @ad_integration_domain.json"
  • Where ad_integration_domain.json is:
    {
    "name": "da.test",
    "description": "AD Integration Domain",
    "integration_domain_url": "ldap://ad.da.test",
    "client_id": "[email protected]",
    "client_secret": "Secret123",
    "id_provider": "ad",
    "user_extra_attrs": "mail:mail, sn:sn, givenname:givenname",
    "user_object_classes": "",
    "users_dn": "cn=Users,dc=da,dc=test",
    "ldap_tls_cacert": "/etc/openldap/certs/cacert.pem"
    }

Once the bridge service is enrolled to an integration domain, you can start using SCIMv2 app. Frist you need to get a cookie with simple authentication:

curl -k -s -X POST --data 'username=scim&password=Secret123' -c /tmp/my.cookie -b csrftoken=XzLJ9NmZTQNQcXS6v3JCNUTnV6gFVorJ -H Accept:text/html -H Content-Type:application/x-www-form-urlencoded -H 'X-CSRFToken: XzLJ9NmZTQNQcXS6v3JCNUTnV6gFVorJ' -H referer:https://bridge.ipa.test:443/admin/login/ https://bridge.ipa.test/admin/login/
  • Where:
`bridge.ipa.test` is the host that is running the bridge service.

and this is how you can add a user using a CURL command:

curl -k --header 'Authorization: Basic ' -b /tmp/my.cookie -s --request POST --data @ipauser.json --header 'Content-Type: application/scim+json' https://bridge.ipa.test/scim/v2/Users
  • Where @ipauser.json is:
 {
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "ftrivino",
    "name":
    {
        "givenName": "Francisco",
        "middleName": "Garcia",
        "familyName": "Trivino"
    },
    "emails":
    [{
        "primary": true,
        "value": "[email protected]",
        "type": "work"
    }],
    "displayName": "ftrivino",
    "externalId": "extId",
    "meta":
    {
        "resourceType":"User"
    }
    "groups": [],
    "active": true
    }

Real Use Case

One significant use case for this project is to replace Keycloak User Federation Storage. You can set up your own Keycloak instance and install the following plugin:

SCIM Keycloak User Storage SPI

Once you deploy your Keycloak instance and install the plugin, you can navigate to the User Federation Storage tab and enroll in an integration domain by providing the required integration domain fields at the SCIM user storage plugin configuration in keycloak.

Keycloak integration domain

As an example, we can authenticate in Nextcloud by using Keycloak through the OpenID Connect user backend, as documented here. Assuming there is an integration domain already added to Keycloak using ipa-tuura, we will be able to seamlessly authenticate using users from our provider. Additionally, GSSAPI authentication can be performed in case you have a valid Kerberos ticket available and your browser correctly configured:

  • Mozilla Firefox: add the realm to network.negotiate-auth.trusted-uris in about:config.
  • Google Chrome: run with --auth-server-whitelist="<keycloak hostname>" parameter.

Existing limitations

  • The bridge can currently only handle user identities.
  • Only one integration domain is allowed per container. The domains app implements a singleton class allowing only one active integration domain. However, you can delete the existing one and enroll to a different system.
  • The bridge service is deployed as a privileged container; however, it is recommended to deploy it as non-privileged to follow best practices for container service deployment. This is because SSSD service is not currently rootless.

Developer documentation

Django preparation

Create and activate a python virtual env

python3 -m venv --system-site-packages ipatuura-env
source ipatuura-env/bin/activate

Install the requirements

pip install -r src/install/requirements.txt

Apply migrations

cd src/ipa-tuura
python manage.py migrate

Create the djangoadmin user and start the ipa-tuura server

Note: do not use "admin" name as it conflicts with IPA "admin" user

python manage.py createsuperuser
python manage.py runserver

If connecting from another system, update the ALLOWED_HOSTS line root/settings.py

ALLOWED_HOSTS = ['192.168.122.221', 'localhost', '127.0.0.1']

as well as the NETLOC from SCIM_SERVICE_PROVIDER settings:

SCIM_SERVICE_PROVIDER = {
    'NETLOC': 'localhost',
...

and replace localhost by the IP address or hostname where the service is deployed. This way, the /ServiceProviderConfig endpoint will return the location of the app implementing the SCIM api.

Finally, run the following to have django listen on all interfaces:

python manage.py runserver 0.0.0.0:8000

This command will start a lightweight development web server on the local machine.

Documentation

This project uses Sphinx as a documentation generator. Follow these steps to build the documentation:

cd docs/
make venv
make html

The generated documentation will be available at docs/_build/html/ folder.

ipa-tuura's People

Contributors

alexey-tikhonov avatar antoniotorresm avatar f-trivino avatar flo-renaud avatar justin-stephenson avatar spoore1 avatar tiboris avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ipa-tuura's Issues

Interoperability issues between Domains and SCIM apps

The current implementation faces interoperability issues between the domains app, which serves as the administrative interface for managing integration domains, and the SCIM app, responsible for read and write operations to and from these domains. The writability of the interface is contingent upon specific settings within the integration domain.

Integration domains are not seamlessly interacting with the SCIM app, leading to potential synchronization problems.

The writable interface is not resetting appropriately after the addition of a new integration domain.

RFE: replace internal django HTTP runserver by Apache/nginx

Runserver is not intended for production as it doesn’t support HTTPS, instead we need to deploy the bridge service with WSGI platform in a container. This way, we will be able to start serving API HTTPS requests. The deployment must be container friendly.

Finally, the different services must redirect everything into HTTPS, only HTTPS based communication should be allowed.

https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/

https://medium.com/@adamsokode/deploying-django-app-inside-container-running-apache-mod-wsgi-73831aa04724

AD users missing attributes

When testing with AD, it appears that ipa-tuura is creating the users but, there are a couple missing attributes needed to enable them to be used.

Without the attributes:

PS C:\cygwin64\home\Administrator> id kcuser101                                                          
/usr/bin/id: 'kcuser101': no such user                                                                   

With the attributes, you should see:

PS C:\cygwin64\home\Administrator> id kcuser107
uid=1049687(kcuser107) gid=1049089(Domain Users) groups=1049089(Domain Users)

Minimum attributes needed that I've found so far:
userAccountControl set to 66048 (65536=don't expire password, 512=normal account
sAMAccountName set to username

Unsure if there are others but, adding those enables the account and sets SamAccountName so that it can be seen from PS on Windows and SSSD on Linux.

Applying image updates to a running container make the service to stop working

Issue

After applying updates to a running container, the service stops working.

Steps to Reproduce

  1. Deploy for the first time:
    podman run --name=bridge -d --privileged --dns --add-host idm.ipa.test: -p 8000:8000 -p 3501:3500 -p 4701:81 -p 4430:443 --hostname bridge.ipa.test
  2. service works
  3. sudo podman pull image
  4. sudo podman stop bridge
  5. sudo podman rm -a
  6. podman run --name=bridge -d --privileged --dns --add-host idm.ipa.test: -p 8000:8000 -p 3501:3500 -p 4701:81 -p 4430:443 --hostname bridge.ipa.test

Actual behavior

After applying updates the service doesn't work.

"Cannot connect to provided URL!"

from error_log: [Wed Nov 29 08:11:50.272546 2023] [ssl:info] [pid 104:tid 322] SSL Library Error: error:0A000416:SSL routines::sslv3 alert certificate unknown (
SSL alert number 46)

Expected behavior

Service should work.

realm join failing to AD domain

Adding an AD domain from Keycloak with the SCIM user storage plugin, it looks like the domain is properly added. However, when I check on the ipa-tuura bridge container, SSSD isn't configured and I see errors in the journal for the realm join.

bridge_ad_join2.log

Iipa-tuura package creation (github)

I am asking any owner of freeipa organization to enable packages for an organization freeipa At this this page you should be able to enable public packages to be created at least for this project. It will help us to publish container images and use ghcr.io per pull rewuest to test changes and store containers.

ISSUE: IPA domain needs ldap_user_extra_attrs in sssd.conf

When an IPA Integration Domain is enabled and setup, the sssd.conf file is missing the ldap_user_extra_attrs setting in the domain section.

When the setting is missing, I'm unable to see IPA users reflected in Keycloak. To resolve the issue, I'm adding the following after setting up an IPA Integration Domain:

ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname

failure adding user in ldap when domain requires custom user_object_classes

I'm testing with a 389 Directory Server that is setup on Fedora 38 like this:

dnf -y install 389-ds-base cockpit-389-ds

cat > /tmp/instance.inf <<EOF
[general]
config_version = 2

[slapd]
root_password = Secret123

[backend-userroot]
sample_entries = yes
suffix = dc=ldap,dc=test
EOF

dscreate from-file /tmp/instance.inf

I used Keycloak 17 with the Storage Plugin from here:
https://github.com/justin-stephenson/scim-keycloak-user-storage-spi/tree/kc17_test_user_extra_attrs_string

In Keycloak for LDAP User Object Classes, I added:
posixAccount, nsPerson, nsAccount, nsOrgPerson

When I add a user in Keycloak, I'm seeing an error from ipa-tuura and the user account does not appear to be added to LDAP. I see this in the journal:

Sep 26 22:12:06 bridge.ipa.test python3[204]: Unable to complete SCIM call.                              
Sep 26 22:12:06 bridge.ipa.test python3[204]: Traceback (most recent call last):                         
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/www/ipa-tuura/src/ipa-tuura/scim/ipa.py", line 353, in modify
Sep 26 22:12:06 bridge.ipa.test python3[204]:     self._conn.modify_ext_s(dn, mod_attrs)                 
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/usr/lib64/python3.11/site-packages/ldap/ldapobject.py", line 400, in modify_ext_s
Sep 26 22:12:06 bridge.ipa.test python3[204]:     resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all=1,timeout=self.timeout)
Sep 26 22:12:06 bridge.ipa.test python3[204]:                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/usr/lib64/python3.11/site-packages/ldap/ldapobject.py", line 543, in result3
Sep 26 22:12:06 bridge.ipa.test python3[204]:     resp_type, resp_data, resp_msgid, decoded_resp_ctrls, retoid, retval = self.result4(
Sep 26 22:12:06 bridge.ipa.test python3[204]:                                                                            ^^^^^^^^^^^^^
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/usr/lib64/python3.11/site-packages/ldap/ldapobject.py", line 553, in result4
Sep 26 22:12:06 bridge.ipa.test python3[204]:     ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
Sep 26 22:12:06 bridge.ipa.test python3[204]:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/usr/lib64/python3.11/site-packages/ldap/ldapobject.py", line 128, in _ldap_call
Sep 26 22:12:06 bridge.ipa.test python3[204]:     result = func(*args,**kwargs)                          
Sep 26 22:12:06 bridge.ipa.test python3[204]:              ^^^^^^^^^^^^^^^^^^^^                          
Sep 26 22:12:06 bridge.ipa.test python3[204]: ldap.NO_SUCH_OBJECT: {'msgtype': 103, 'msgid': 2, 'result': 32, 'desc': 'No such object', 'ctrls': [], 'matched': 'ou=people,dc=ldap,dc=test'}
Sep 26 22:12:06 bridge.ipa.test python3[204]: During handling of the above exception, another exception occurred:
Sep 26 22:12:06 bridge.ipa.test python3[204]: Traceback (most recent call last):                         
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/usr/local/lib/python3.11/site-packages/django_scim/views.py", line 112, in dispatch
Sep 26 22:12:06 bridge.ipa.test python3[204]:     return super(SCIMView, self).dispatch(request, *args, **kwargs)
Sep 26 22:12:06 bridge.ipa.test python3[204]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
Sep 26 22:12:06 bridge.ipa.test python3[204]:     return handler(request, *args, **kwargs)               
Sep 26 22:12:06 bridge.ipa.test python3[204]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^               
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/usr/local/lib/python3.11/site-packages/django_scim/views.py", line 372, in put
Sep 26 22:12:06 bridge.ipa.test python3[204]:     scim_obj.save()                                        
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/www/ipa-tuura/src/ipa-tuura/scim/adapters.py", line 133, in save
Sep 26 22:12:06 bridge.ipa.test python3[204]:     ipa_if.user_mod(self)                                  
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/www/ipa-tuura/src/ipa-tuura/scim/ipa.py", line 417, in user_mod
Sep 26 22:12:06 bridge.ipa.test python3[204]:     self._apiconn.modify(scim_user)                        
Sep 26 22:12:06 bridge.ipa.test python3[204]:   File "/www/ipa-tuura/src/ipa-tuura/scim/ipa.py", line 357, in modify
Sep 26 22:12:06 bridge.ipa.test python3[204]:     raise LDAPNotFoundException(                           
Sep 26 22:12:06 bridge.ipa.test python3[204]: scim.ipa.LDAPNotFoundException: User testldapuser1 not found

EDIT:

I should note that on the 389 server, I enabled the DNA plugin to handle automatic UID/GID assignment when I was troubleshooting why SSSD could not see the users in LDAP. That's when I also tried adding the custom User Object Classes.

DNA plugin config:

dn: cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectClass: top
objectClass: nsSlapdPlugin
objectClass: extensibleObject
objectClass: nsContainer
cn: Distributed Numeric Assignment Plugin
nsslapd-pluginInitfunc: dna_init
nsslapd-pluginType: bepreoperation
nsslapd-pluginEnabled: on
nsslapd-pluginPath: libdna-plugin
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: Distributed Numeric Assignment
nsslapd-pluginVersion: 2.1.8
nsslapd-pluginVendor: 389 Project
nsslapd-pluginDescription: Distributed Numeric Assignment plugin

# UID and GID numbers, Distributed Numeric Assignment Plugin, plugins, config
dn: cn=UID and GID numbers,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectClass: top
objectClass: extensibleObject
cn: UID and GID numbers
dnaType: uidNumber
dnaType: gidNumber
dnaMaxValue: -1
dnaMagicRegen: 0
dnaFilter: (|(objectclass=posixAccount)(objectclass=posixGroup))
dnaScope: dc=example,dc=com
dnaNextValue: 99999

Allow to configure encryption types during AD domain addition

You might want to allow encryption type list be configurable. There are plenty of environments where people are still using RC4 (sorry) or AES128-SHA1. Also, with Windows Server 2025 there will be support for RFC8009 encrytpion types (SHA2-based) so it is best to remove the hard-coded encryption lines here and instead add a configuration with sensible defaults.

Originally posted by @abbra in #88 (comment)

Adding IPA integration domain is broken

This curl call:

curl -k -X POST "https://bridge.ipa.test:4430/domains/v1/domain/" -H "accept: application/json" -H "Content-Type: application/json" -H "X-CSRFToken: x1yU9RGPKs4mJdWIOzEc7wKbwbnJ0B6iTHuW6ja0gdBpEOBVacK1vIhSSYlfsnRw" -d "{ \"name\": \"ipa.test\", \"description\": \"IPA Integration Domain\", \"integration_domain_url\": \"https://master.ipa.test\", \"client_id\": \"admin\", \"client_secret\": \"Secret123\", \"id_provider\": \"ipa\", \"user_extra_attrs\": \"mail:mail, sn:sn, givenname:givenname\", \"user_object_classes\": \"\", \"users_dn\": \"ou=people,dc=ipa,dc=test\", \"ldap_tls_cacert\": \"/etc/openldap/certs/cacert.pem\"}"

results in:

[Wed Nov 29 08:18:06.228224 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966] HTTP connection keep-alive (idm.ipa.test)
[Wed Nov 29 08:18:06.513683 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966] ipa: role_member_add result {'completed': 1, 'faile
d': {'member': {'privilege': ()}}, 'result': {'cn': ('ipatuura writable interface',), 'member_service': ('ipatuura/[email protected]',), 
'memberof_privilege': ('User Administrators',), 'dn': 'cn=ipatuura writable interface,cn=roles,cn=accounts,dc=ipa,dc=test'}}
[Wed Nov 29 08:18:07.704047 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966] Internal Server Error: /domains/v1/domain/
[Wed Nov 29 08:18:07.704075 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966] Traceback (most recent call last):
[Wed Nov 29 08:18:07.704079 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/djan
go/core/handlers/exception.py", line 55, in inner
[Wed Nov 29 08:18:07.704083 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     response = get_response(request)
[Wed Nov 29 08:18:07.704087 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/djan
go/core/handlers/base.py", line 197, in _get_response
[Wed Nov 29 08:18:07.704091 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     response = wrapped_callback(request, *callback_
args, **callback_kwargs)
[Wed Nov 29 08:18:07.704094 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/djan
go/views/decorators/csrf.py", line 56, in wrapper_view
[Wed Nov 29 08:18:07.704098 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     return view_func(*args, **kwargs)
[Wed Nov 29 08:18:07.704101 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/rest
_framework/viewsets.py", line 125, in view
[Wed Nov 29 08:18:07.704105 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     return self.dispatch(request, *args, **kwargs)
[Wed Nov 29 08:18:07.704109 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/rest
_framework/views.py", line 509, in dispatch
[Wed Nov 29 08:18:07.704112 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     response = self.handle_exception(exc)
[Wed Nov 29 08:18:07.704116 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/rest
_framework/views.py", line 469, in handle_exception
[Wed Nov 29 08:18:07.704120 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     self.raise_uncaught_exception(exc)
[Wed Nov 29 08:18:07.704123 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/rest
_framework/views.py", line 480, in raise_uncaught_exception
[Wed Nov 29 08:18:07.704127 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     raise exc
[Wed Nov 29 08:18:07.704130 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/usr/local/lib/python3.9/site-packages/rest
_framework/views.py", line 506, in dispatch
[Wed Nov 29 08:18:07.704134 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     response = handler(request, *args, **kwargs)
[Wed Nov 29 08:18:07.704137 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/www/ipa-tuura/src/ipa-tuura/root/../domain
s/views.py", line 45, in create
[Wed Nov 29 08:18:07.704141 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     raise e
[Wed Nov 29 08:18:07.704145 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/www/ipa-tuura/src/ipa-tuura/root/../domain
s/views.py", line 41, in create
[Wed Nov 29 08:18:07.704148 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     add_domain(serializer.validated_data)
[Wed Nov 29 08:18:07.704152 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/www/ipa-tuura/src/ipa-tuura/root/../domain
s/utils.py", line 482, in add_domain
[Wed Nov 29 08:18:07.704155 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     ipa = IPA()
[Wed Nov 29 08:18:07.704159 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/www/ipa-tuura/src/ipa-tuura/root/../scim/i
pa.py", line 443, in IPA
[Wed Nov 29 08:18:07.704162 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     _IPA._instance = _IPA()
[Wed Nov 29 08:18:07.704176 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]   File "/www/ipa-tuura/src/ipa-tuura/root/../scim/i
pa.py", line 410, in __init__
[Wed Nov 29 08:18:07.704180 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966]     self._apiconn = self._write(domains.models.Doma
in.objects.last().id_provider)
[Wed Nov 29 08:18:07.704184 2023] [wsgi:error] [pid 102:tid 243] [remote 10.45.225.10:38966] AttributeError: 'NoneType' object has no attribute 
'id_provider'

ISSUE: naming of the django apps is confusing

Currently, the django project (ipa-tuura) is composed by:

  • ipa-tuura app
  • creds app
  • domains app

ipa-tuura app is actually the scimv2 app so that the following naming would make more sense:

  • scim app
  • creds app
  • domains app

also the project name could be renamed to ipatuura.

New AD users not seen in Keycloak

I am able to setup an Integration domain in Keycloak to an AD domain. If I add a user in Keycloak, I see it replicated to AD. However, if I add a new user in AD, I do not see it in Keycloak.

I will add more details soon.

RFE: Protect Authentication and Authorization of the SCIMv2 Service with OAuth2 Bearer Token Authentication.

The SCIM 2.0 protocol supports multiple HTTP-based authentication schemes to enable API access by some SCIM clients. Currently, only httpbasic is supported and there is no Authorization defined. The aim of this ticket is to implement support for Oauth2 with bearer token.

The new auth scheme should be exposed in the “/ServiceProviderConfig” endpoint for the auto-discovery service.

OAuth2 Bearer Token allows the authentications to be delegated to a OIDC server outside of the SCIM API implementation apart from making the auth mech compatible with OIDC. The best security practices related to bearer tokens (like TLS transport, limited scoping, short lifetimes) must be enforced.

Ideally, we should also define authorization scopes such as scim read and scim write so that the client can request the minimum access to the API.

ISSUE: LDAP provider integration

After adding a SCIM plugin with the LDAP integration domain, I needed to change in sssd.conf as it was 'dn=ldap, dn=test'

ldap_search_base = dc=ldap, dc=test
and also add
ldap_default_authtok = Password

This allowed me to id the user, but infopipe will not find the correct user attributes if the default user LDAP schema does not contain sn or givenName.

ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname

A solution should be investigated, which requires consideration for different LDAP schemas that SSSD can work with.

ISSUE: Implement better error handling for the Domain app

A call to delete a domain with a wrong id does not return any error, IMO it should mention something like "No such domain".

If a wrong client id/password is provided, ipa-client-install fails but this error is not well handled

RFE: split users_dn so that user can use different OUs for READ and WRITE

Currently, the domains app exposes users_dn field so that admin can specify the full DN of LDAP tree where users are, basically the distinguished name (DN) of the Organization Unit (OU) that holds the user accounts. The aim of this ticket is to split users_dn into two fields so that the admin can decouple different OUs with READ and WRITE permissions.

Support password change

It would be awesome if we could support password change e.g. on password expiration events.

This is especially acute as freeipa by default requires that users change their password on first logon.

ISSUE: Better handling of concurrent Domain request handling

if 2 calls are done to add the same domain, the REST API does not complain but we end up with 2 domains in the sql db and only one in sssd.conf. Removing any of these domains results in an inconsistency (one remaining domain in sql, but no domain in sssd.conf).

User lookup fails in keycloak due to null familyName and null givenName

[root@client ~]# ipa user-show testuser1 --all --raw
  dn: uid=testuser1,cn=users,cn=accounts,dc=ipa,dc=test
  uid: testuser1
  givenname: test
  sn: user
  cn: testuser1
  initials: tu
  homedirectory: /home/testuser1
  gecos: test user
  loginshell: /bin/sh
  krbcanonicalname: [email protected]
  krbprincipalname: [email protected]
  mail: [email protected]
  uidnumber: 1319600004
  gidnumber: 1319600004
  nsaccountlock: FALSE
  has_password: FALSE
  has_keytab: FALSE
  displayName: test user
  ipaNTSecurityIdentifier: S-1-5-21-3608036487-284666822-748930798-1004
  ipaUniqueID: 2c791fd0-1ff1-11ee-abe2-fa163e14acb1
  memberof: cn=ipausers,cn=groups,cn=accounts,dc=ipa,dc=test
  mepManagedEntry: cn=testuser1,cn=groups,cn=accounts,dc=ipa,dc=test
  objectClass: top
  objectClass: person
  objectClass: organizationalperson
  objectClass: inetorgperson
  objectClass: inetuser
  objectClass: posixaccount
  objectClass: krbprincipalaux
  objectClass: krbticketpolicyaux
  objectClass: ipaobject
  objectClass: ipasshuser
  objectClass: ipaSshGroupOfPubKeys
  objectClass: mepOriginEntry



[root@client ~]# curl -b cookies.txt -X POST -d @filter_testuser1.json "http://127.0.0.1:8000/scim/v2/Users/.search" |json_pp 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   665  100   551  100   114  22569   4669 --:--:-- --:--:-- --:--:-- 30227
{
   "Resources" : [
      {
         "active" : true,
         "displayName" : "testuser1",
         "emails" : [
            {
               "primary" : true,
               "value" : "[email protected]"
            }
         ],
         "externalId" : null,
         "groups" : [],
         "id" : "1319600004",
         "meta" : {
            "location" : "https://localhost/scim/v2/Users/1319600004",
            "resourceType" : "User"
         },
         "name" : {
            "familyName" : null,
            "formatted" : "testuser1",
            "givenName" : null
         },
         "schemas" : [
            "urn:ietf:params:scim:schemas:core:2.0:User"
         ],
         "userName" : "testuser1"
      }
   ],
   "itemsPerPage" : 50,
   "schemas" : [
      "urn:ietf:params:scim:api:messages:2.0:ListResponse"
   ],
   "startIndex" : 1,
   "totalResults" : 1
}



2023-07-11 10:15:12,242 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-31) Uncaught server error: com.fasterxml.jackson.databind.JsonMappingException: Cannot invoke "String.equals(Object)" because the return value of "org.keycloak.models.UserModel.getFirstName()" is null
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._wrapAsIOE(DefaultSerializerProvider.java:509)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:482)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:400)
        at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1514)
        at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1007)

RFE: implement Integration Domain UnitTests with Mock

The view integration domain unit tests end calling the corresponding POST request for domain enrollment. We don't really want to enroll with an integration domain as we will need to add more infra to the GitHub Actions (e.g. IPA/LDAP/ADDC servers)...

This RFE is all about to implement mocks for the app REST-API calls, a JSON should be returned instead of enrolling with a domain.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.