Virtual sprint to improve the SAML story in Plone - dm.zope.saml2 and collective.saml2 [Proposal]

Continuing the discussion from Trying to troubleshoot Saml2 SSO between Zulip and Plone:

Let me start by saying, SAML2 works with enough effort. The proposal that follows is with the goal of improvement.

I'd love to see some improvements to the SAML story on Plone. Anyone open to a mini virtual sprint some time in July or August? I would really appreciate some feedback on this idea.
@dieter, is this something you're able to support (mostly because you're the author and maintainer on pypi), even to be available to support releasing the updates to pypi?

Merging useful code
Looking at the forking history of dm.zope.saml2, it seems that some "good stuff" hasn't made it back to pypi.

Examples of interesting code:
On the Jazkarta fork, making use of the came_from variable for redirects
On the collective fork, disabling csrf on post

Adding new capabilities

  • I'd like to be able to force attributes to be returned from dm.zope.saml2 when acting as an Identity Provider (IdP), especially when they aren't requested by the SP (mostly because I have an issue with Zulip, which does not request attributes as an SP)
  • I'd love a simple control panel implemented in collective.saml2

Proposed goals

  1. Review and merge useful changes, already implemented on some of the forks, back to dm.zope.saml2
  2. Make the collective branch the authoritative branch for dm.zope.saml2 (assuming there are no issues with this)
  3. Fix collective.saml2 to work with Python 3 (It looks like simply changing the dependency info for PyXB). There's already an issue logged for this
  4. Deploy updates to pypi

Stretch goals

  1. Enhance collective.saml2 to implement a control panel in Plone
1 Like

dm.zope.saml2 is maintained in a local repository -- not on github. All forks are unofficial and not supported by me.

For some enhancements, I might be persuaded to accept patches -- but not for any enhancement. For example, I will refuse to add logic to support SAML entities with missing or incomplete metadata description: there are easy workarounds outside dm.zope.saml2.

:point_up: so moving it to the collective will be an issue?

What about the other capabilities mentioned above?:point_down:

and forcing attributes to be returned even if not requested with RequestedAttribute.

I just want to be clear on the constraints.

2 Likes

So there is no official dm.zope.saml2 repository on github?

When I install version 4.0.3, I need to add the package to buildout's zcml. This shouldn't be necessary. It looks like a bug to me. Where can I report this?

Wesley Barroso Lopes via Plone Community wrote at 2024-6-5 18:20 +0000:

So there is no official dm.zope.saml2 repository on github?

Right.

When I install version 4.0.3, I need to add the package to buildout's zcml. This shouldn't be necessary. It looks like a bug to me. Where can I report this?

You can send an email to the author (i.e. me).

