-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ELY-2254] Provide a LoginModule compatible security realm. #1623
Conversation
// map all subject's principals to attributes with the following rule: | ||
// key of the attribute is principal's simple classname and the value is principal's name | ||
for (Principal principal : subject.getPrincipals()) { | ||
attributes.addLast(principal.getClass().getSimpleName(), principal.getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@darranl Just FYI, this is how I am currenly mapping subject's principal list into attributes of SecurityIdentity. It is like you mentioned on the meeting - attribute key is simple classname of Principal and attribute value is principal's name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 Most importantly here they have a predictable way to view information about the principals in the resulting attributes.
this.subject.getPrincipals().add(new AnonymousPrincipal()); | ||
this.subject.getPrincipals().add(new Roles("Admin")); | ||
this.subject.getPrincipals().add( new Roles("User")); | ||
this.subject.getPrincipals().add(new Roles("Guest")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@darranl Each role must then be placed into separate principal.
It might make sense to map principal with classname "Role" (without plural) into "Roles" attribute, but I though it might be confusing and would need to be documented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on this being documented, I think the use if plural / singular attribute names will just be a side effect of the mapping. Otherwise we could come up with a more complex mapping configuration but I don't think we would benefit from that really most importantly the attribute names are predictable.
* A {@code Group} implementation used in the tests to store the caller principal. | ||
*/ | ||
private class TestGroup implements Group { | ||
private static class Roles implements Principal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@darranl I do not expose this class anywhere, users can create their own principal classes that will be mapped to attribute keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 this is just for our tests.
} | ||
|
||
@Override | ||
public RealmIdentity getRealmIdentity(final Principal principal) { | ||
return principal instanceof NamePrincipal ? new JaasRealmIdentity(principal) : RealmIdentity.NON_EXISTENT; | ||
return new JaasRealmIdentity(principal); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@darranl I do not map any specific subject's principal to be the main "caller" principal. The main caller principal is the one that was passed into the realm for authentication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 that sounds good so that is not a problem that needs to be resolved as we already have the Principal identified.
b16506e
to
efbe1f4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added some discussion points Diana.
It is great that this looks like it slots into the Elytron SPIs without too much special configuration or behaviour needed. One point I flagged up to discuss is just double checking the SPI changes.
Maybe once @fjuma has had a chance to review we could discuss these last points tomorrow?
*/ | ||
public JaasSecurityRealm(final String loginConfiguration) { | ||
this(loginConfiguration, null); | ||
public JaasSecurityRealm(final String jaasConfigFilePath, ClassLoader classLoader) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One point on this class, I think we should double check if this was a part of public API or was always private API - if it was public we may need to fork it instead.
If this is not being picked up by JAPICMP it likely was private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this has always been private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have put this constructor back to the class. I realized a person might not want to change the classloader and so classloader can be null.
} | ||
|
||
@Override | ||
public RealmIdentity getRealmIdentity(final Principal principal) { | ||
return principal instanceof NamePrincipal ? new JaasRealmIdentity(principal) : RealmIdentity.NON_EXISTENT; | ||
return new JaasRealmIdentity(principal); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 that sounds good so that is not a problem that needs to be resolved as we already have the Principal identified.
for (Object credential : subject.getPrivateCredentials()) { | ||
if (credential instanceof Credential) { | ||
privateCredentials.add((Credential) credential); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are dropping credentials that are not the correct type maybe we should log at TRACE level to identity the class names of the ones being dropped.
// map all subject's principals to attributes with the following rule: | ||
// key of the attribute is principal's simple classname and the value is principal's name | ||
for (Principal principal : subject.getPrincipals()) { | ||
attributes.addLast(principal.getClass().getSimpleName(), principal.getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 Most importantly here they have a predictable way to view information about the principals in the resulting attributes.
@@ -0,0 +1,40 @@ | |||
package org.wildfly.security.auth.realm; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright header ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by removing of the ObjectCallback .
@@ -268,6 +269,14 @@ default Attributes getAttributes() throws RealmUnavailableException { | |||
return null; | |||
} | |||
|
|||
default Set<Credential> getPublicCredentials() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we add to RealmIdentity it should contain javadoc to describe the purpose, within this we should also make sure the contract is clear as to if these methods should return null or an empty collection - the latter would allow callers to skip the null check.
I would suggest if an API change is needed here it is checked in relation to the token authentication work being undertaken, that may also be adding credentials to the identity based on interaction with the realm so probably worth a double check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just FYI, some of the draft token authentication work can be found here:
Looks like we were using SecurityIdentity.withPrivateCredential()
there, there wasn't interaction with the realm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@darranl @fjuma I added javadoc to these methods and made them return IdentityCredentials.NONE instead of null.
Btw I am not sure anymore whether the credentials from the subject are useful for us to propagate to security identity? I added it here just to preserve all the information I can from the subject. But I am not sure if these private and public credentials have its use case once they are put in the security identity.
UPDATE - we decided not to propagate the credentials from the subject to the security identity. Reason is that private / public credentials are tied with the mechanism in elytron, so we decided not to change Elytron API for this currently. If it will be needed in the future we can add it or use subject in some sort of attachment.
Set<Credential> privateCredentialsFromRealmIdentity = realmIdentity.getPrivateCredentials(); | ||
if (privateCredentialsFromRealmIdentity != null) { | ||
for (Credential credential : privateCredentialsFromRealmIdentity) { | ||
authorizedIdentity = authorizedIdentity.withPrivateCredential(credential); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each iteration of the for loop will result in a new SecurityIdentity being created and one more being left for GC. Could this be reduced by converting to an IdentityCredentials first?
this.subject.getPrincipals().add(new AnonymousPrincipal()); | ||
this.subject.getPrincipals().add(new Roles("Admin")); | ||
this.subject.getPrincipals().add( new Roles("User")); | ||
this.subject.getPrincipals().add(new Roles("Guest")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on this being documented, I think the use if plural / singular attribute names will just be a side effect of the mapping. Otherwise we could come up with a more complex mapping configuration but I don't think we would benefit from that really most importantly the attribute names are predictable.
* A {@code Group} implementation used in the tests to store the caller principal. | ||
*/ | ||
private class TestGroup implements Group { | ||
private static class Roles implements Principal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 this is just for our tests.
* @author [email protected] | ||
* @version $Revision$ | ||
*/ | ||
public class ObjectCallback implements Callback { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think supporting this callback may be worth discussing more, as a new callback existing login modules will not be using this - maybe for now we would be better sticking with the PasswordCallback and CredentialCallback support - at least the former of the two should be a standard type?
* @param handler the JAAS callback handler to use | ||
* @param jaasConfigFilePath path to JAAS configuration file | ||
* @param entry login configuration file entry | ||
* @param classLoader classLoader to use with LoginContext, this class loader must contain LoginModule CallbackHandler classes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to mention in the javadoc for each param whether or not null
is allowed (here and in the other constructors too).
eebf4fd
to
de170c8
Compare
de170c8
to
8d0ce4b
Compare
Current failures in CI are unrelated to this PR and are addressed by ELY-2259 #1628 |
8d0ce4b
to
0b4aeb9
Compare
https://issues.redhat.com/browse/ELY-2254