Problems calling EJB from a Standalone client in EAP 7 - jboss

I migrated Weblogin application to JBoss EAP 7.1.
But when I call my API from browser I have an exception :
WFLYEJB0364: Invocation on method: public abstract java.util.List
com.medtronic.diabetes.carelink.hcp.service.UserService.getCountryLanguages(java.lang.String,com.medtronic.diabetes.carelink.hcp.persistence.model.ApplicationType)
of bean: UserServiceImpl is not allowed
UserService method signature :
#PermitAll
List<LanguageDefinitionItemDto> getCountryLanguages(String countryCode, ApplicationType type);
In weblogic.xml I had security properties:
<security-role-assignment>
<role-name>admin</role-name>
<principal-name>adminGroup</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>user</role-name>
<principal-name>userGroup</principal-name>
</security-role-assignment>
<!-- session configuration -->
<session-descriptor>
<cookie-secure> true </cookie-secure>
<persistent-store-type> replicated_if_clustered </persistent-store-type>
<cookie-http-only> false </cookie-http-only>
<url-rewriting-enabled> false </url-rewriting-enabled>
<timeout-secs> 1800 </timeout-secs>
</session-descriptor>
in standalone-full.xml I have one login-module from another ear. Do I need to add RoleMappingLoginModule ?
<security-domain name="mySecurityDomain" cache-type="default">
<authentication>
<login-module code="Database" flag="required">
<module-option name="dsJndiName" value="java:/jdbc/powds"/>
<module-option name="principalsQuery" value="SELECT password FROM DDMS_ACCOUNT WHERE user_name = ?"/>
<module-option name="rolesQuery" value="SELECT group_name, 'Roles' FROM DDMS_ACCOUNT_GRP_ASSOC WHERE user_name = ?"/>
</login-module>
</authentication>
</security-domain>
</security-domains>
Plese help me to transfer this config on Jboss EAP 7.1.0.
I tried add in web.xml but this didn't help :
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
jboss server.log
Principal: anonymous
:callerRunAs=null:callerRunAs=null:ejbRestrictionEnforcement=false:ejbVersion=2.0];Action=authorization;Source=org.jboss.security.plugins.javaee.EJBAuthorizationHelper;policyRegistration=null;Exception:=PBOX00017: Access denied: authorization failed ;
2019-12-17 10:59:59,177 TRACE [org.jboss.security] (default task-7) PBOX00354: Setting security roles ThreadLocal: null
If I remove #PermitAll annotation it still doesnt works.
End please explain me where this security-role uses and why? Do I need to add this admin and user to jboss security ApplicationRealm?
<default-missing-method-permissions-deny-access value="false"/> works. but Will it have negative affect?

delete cofig <default-security-domain value="other"/> in standalone-full.xml helped me

Related

Proper way to retrieve password for Datasource from external service in Wildfly

I have an application running under Wildlfy 21. I'm also using MariaDB and OpenJPA. The problem is that the password used to connect to MariaDB is retrieved from external custom service. And it can change at any time. Unfortunately I am not getting any notification that database password has been changed.
I'm looking for a way where Wildfly could handle a situation when there is a problem with connection to database. And will be able to retrieve and replace old password.
So far I have tried to solve this problem using security domain and extend ConfiguredIdentityLoginModule class to retrieve and overwrite the password. Like in this case:
Wildfly - set datasource password at runtime
The code which extends ConfiguredIdentityLoginModule is added as Wildfly module.
Here is my actual implementation
Datasouce:
<datasource enabled="true" jndi-name="jdbc/aenDS" pool-name="aenDS">
<connection-url>jdbc:mariadb://localhost:3306/AEN</connection-url>
<driver>mariadb</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>50</max-pool-size>
</pool>
<security>
<security-domain>aenSecurityDomain</security-domain>
</security>
</datasource>
Login module implementation:
public class DatabaseLoginModule extends ConfiguredIdentityLoginModule {
#Override
public void initialize(final Subject subject, final CallbackHandler handler, final Map<String, ?> sharedState,
final Map<String, ?> options) {
final Map<String, Object> newOptions = new HashMap<>(options);
//retrieve password from external credential service
final String password = new CredentialService().retrievePassword(options.get("username"), "database");
//update options with new password
newOptions.put("password", password);
super.initialize(subject, handler, sharedState, newOptions);
}
}
Sercurity domain:
<security-domain name="aenSecurityDomain" cache-type="default">
<authentication>
<login-module code="com.aen.DatabaseLoginModule" flag="required" module="com.aen">
<module-option name="principal" value="user"/>
<module-option name="username" value="user"/>
<module-option name="password" value="sa"/>
<module-option name="managedConnectionFactoryName" value="jboss.jca:service=LocalTxCM,name=aenDS"/>
</login-module>
</authentication>
</security-domain>
The main problem in this solution is how many times DatabaseLoginModule is called. When cache-type is not defined in security domain (cache is not used) then DatabaseLoginModule is called everytime when OpenJPA is obtaining connection from the pool. During the tests, more than 50 password inquiries were made within 10 seconds. It's way too much.
When "default" value is used in cache-type then DatabaseLoginModule is called only once during startup and never again. So the password is never updated.
Is there any other way this problem can be solved? Is it possible to clear security domain cache when connection to database fails?