But, I can already tell you, that I have not used z3c.autoinclude
by purpose (to include the project's ZCML):
it is possible that you have to repackage the ZCML delivered with
dm.zope.saml2 and this is easier whan it is not activated automatically.
An example are some zope.formlib extensions which are important
for dm.zope.saml2 (and therefore registered in its zcml) but which
may conflict with your own setup.

Oh, OK! So you didn't use z3c.autoinclude on purpose. If you've already analyzed this, that's fine. I loaded his zcml into my package:

<configure
 xmlns="http://namespaces.zope.org/zope"
 i18n_domain="package">

 <include package="dm.zope.saml2" />

</configure>

Another thing I saw (which you've probably already noticed too), is that dm.saml2 uses pyxb, but doesn't declare it as a dependency.

Wesley Barroso Lopes via Plone Community wrote at 2024-6-5 21:31 +0000:

...
Another thing I saw (which you've probably already noticed too), is that dm.saml2 uses pyxb, but doesn't declare it as a dependency.

It does not use PyXB directly but indirectly via dm.saml2.

dm.saml2 used to declare the PyXB dependency.
Unfortunately, the original author of PyXB has stopped its development
and the offical PyXB distribution no longer works with modern Python
versions.
There are unofficial PyXB forks compatible with mondern Python
versions.

I am using PyXB-CTC with Python 3.10; but I had to download
the source distribution and generate the SAML2 bundles myself.
Potentially, this is no longer necessary with a new PyXB-CTC version.

Due to those problems, dm.saml2 no longer declares the
PyXB dependency.
Depending on what Python version you are using, you must
use different PyXB variants/forks; in addition, you
may need to generate the SAML2 bundles.
All this is explained in the dm.saml2 documentation.

I've started a branch to add tests. That helps ensure it works with python 3.

But it's tricky and any help would be appreciated.

It would also be great to have a Volto control panel to make it easy to setup, esp where the metadata url doesn't exist.

@dieter I managed to install dm.zope.saml2 on a Plone 4.3 with Python 2 on a CentOS 7. I used the OS libs. But when it reaches line 19 of the file dm.xmlsec.binding-2.2-py2.7-linux-x86_64.egg/dm/xmlsec/binding/__init__.py an error occurs and the process stops without a traceback. The line in question is this:

transformByHref = dict((t.href, t) for t in transforms)

More specifically in t.href. Do you know what it could be? Any help is useful.

In a non-Plone installation, one occurs: Segmentation fault

Python 2.7.18 (default, Aug  1 2022, 12:58:53) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dm.xmlsec.binding
Segmentation fault (core dumped)

In a non-Plone installation, this solved the problem:

It will probably resolve in Plone too.

Wesley Barroso Lopes via Plone Community wrote at 2024-6-6 20:33 +0000:

@dieter I managed to install dm.zope.saml2 on a Plone 4.3 with Python 2 on a CentOS 7. I used the OS libs. But when it reaches line 19 of the file dm.xmlsec.binding-2.2-py2.7-linux-x86_64.egg/dm/xmlsec/binding/__init__.py an error occurs and the process stops without a traceback. The line in question is this:

transformByHref = dict((t.href, t) for t in transforms)

More specifically in t.href. Do you know what it could be? Any help is useful.

I have seen problems like this with an incompatible (C-) library
libxmlsec1.

dm.xmlsec.binding is a cython generated binding for
the C-library libxmlsec1.
Because most users do not have cython installed, dm.xmlsec.binding
contains pregenerated C sources. Obviously, they have been
generated with a specific version of libxmlsec1.
If you use a different version, there will be an incompatibility risk.

With the problem I mentioned above, a newer libxmlsec1 version
has dropped support for a formerly supported transform.
As a consequence, the linker could not resolve a corresponding symbol to
libxmlsec1 and set the corresponding variable to NULL.
When Python accessed the variable, a SIGSEGV terminated the process.
Your problem seems similar.

I have a report that dm.xmlsec.binding can no longer be
compiled for libxmlsec1 >= 1.2.39.
The problem likely is that those versions no longer
support the HmacMd5 transform.

I have no easy access to those newer libxmlsec1 versions
and therefore have not yet worked on this problem.

Could you check your libxmlsec1 version and whether it
is problematic?
If so, I could tell you how to patch the dm.xmlsec.binding
source and if the problem disappears with the patch,
make a new release with it.

An alternative workaround:
You could find out which transforms make problems
and remove them from the list of transforms.

For this, you would add temporary code to dm.xmlsec.binding.__init__
after the transforms = ....
The added code would be:

from sys import stdout
for i, t in enumerate(transforms):
  print(i); stdout.flush(); t.href
else: print("success")

The process will dies (with SIGSEGV) as soon as you hit
the first no longer supported transform. This means,
that if you do not see "success", the last i you see indicates the
last still supported transform.
You can then permanently add del transforms[i + 1] to remove the
no longer supported transform.

If more transforms are affected, you repeat the process until you
see "success".

Wesley Barroso Lopes via Plone Community wrote at 2024-6-6 20:51 +0000:

In a non-Plone installation, this solved the problem:

dm.xmlsec.binding broken? · Issue #30 · SAML-Toolkits/python-saml · GitHub

Wow! A problem from 2014!

I just noticed an error in my previous message:
i does not indicate the last supported transform but
the first non supported one.

My version of libxmlsec1 is 1.2.20

I compiled again without CFLAGS=-DXMLSEC_NO_SIZE_T and the error occurred again. It seems like everyone has a problem. I went as far as deleting 15. I also tried just sounding the last item and it also had a problem.

But everything worked when I compiled it with CFLAGS=-DXMLSEC_NO_SIZE_T