Repository navigation
KEYCLOAK-19866 Fix user-defined-/anyType parsing and introduce XPathAttributeMapper - #10650
Conversation
|
I cannot comment on whether this fits in with the guidelines and conventions within the code base but from a purely functional point of view this looks promising. It allows us to work with complex XML types with relative ease and removes the need for a customized keycloak. I got it up and running and can confirm that this works as expected. A bit of documentation or examples might be helpful. I figured out how to use the included Mapper but had to refer to the source code to realize that the XPath must be relative to the SAML Attribute, not the SAML Assertion. |
There was a problem hiding this comment.
Thank you for creating this pull request. I can see that this offers a very flexible way to extract information from SAML and that it will be useful to a lot of users.
@hmlnarik asked me to review it, please find my comments below.
Please let me know if any of my comments leaves open questions, or if you think any of the suggestions doesn't fit the context of this pull quest.
I'm looking forward to you replies or an updated pull request.
|
@ahus1: I agree to and basically implemented all of your suggestions in 5dec051. Comments:
Is there anything else I can or have to do? |
There was a problem hiding this comment.
Thanks for updating this PR, looking at the new functionality this looks now good to me.
As this is your first PR to the Keycloak project, the GitHub actions don't run automatically to provide feedback. They will require a manual approval by a maintainer.
I ran some unit tests on the SAML module using
mvn clean install -am -pl saml-core
and I see that there are two failing tests:
[ERROR] Failures:
[ERROR] SAMLParserTest.testSaml20AssertionExample:1007 expected:<[<saml:AttributeValue xsi:type="xs:anyType" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">060D00000000SHZ
</saml:AttributeValue>]> but was:<[060D00000000SHZ]>
[ERROR] SAMLParserTest.testSaml20AssertionsAdviceTag:1137
Expected: iterable containing [is "060D00000000SHZ"]
but: item 0: was "<saml:AttributeValue xsi:type=\"xs:anyType\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">060D00000000SHZ\n </saml:AttributeValue>"
[INFO]
[ERROR] Tests run: 85, Failures: 2, Errors: 0, Skipped: 0
Maybe something broke during refactoring, please have a look.
In addition to that, I'd prefer if you could rebase your PR with the lastest changes onto main. This will ensure that your changes work well with the latest changes in the main branch, even when there are no code conflicts.
Please some additional small review comments below.
|
Sorry for closing it ... rebased to main, changed the help text (two better examples) and added some trace logging to help getting the right xpath. Now checking the unit tests. |
|
@KnauerSecunet - good to see it the PR back open and no worries! Please let me know when you got any questions or code I should look into! |
|
@ahus1 Yeah the test gave me some more insight what's possible already and what let to exceptions: I guess my change should not change the result for case 1a/b (or anything in
Then case 2 would behave similar to an anyType of case 1, but I lose the AddressType type (any better ideas?). case 3 and case 4 also return similar results (and no longer throw exceptions). |
|
I had a look at the code an tried different variants. Yes, the existing parsing should remain the same. On the other hand I see that there is some inconsistency how values are returned. Here's some variants, I probably need to discuss with @hmlnarik what's best here, and if we could afford to break the existing behavior:
|
|
Thinking a bit more, a consistent way with the existing logic would be to return an XML fragment, and to never return the |
|
Reading yesterday's comments, they sound rather draft and exploring. After a night's sleep, I suggest the following:
With regards to namespace handling in SAMLAttributeValueParser: While my namespace handling is rusty, I suppose any namespace on the attributeValue that would be relevant for its children might as well be declared on the children, so they can be preserved even if the attributeValue tag is not part of the fragment. @KnauerSecunet, @hmlnarik - what do you think about this suggestion? I know this different from the original suggestion, still I see that it matches the behavior in the existing tests. This drops the information in |
As I understand it your draft and the proposed solution are the same: Both return the xml string (fragmet) including namespace and the mapper handles the missing root tag? It won't be that easy for the mapper to recognize a missing root element but basically I like that idea very much and think it would be feasible. The missing xml-type also came to my mind, but I actually think it should be possible to rely on the attribute name (which can be configured/filtered in the xpath mapper). @ahus1 Works for me, just waiting for your go when you get the projects feedback ... |
|
@KnauerSecunet - thanks for the feedback. Regarding the root tag: I'd suggest that the mapper will always wrap the string it receives within the root tag. That will make it simpler to implement, and it would not depend on the number of siblings in the string. Any user who would use an XPath with "//" wouldn't notice it, anyway IMHO. I'll update this issue once I get feedback from the project. |
I agree with this approach, and agree also with the proposal to propagate namespaces to the first-level tags of the value as suggested here:
|
There was a problem hiding this comment.
@KnauerSecunet - after talking to @hmlnarik today, the suggested approach is now generally approved (thank you, @hmlnarik!).
While the new code uses the safe XXE methods, he also asked for a test to show that it is safe. This shouldn't affect the implementation, and I'll have more information on that, soon.
If you have additional questions, I'm happy to get the answers for them.
|
Changed the code as discussed (parsing without root-tag and type; adding a root tag in mapping). Changed the help texts and tests accordingly. Added some new tests in SAMLParserTest#testInvalidEndElement.
I was not able to add a XXE test for the mapper. XXE via DOCTYPE should no longer be possible as we add a root tag on top level. If I change the input to @ahus1 Any ideas for the XXE test (or comments for the other changes)? |
There was a problem hiding this comment.
Thanks for the PR! The overall direction looks good. I left a few comments inline, could you please have a look?
All comments make sense. @hmlnarik Could please answer ahus1 open question whether attributes can be used / whether that was your intention? Once that is done I can implement all changes / answer the namespace questions ... I think sometime next week |
|
I will continue working on the issue around June 20th ... |
f1ef6b5 to
172ec79
Compare
Your changes and @hmlnarik comments are now included in my pull request. I either resolved the comment above or added some reasoning for my change. I made a separate branch in my clone keycloak_pull_10650 which contains a commit 71244a61 for my recent changes only. |
|
@KnauerSecunet Thank you for updates. Could you please rebase the PR? |
@hmlnarik Rebased on current main |
There was a problem hiding this comment.
@KnauerSecunet Thank you for the work, this is very nice piece of code! Once you address the one last comment regarding XPath, this PR is ready for merging.
|
@hmlnarik Done and rebased on current main |
There was a problem hiding this comment.
Approved on the condition that the tests pass
|
@svenhartmann - it will be part of Keycloak 20. You can watch the progress on KC20 by looking at the milestone https://github.com/keycloak/keycloak/milestone/22 ... the last open issues are actively being worked on, at the same time it will be released when it is ready. To give this feature a try, please use the Keycloak nightly builds. Given the small number of open issue for the milestone it should be quite close. |
@hmlnarik following my email from end of january here is my proposed solution for KEYCLOAK-19866 which also renders KEYCLOAK-19608 unnecessary.
It fixes parsing user-defined types and anyType saml attributes. And lets you later processthem via a xpath attribute mapper.
Please let me know what you think about it and which parts need improving/changes. Concerning the tests for the xpath mapper I plan to add one similar to AbstractUserAttributeMapperTest? Is there a documentation that needs to be expanded (with examples)?