LDAP configuration in wildfly, searching for roles

I have Kerberos set up with wildfly plus I get groups from LDAP and it works for certain configurations but doesn't for others.
Kerberos works as expected and here is the config I have for LDAP:
<login-module code="org.jboss.security.negotiation.AdvancedLdapLoginModule" flag="requisite">
<module-option name="java.naming.provider.url" value="ldap://ttttt.com:3268/"/>
<module-option name="bindDN" value="user"/>
<module-option name="bindCredential" value="passwd"/>
<module-option name="baseCtxDN" value="DC=AD,DC=TTT,DC=com"/>
<module-option name="baseFilter" value="(userPrincipalName={0})"/>
<module-option name="rolesCtxDN" value="OU=Groups, DC=AD,DC=TTT,DC=com"/>
<module-option name="roleFilter" value="(member={1})"/>
<module-option name="roleAttributeID" value="memberOf"/>
<module-option name="roleAttributeIsDN" value="true"/>
<module-option name="roleNameAttributeID" value="cn"/>
<module-option name="recurseRoles" value="true"/>
<module-option name="password-stacking" value="useFirstPass"/>
<module-option name="allowEmptyPassword" value="false"/>
<module-option name="searchScope" value="SUBTREE_SCOPE"/>
</login-module>
I have setup a group called app_ttt_api. I added some members to this group.
So my setup works when the member I added is a group itself and you are a member of that group. If you add a user directly, it doesn't work. Also if you add a group that contains a group that contains a user it also doesn't work.
So, group->group->user works but
group->user
and
group->group->group->user
doesn't
So I am trying to figure out what's wrong and what I should modify so if the user is part of any recursive groups or directly a part of group it should work.
Edit: subsequent question - can I see what LDAP actually returns in the log, i.e. the list of user groups the user belongs to? Or LDAP traffic?
Edit2: actually figured out the debugging, it's described here - https://developer.jboss.org/thread/272926
Edit3:
I looked at the source code of AdvancedLdapLoginModule
here: AdvancedLdapLoginModule
From the code it looks like following:
1. get all the roles from initial role context filtering by user
526 results = searchContext.search(rolesCtxDN, roleFilter, filterArgs, roleSearchControls);
rolesCtxDN=DC=AD,DC=TTT,DC=com roleFilter=(member={1}) filterArgs[0]=myuser#AD.TTT.COM filterArgs[1]=CN=myuser,CN=Managed Service Accounts,DC=AD,DC=MLP,DC=com
Iterate through roles calling
532 obtainRole(searchContext, resultDN);
In obtainRole it calls
572 Attributes result = searchContext.getAttributes(dn, attrNames);
575 Attribute roles = result.get(roleAttributeID);
where attrNames is roleAttributeID - "memberOf" in my case.
Go through all the roles obtained from line 575 and call
585 loadRoleByRoleNameAttributeID(searchContext, roleDN);
586 recurseRolesSearch(searchContext, baseRoleDN);
where 585 adds a role and 586 recursively searches for underlying roles.
The problem in my case in 3 - why would we try to get roles our initial role is memberOf and not add it right away, we already know that the user is a member of this role. I think that's the reason why I only get authorized when I have group->group->user and not in other cases.
Am I understanding what's going on right? Should I pass something else in the config? I tried different variations of the config, when I do
<module-option name="roleAttributeID" value="cn"/>
<module-option name="roleAttributeIsDN" value="false"/>
it will load all first level roles, but wouldn't recurse to lower level groups.
In other configurations I tried there were no roles loaded.

Wildfly 10.1.0 getting "anonymous" as principal name in EJB

