I have a JMX server configured without Spring and am trying to implement Spring Security for the Authorization part.
(See here, https://blogs.oracle.com/lmalventosa/entry/jmx_authentication_authorization
Use Case 4, without the Authorization part)
I would like now to implement the Authorization part using Spring Security.
In my JMX authenticator, I do:
final List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
roles.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
final Authentication auth = new UsernamePasswordAuthenticationToken(credentialsArr[0], credentialsArr[1],
roles);
SecurityContextHolder.getContext().setAuthentication(auth);
And in the MBeans I try to fetch it and see that it has been passed correctly (in the future I plan to add Spring Annotations to check for roles, for method invocation).
final Authentication springAuth = SecurityContextHolder.getContext().getAuthentication();
The problem is, that in the standard connection flow:
JMXServiceURL url = ...;
Map env = ...;
String[] creds = {"monitorRole", "mrpasswd", "FileRealm"};
env.put(JMXConnector.CREDENTIALS, creds);
JMXConnector cc = JMXConnectorFactory.connect(url, env);
MBeanServerConnection mbsc = cc.getMBeanServerConnection();
I get a JMX connector, then connect to the MBean server and invoke a method - it works.
I get through the authenticator, set the Spring Context and get it in the Mbean.
But when I connect using a Jconsole, for example, I don't get the Spring Context in the Mbean.
I am using the Inheritable Thread strategy.
Is there a way to get the context also in the MBean, when connecting using the JConsole and other connectors?
If I implement JMX using Spring, will it help me to solve the problem?
Is my main flow fool proof (is there a chance I will not get the Context in the MBean)? I am asking this, since this flow is critical to me, to be fool proof.
Thanks a lot!
I will answer my own question, as I've seen interest in it and wanted to share my own conclusions (unrelated to the numbers above):
It looks like connecting with JConsole(or JVisualVM) locally (i.e. to localhost) connects directly to the thread, without going through the JMX Authenticator.
The only workaround I found was by connecting with a full URL (e.g. service:jmx:rmi:///jndi/rmi://10.45.32.112:3251/jmxrmi).
One mechanism that works always is the Java Security context; when JMXAuthenticator returns a Subject, you may assign the Spring Security Context to it and thus surely get it when invoking the method (e.g. in an Advice running before the invocation).
See this reply I got:
http://forum.springsource.org/showthread.php?134327-JMX-Authentication-with-Spring-Security-%283-1-x%29
I can't say for sure if the flow mentioned in the question is fool proof.
But it seems like it is, based on this assumption:
If you create a new connection for each JMX call and use it only for one invocation, you will get the Spring Security Context to propagate correctly.
Hope it helped you people :-)
Related
Am trying to hit my rest API in spring boot with the embeded server configured through browser and postman, but the request doesn't hit the server and am getting 404-not found am pretty new to springboot , please help me in this as in what to check further so that i can test my rest API
This could be due to couple of reasons
Try the following
Ensure the port you are specifying is correct
Ensure the end point you are specifying exist
Ensure the request you are sending is of correct REST action type (GET,POST etc)
Ensure your controller class is available in the same package in which Application class (with #SpringBootAnnotation) exists, else you will have to use #ComponentScan to make sure your controller class is scanned and endpoints available to receive traffic
Most likely, above should help :) If not, you'll need to describe what is done in the application so far
I am handling session on server side and i am able to manage that by using adapter side code
var cookie = WL.Server.getClientRequest().getHeader('Cookie');
var request = WL.Server.getClientRequest();
var session = request.getSession();
var sessionid = session.getId();
But the problem is every time i am hitting the adapter i am getting the same session on server side.
How to kill that session on adapter side so that i can create new session every time i hit the adapter.
I tried session.invalidate() but no use for me. After doing this also i am getting the same session on server side.
Please suggest what need to be done on server side or adapter side.
What you're describing is a default WL server behaviour. You'll get a new session created first time you hit the server and this session will be reused till it times out.
It will help greatly if you will explain exactly what you want to achieve. As it is, you are not explaining it clearly enough.
If you're talking about the server between the Worklight Server and the backend, then:
To get a new session with every adapter request sent to the backend, you need to set the connectAs property to endUser on the relevant procedure:
<procedure name="getStories" connectAs="endUser"/>
Refer to the following blog post which explains it at length:
Configuring HTTP adapters for stateless/stateful backend connectivity and user identity propagation
If you're actually talking about the session creating when invoking the adapter on the client-side, then you cannot invalidate the session on the adapter-level. The only way to get a new session would be to re-open the application (assuming the session has already expired between the client and the Worklight Server, you'll then get a new session).
Some pointers more than anything required here.
I'm trying to get both X509 and LDAP working in my application. I want users to be authenticated using their PKI certs and then for the APP to get their authorities from our LDAP server.
I have LDAP working with a customer userDetailsContextMapper at the moment however how to add the x509 properly stumps me a little.
I think what I want is a PreAuthenticatedAuthenticationProvider that uses an injected ldapUserDetails service.
How can I do that? Do I need a UserDetailsByNameServiceWrapper to wrap the LdapUserDetailsService up to be used within the pre-authentication provider?
I ask because unfortunately the testing platform and the development environment at the moment is detached, and I don't have local LDAP or PKI set up to test against so its about a 6 hour process getting a new war onto the dev environment... Restrictive I know... So I want to get it right first time.
Cheers!
NOTE: THE FOLLOWING WORKS WITH Spring-Security-Core v1.2.7.3, Configuration names are different in 2.0RC2
Following a few different ideas, this is what I came up with. This assumes you already have LDAP working with a custom and UserDetailsContextMapper (see: ldap documentation):
Ensure both the LDAP and a PreAuthenticatedAuthentication Provider are in the provider list:
grails.plugins.springsecurity.providerNames = [
'preAuthenticatedAutehnticationProvider',
'ldapAuthProvider',
'daoAutehnticationProvider',
'anonymousAuthenticationProvider',
'rememberMeAuthenticationProvider']
Then in your spring resources (grails-app/conf/spring/resources.groovy) configure the following beans:
ldapUserDetailsService(org.springframework.security.ldap.userdetails.LdapUserDetailsService,
ref('ldapUserSearch'),
ref('ldapAuthoritiesPopulator')) {
userDetailsMapper = ref('ldapUserDetailsMapper')
}
userDetailsByNameServiceWrapper(org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper) {
userDetailsService = ref('ldapUserDetailsService')
}
preAuthenticatedAuthenticationProvider(org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider) {
preAuthenticatedUserDetailsService = ref('userDetailsByNameServiceWrapper')
}
And bobs your uncle and you have some aunts!
For reference the pages I used to come up with this solution are:
No AuthenticationProvider found using spring security
Wrap your LdapUserDetailsService in a UserDetailsByNameServiceWrapper
Instead of the LdapAuthenticationProvider configure a PreAuthenticatedAuthenticationProvider that will be able to process the PreAuthenticatedAuthenticationToken issued by your CustomX509AuthenticationFilter.
Inject the wrapped LdapUserDetailsService into the PreAuthenticatedAuthenticationProvider.
http://blog.serindu.com/2011/05/26/grails-spring-security-using-preauthenticated-authentication-provider/
Covers how to wire up a preAuthenticationAuthenticationProvider in grails
http://forum.spring.io/forum/spring-projects/security/108467-combine-pre-authentication-with-ldap-for-user-details-and-authorities
there's an LdapUserDetailsService that does all the good things the LdapAuthenticationProvider does - except for authentication
http://pwu-developer.blogspot.co.uk/2012/02/grails-security-with-cas-and-ldap.html more on how to wire up that ldapUserDetailsService
Hope this helps someone else!
I am trying to setup a REST-webservice with RESTeasy that access EJBs that are deployed on a JBoss 7.1.1.
I've been successful in:
Setting up Beans to be accessed via REST
Configuring SSL for the connection
Setting up a PreProcessInterceptor that uses HTTP Basic Auth to ask the User for his credentials.
Currently I basically just check the credentials hardcoded in the interceptor.
This works to make sure that the User is authenticated, but our Beans query for the name of the currently logged in Principal for some Beancalls like this:
#Resource
private SessionContext context = null;
[...]
String userName = context.getCallerPrincipal().getName();
Currently userName is now always anonymous. What is the right way to set the caller principal? Do I do this in an Interceptor? Or in the Bean itself? My goal is to basically be able to call a method loginUserWithEJBOnJboss(String user, String pass) that uses the login-methods that are configured within the jboss and sets the principal correctly.
I am at a loss here, google didn't find anything. Maybe I am just searching for the wrong words.
So yeah, as always soon after asking I find the solution myself. I think sometimes I only ask because I know this will happen.
So the solution are these methods:
SecurityContextAssociation.setPrincipal(new SimplePrincipal(username));
SecurityContextAssociation.setCredential(password.toCharArray());
They do pretty much all I wanted :)
here's the setup for the project.
I have a WCF Service that is hosted on a net.tcp binding in buffered mode and ReliableSession enabled.
The binding is configured to use TransportWithMessageCredential security. The certificate is a self signed certificate that I am identifying using the Thumbprint.
The UserNameValidator is a custom validator which for testing, never fails (it wasn't failing before but I removed the uncertainty)
The service and client are on the same machine and they both have access to the certificate.
The problem:
I am receiving a Socket Aborted exception when trying to consume a Method from the service. Here is the code I use to open a connection to the service. MonitorServiceCallbacks only contains empty methods to fulfil the requirements of the Interface.
_instanceContext = new InstanceContext(new MonitorServiceCallbacks());
_serviceInterface = new MonitorCallbackServiceClient(_instanceContext);
_serviceInterface.ClientCredentials.UserName.UserName = Environment.MachineName;
_serviceInterface.ClientCredentials.UserName.Password = "myPassword";
_serviceInterface.Open();
This appears to work fine as the _serviceInterface.State variable is set to State.Opened and the custom validator is called and returns without exception.
However, if I try to call a method using the _serviceInterface proxy, no code that I can break into is run on the service and the tracelog reveals no errors apart from a SocketAborted exception which occurs 1 minute after receiving what appears to be the message for the method.
There is no InnerException.
I have tried to google the issue but the results tend to say "just disable security and it will work fine". Unfortunately, this cannot be done.
I am extremely confused by this issue and any help would be greatly appreciated.
Many thanks,
Ehrys
This was actually a serialisation error.
The object I was trying to send to the service inherited from the data contract. So I was trying to send a cast down to the data contract to the service.
WCF doesn't appear to allow this.
I would like to thank John Saunders for reminding me that not only the service can have tracing enabled. Enabling client side tracing would have saved me a lot of time.
I was attempting to do the following:
_serviceInterface.Register((MyDataContract)MyParentObject, aVariable, anotherOne);
What I needed to do:
MyDataContract tempContract = MyParentObject.CreateMyDataContract();
_serviceInterface.Register(tempContract, aVariable, anotherOne);
/* Note: MyParentObject.CreateMyDataContract() is my own method which creates an instance
of the MyDataContract and copies the relevant information to it */