-
1. Re: Elytron and jdbc-realm
mchoma Mar 7, 2018 4:57 AM (in response to nickarls)1 of 1 people found this helpfulYour general understanding is correct. So 2-way SSL works OK when whole app is secured? There is no issue so far.
Problem is how to split application to secured and unsecured.
You can't remove the need-client-auth attribute. This is how server knows he should request certificate from user.
But when you return it it starts to ask for certificate also on unsecured part and that is problem, right? You can use want-client-auth instead of need-client-auth. This differs in that way user has possibility to cancel certificate dialog.
Or can you split your app to 2 apps each secured by different ssl-context?
-
2. Re: Elytron and jdbc-realm
mchoma Mar 7, 2018 5:23 AM (in response to mchoma)Was you able to split app to CLIEN_CERT secured and unsecured part prior to Elytron? How?
-
3. Re: Elytron and jdbc-realm
nickarls Mar 7, 2018 5:32 AM (in response to mchoma)It was a long time since I tried it but looking from my notes, I had a web.xml security-constraint for a pattern and a CLIENT-CERT login config with a security-domain + DB login module. Technically, it shouldn't be impossible to have an application split up in three parts where one is unsecured, the other is form-secured and the third with client certs(?)
-
4. Re: Elytron and jdbc-realm
nickarls Mar 7, 2018 6:09 AM (in response to mchoma)Thanks, I'll try with the want-client-auth. Splitting the application in parts is not practical since a plain login should be the fallback if the user cancels the smartcard-pin-dialogue
<testing>
OK. With the "wants", the dialogue still pops up even for the / and the unsecured parts but the PIN dialogue can be cancelled and you can move on so it's a start
Now, according to the log I get a
2018-03-07 12:35:44,918 TRACE [org.wildfly.security] (default task-30) Evidence verification failed - alias [<LastName> <FirstName> <serial#>] does not exist in KeyStore
So the problem might be that
<aggregate-realm name="QuickstartRealm" authentication-realm="KeyStoreRealm" authorization-realm="dbRealm"/>
expects to find the principal as an alias in the trust store (which it of course can't since all individual cards cannot be registered there) and I should skip the aggregate use the jdbc-realm for both authentication and authorization? Or can I skip this part completely? Jdbc-realm examples usually have queries like "select password, roles..." but since the SSL level is OK with the certificate that signed for the card and the PIN is actually the password, how is jdbc-realm supposed to work with CLIENT-CERT when it comes to the concept of password?
-
5. Re: Elytron and jdbc-realm
honza889 Mar 7, 2018 7:10 AM (in response to nickarls)1 of 1 people found this helpfulCLIENT-CERT authentication in Elytron currently requires certificate verification against realm - I think currently only ldap-realm and keystore-realm supports X509PeerCertificateChainEvidence, so you need:
- a) KeyStore containing all user certificates (which is not practical as you say)
- b) LDAP contaning user certificate serial numbers/hashes
jdbc-realm currently does not support certificate verification.
Without realm verificating certificates there will be the "Evidence verification failed", regardless authorization configuration.
-
6. Re: Elytron and jdbc-realm
nickarls Mar 7, 2018 8:05 AM (in response to honza889)Ngh, thats annoying. Is there a simple way to write a completely custom realm that would accept the X509PeerCertificateChainEvidence that would just say "OK" for the evidence and internally use a datasource for fetching the roles? Or perhaps a handy extension-point when using a custom-realm that extends the jdbc-realm-implementation?
-
7. Re: Elytron and jdbc-realm
honza889 Mar 7, 2018 1:43 PM (in response to nickarls)There is custom-realm - you just need to create wildfly module with custom SecurityRealm implementation (you can use custom-elytron-realm as an example).
You cannot use other realm defined in subsystem, but (as you will have wildfly-elytron in your module dependencies) you can create new JdbcSecurityRealm inside of your realm.
If you dont need supported solution, you can also alternatively try my experimental patch of Elytron which allows to disable the verification: [ELY-1418]
Its usage is described in blogpost: CLIENT-CERT authentication with Elytron
-
8. Re: Elytron and jdbc-realm
nickarls Mar 9, 2018 3:54 AM (in response to honza889)Thanks for the pointer, I started on a custom-realm since it appears to be the less intrusive approach. Essentially what I'm trying out is overriding
public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName)
throws RealmUnavailableException
{
return X509PeerCertificateChainEvidence.class.isAssignableFrom(evidenceType) ? SupportLevel.POSSIBLY_SUPPORTED
: SupportLevel.UNSUPPORTED;
}
and
public RealmIdentity getRealmIdentity(final Principal principal) throws RealmUnavailableException
{
return new RealmIdentity()
{
public boolean verifyEvidence(Evidence evidence) throws RealmUnavailableException
{
return true;
}
public Principal getRealmIdentityPrincipal()
{
return principal;
}
public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName)
throws RealmUnavailableException
{
return null;
}
public SupportLevel getCredentialAcquireSupport(Class<? extends Credential> evidenceType, String algorithmName,
AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException
{
return null;
}
public <C extends Credential> C getCredential(Class<C> credentialType) throws RealmUnavailableException
{
return null;
}
public boolean exists() throws RealmUnavailableException
{
return true;
}
};
}
and then I have
<security-domain name="vrk_security_domain" default-realm="vrk_realm" permission-mapper="vrk_permission_mapper" principal-decoder="vrk_principal_decoder">
<realm name="vrk_realm" role-decoder="groups-to-roles" role-mapper="vrk_role_mapper"/>
</security-domain>
<custom-realm name="vrk_realm" module="my.vrk" class-name="my.VRKRealm"/>
<constant-role-mapper name="vrk_role_mapper">
<role name="authenticated"/>
</constant-role-mapper>
<simple-permission-mapper name="vrk_permission_mapper">
<permission-mapping>
<role name="authenticated"/>
<permission class-name="org.wildfly.security.auth.permission.LoginPermission"/>
</permission-mapping>
</simple-permission-mapper>
<x500-attribute-principal-decoder name="vrk_principal_decoder" attribute-name="SERIALNUMBER"/>
I might be doing some unnecessary work in the granting of the roles(?) but at least now my "authenticated"-role-secured area prompts for card input and req.getUserPrincipal() is populated with the serial number and req.isUserInRole("authenticated") returns true
I still have to do some testing so I don't make some glaring security miss with the realm-implementation ;-)
-
9. Re: Elytron and jdbc-realm
honza889 Mar 9, 2018 7:17 AM (in response to nickarls)Just note, you should return meaningful SupportLevel from get*Support methods in an identity class too. Feel free to just delegate to appropriate methods of the realm, but you should not return null in them.
In verifyEvidence method I would at least recommend to check type of the evidence - if it is X509PeerCertificateChainEvidence, it was already verified by SSLContext, but you should be careful to not accept PasswordGuessEvidence.
-
10. Re: Elytron and jdbc-realm
nickarls Apr 3, 2018 4:51 AM (in response to honza889)What would be the appropriate way of passing parameters to the custom realm?
If I were to call a database function for the actual evidence verification but would like to configure what data source to use for the call? Of course I could hardcode the data source and just use different custom-realms for different applications but parameters would be nice.
A programmatic approach (e.g. public static ThreadLocals) would probably not work because the authentication is (surprise, surprise) called before the application method
-
11. Re: Elytron and jdbc-realm
honza889 Apr 3, 2018 5:59 AM (in response to nickarls)1 of 1 people found this helpfulTo pass parameters into custom-realm (or any other custom-* in elytron) you need to implement interface org.wildfly.extension.elytron.Configurable in your realm and to pass params into "configuration" map:
/subsystem=elytron/custom-realm=myRealm:add(
module=jk.demo.myrealm,
class-name=MyRealm,
configuration={myAttribute="myValue"}
)You will need to add dependency on the org.wildfly.extension.elytron module into your module.
Check branch configurable in my demo:
-
12. Re: Elytron and jdbc-realm
nickarls Apr 3, 2018 7:27 AM (in response to honza889)Something strange still going on - I made the changes and on boot, I see the correct configuration - however, when I enter a protected area, I see getRealmIdentity called several times but then nothing happens - my page is entered, the principal is null but no breakpoints within the created RealmIdentity is ever hit...
-
13. Re: Elytron and jdbc-realm
honza889 Apr 4, 2018 1:35 PM (in response to nickarls)Just re-tested and it works ok for me - verifyEvidence() with X509PeerCertificateChainEvidence is called correctly for me.
Is your RealmIdentity returned from getRealmIdentity()?
Is CLIENT_CERT first mechanism in used http-authentication-factory?
-
14. Re: Elytron and jdbc-realm
nickarls Apr 5, 2018 2:10 AM (in response to honza889)I ran out of time at the office but could it have something to do with the fact that I tried to hook it up to the database at the same time. Could javax.sql imports without some module dependency lead to some sort of silent semi-failure due to a ClassNotFoundException?
Edited:
Adding a <module name="javax.api"/> dependency helped. A bit cruel not to throw a CNFE ;-)