Problem Statement: context.getCallerPrincipal().getName() always gives "anonymous" with following client and server settings
I have done all the settings required. My security domain is using a Custom spring security module for JAAS login. The client acts as an installer for the application. The main application is deployed on wildfly 10.1 and installer launches as a standalone application which access the remote EJBs from the server. The EJB access is successfully but when I access caller principle from context it always gives "anonymous"
Client Side Settings:
jboss-ejb-client.properties:
remote.connections=default
remote.connection.default.port=8080
remote.connection.default.host=127.0.0.1
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=root
remote.connection.default.password=catch22*
Initial Context Creation:
Properties prop1 = new Properties();
prop1.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop1.put("org.jboss.ejb.client.scoped.context", "true");
System.out.println("setup() ################### 1");
context = new InitialContext(prop1);
Used jboss-client.jar
I have used the jboss-client.jar lib provided with in "WILDFLY_HOME/bin/client" directory
Server Side Settings
ejb realm:
Added following ejb realm in standalone-full.xml
<security-realm name="ejb-outbound-realm">
<server-identities>
<secret value="Q29ubmVjdGlvblBhc3N3b3JkMSE="/>
</server-identities>
</security-realm>
remoting subsystem settings:added out bound connection as follows
<outbound-connections>
<remote-outbound-connection name="ejb-outbound-connection" outbound-socket-binding-ref="ejb-outbound" security-realm="ejb-outbound-realm" username="root">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
</outbound-connections>
Against out bound connection I have added following socket binding group
<outbound-socket-binding name="ejb-outbound">
<remote-destination host="localhost" port="8080"/>
</outbound-socket-binding>
application-users.properties:
root=7c5b7db204cb436044a4148094ef152e
application-roles.properties:
No change in this file
Session Bean Changes
#Stateless
#Local(AbstractEnterpriseSessionFacadeLocal.class)
#Remote(AbstractEnterpriseSessionFacadeRemote.class)
#SuppressWarnings({WarningConst.UNCHECKED, "rawtypes"})
#PermitAll
//#org.jboss.ejb3.annotation.SecurityDomain("acegi-simple")
public class AbstractEnterpriseSessionFacadeBean<T, E extends IGeneralObject> implements AbstractEnterpriseSessionFacade {
injection of context in above class
#Resource
private transient SessionContext context;
After above settings, when I am calling context.getCallerPrincipal().getName() it always gives me "anonymous"
Please help!

jBoss add-user.bat does not see the new realm

I created a new realm in standalone.xml and now I'm trying to create a new user in that realm. When I use full command like
add-user -a -r realm-name -u user -p password
I get the error:
JBAS015281: The user supplied realm name 'realm-name' does not match the realm name discovered from the property file(s) 'ApplicationRealm'.
When I run just add-user, it promts to choose realm, and there are only applicationrealm and managementrealm in the list.
Here's my snippets from standalone.xml:
1) Domain
<security-domain name="realm-domain" cache-type="default">
<authentication>
<login-module code="Remoting" flag="optional">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
<login-module code="RealmUsersRoles" flag="required">
<module-option name="usersProperties" value="${jboss.server.config.dir}/rt-users.properties"/>
<module-option name="rolesProperties" value="${jboss.server.config.dir}/rt-roles.properties"/>
<module-option name="realm" value="realm-name"/>
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
</authentication>
</security-domain>
2) Realm
<security-realm name="realm-name">
<authentication>
<local default-user="$local"/>
<jaas name="realm-domain"/>
</authentication>
</security-realm>
I post here the solution I've found, maybe it could be useful for someone else who has encountered this problem!
I'm using add-user.sh on Jboss Eap 7, trying to add a user to a new security realm I've created I encountered the same issue:
jboss-eap-7.0/bin/add-user.sh -r HttpsRealm
What type of user do you wish to add?
a) Management User (mgmt-users.properties)
b) Application User (application-users.properties)
(a):
It seems my new realm is not recognized, but if I specify also the new properties file I've created related to the realm it works as expected!
jboss-eap-7.0/bin/add-user.sh -r HttpsRealm -up stand-env/stand1/standalone/configuration/https-mgmt-users.properties
Enter the details of the new user to add.
Using realm 'HttpsRealm' as discovered from the existing property files.
Username :
Hope it helps someone!
The add-user utility does not manage new properties files, you must manage separately.
Look : https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6/html/Development_Guide/Add_a_New_Security_Realm.html
When you add users and roles to this new realm, the information will be stored in a separate file from the default security realms. You can manage this new file using your own applications or procedures.
Adding to what people have said, what finally helped me was.
specifying the realm (-r) first and then user properties (-up)
Make sure the user properties file is empty.

How to map SAML assertion attribute values onto roles in SP with PicketLink?

We're implementing a SAML2-Based SSO solution and use PicketLink on the SP side.
On the IDP side we have a different implementation which is configured to output the multivalued memberOf attribute (these are actually LDAP/AD-group memberships. So we get basically get something like this in the assertion:
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ... >
...
<saml:Assertion ...>
...
<saml:AttributeStatement>
<saml:Attribute FriendlyName="Role" Name="Role">
<saml:AttributeValue>authenticated</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute FriendlyName="memberOf" Name="memberOf">
<saml:AttributeValue>CN=ga-A-102213-...</saml:AttributeValue>
<saml:AttributeValue>CN=g-z-MeetingPlace,...</saml:AttributeValue>
<saml:AttributeValue>CN=g-z-Serviceportal,...</saml:AttributeValue>
<saml:AttributeValue>CN=g-z-BCM...</saml:AttributeValue>
...
</saml:Attribute>
</saml:AttributeStatement>
...
</saml:Assertion>
</samlp:Response>
My question is, how could I configure PicketLink/JBoss to map these memberOf values onto specific roles in the application/SP?
For instance that CN=g-z-MeetingPlace,... should be mapped to ROLE_MEETING or CN=g-z-BCM... should be mapped onto ROLE_BCM. We could probably write a login module to do that, but for me it seems to be a very standard task. However I did not manage to find a configurative solution yet.
Seems like we've figured it out.
What we needed was org.jboss.security.auth.spi.RoleMappingLoginModule:
<login-module code="org.jboss.security.auth.spi.RoleMappingLoginModule"
flag="optional">
<module-option name="rolesProperties">roles.properties</module-option>
</login-module>
Mapping between AD group names and internal application roles is configured in the roles.properties file:
CN\=ga-A-102213-...=SomeInternalRole