Securing JMXConnectorServerService (jmx-remoting.sar) in JBoss 5.1.0.GA - security

I've been trying to understand how to secure the JMXConnectorServerService offered by JBoss 5.1.0.GA by default.
Currently, if I paste the following URL into JConsole, I can get to JMX directly without any authentication: service:jmx:rmi:///jndi/rmi://:1290/jmxconnector
Then I did this to secure my JMXInvoker in hopes that that would secure all JMX access: http://objectopia.com/2009/10/01/securing-jmx-invoker-layer-in-jboss/
But, apparently, that doesn't apply to the JMXConnectorServerService. I can still get to JMX using the the above service URL through jconsole.
Then I found out about this feature request that hasn't been accommodated yet: https://issues.jboss.org/browse/JBAS-8159
Now, presently I'm not worried about crazy security measures. This URL is not gonna be exposed to the outside network. So, I just want to see what's the simplest way for me to secure the jmx-remoting.sar with the "jmx-console" security domain?
I could switch to the default MBean server, but apparently, in 5.1.0.GA, that's a pain: https://community.jboss.org/thread/153594
I'd really appreciate any input in this regard.
Thanks!

I don't think that service has been secured, but there is a patch.
For a slightly simpler version, I am going out on a limb here, since I have not tested this on AS 5, but I backported it to AS 4 and it worked ok.
I'm not sure which version you have, exactly, but let's assume it is this one. The EAP version has a slightly more involved version, but the premise is the same. You will need to extend JMXConnectorServerService and JMXConnectorServerServiceMBean.
In this implementation, the code to create the server looks like this:
// create new connector server and start it
connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
In your extension, add the following:
/** The name of the JAAS domain to use for authentication */
protected String jaasDomain = null;
...
/**
* Returns the name of the JAAS domain to use for authentication
* #return the name of a JAAS Domain
*/
public String getJaasDomain() {
return jaasDomain;
}
/**
* Sets the name of the JAAS domain to use for authentication
* #param jaasDomain the JAAS Domain to use for authentication
*/
public void setJaasDomain(String jaasDomain) {
this.jaasDomain = jaasDomain;
}
Now you need to reimplement the start method which adds an environment containing the JAAS domain name you want to authenticate with.
public void start() throws Exception
{
// the address to expose in the urls
String host = System.getProperty("java.rmi.server.hostname");
// check to see if registry already created
rmiRegistry = LocateRegistry.getRegistry(host, registryPort);
if (rmiRegistry != null)
{
try
{
rmiRegistry.list();
}
catch(RemoteException e)
{
log.debug("No registry running at host '" + host +
"', port '" + registryPort + "'. Will create one.");
rmiRegistry = LocateRegistry.createRegistry(registryPort, null, new DefaultSocketFactory(bindAddress));
}
}
else
{
rmiRegistry = LocateRegistry.createRegistry(registryPort, null, new DefaultSocketFactory(bindAddress));
}
String serviceURL = "service:jmx:rmi://" + host + "/jndi/rmi://" + host + ":" + registryPort + jndiPath;
JMXServiceURL url = new JMXServiceURL(serviceURL);
// create new connector server and start it
// ==== NEW AUTH CODE HERE ====
final Map<String, Object> environment = new HashMap<String, Object>();
environment.put("jmx.remote.x.login.config", jaasDomain);
connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, environment, mbeanServer);
// ==== NEW AUTH CODE ENDS ====
connectorServer.start();
log.info("JMX Connector server: " + serviceURL);
}
You can optionally validate the JAAS name like this:
/**
* Validates the name of the passed JAAS domain.
* If the name is not valid, a RuntimeException will the thrown.
* #param domain The name of the JAAS domain to validate.
*/
private void validateJaasDomain(String domain) {
try {
new LoginContext(domain);
} catch (Exception e) {
throw new RuntimeException("The JAAS Domain [" + domain + "] could not be loaded", e);
}
}
Add the jaasDomain attribute to the new MBean interface:
/**
* Returns the name of the JAAS domain to use for authentication
* #return the name of a JAAS Domain
*/
public String getJaasDomain();
/**
* Sets the name of the JAAS domain to use for authentication
* #param jaasDomain the JAAS Domain to use for authentication
*/
public void setJaasDomain(String jaasDomain);
Let's assume your new impl is com.vijay.JMXConnectorServerService and the new MBean is com.vijay.JMXConnectorServerServiceMBean; You deployment descriptor would look like this: (using the jmx-console jaas domain, since you probably have that secured....)
<!-- ======================================================== -->
<!-- Example Vijay JMX Remoting Service Configuration file -->
<!-- ======================================================== -->
<server>
<mbean code="com.vijay.JMXConnectorServerService"
name="jboss.remoting:service=JMXConnectorServer,protocol=rmi"
display-name="JMX Connector Server (RMI)">
<attribute name="BindAddress">
<!-- Get the port from the ServiceBindingManager -->
<value-factory bean="ServiceBindingManager" method="getStringBinding"
parameter="jboss.remoting:service=JMXConnectorServer,protocol=rmi"/>
</attribute>
<!-- if comment this out, will use 1099 as default and will conflict -->
<!-- with default JNP (JNDI) port. -->
<attribute name="RegistryPort">
<!-- Get the port from the ServiceBindingManager -->
<value-factory bean="ServiceBindingManager" method="getIntBinding"
parameter="jboss.remoting:service=JMXConnectorServer,protocol=rmi"/>
</attribute>
<!-- the path to which will be bound in rmi registry -->
<!-- the commented value below is the default. -->
<!-- <attribute name="JndiPath">/jmxconnector</attribute> -->
<attribute name="JaasDomain">jmx-console</attribute>
</mbean>
</server>
That's all I have. I hope it is useful to you.

Related

UriEndpointmapping working with attribute setendpointmapping - Spring Integration ws

I am trying to set property setendpointmapping of object UriEndpointmapping with a hashmap with the followings values:
UriEndpointMapping uriEndpointMapping = new UriEndpointMapping();
Map<String,Object> endpointMap = new HashMap<>();
endpointMap.put("/miservicio/cliente", gateway);
endpointMap.put("/miservicio/cliente.wsdl", wsdlDefinition());
uriEndpointMapping.setEndpointMap(endpointMap);
Where: gateway is an bean of type int-ws:inbound-gateway
and wsdlDefinition is a method to return DefaultWsdl11Definition
So, When I call from of browser localhost:8080/miservicio/cliente.wsdl, I don't get a response. Thus, How should I work it?
You misunderstood the UriEndpointMapping logic a bit:
* Implementation of the {#code EndpointMapping} interface to map from the full request URI or request URI path to
* endpoint beans.
The WSDL definition logic is a bit different and it is done like a part of the MessageDispatcherServlet startup logic:
private void initWsdlDefinitions(ApplicationContext context) {
wsdlDefinitions = BeanFactoryUtils
.beansOfTypeIncludingAncestors(context, WsdlDefinition.class, true, false);
The WSDL selection logic from there by the incoming request is like this:
protected WsdlDefinition getWsdlDefinition(HttpServletRequest request) {
if (HttpTransportConstants.METHOD_GET.equals(request.getMethod()) &&
request.getRequestURI().endsWith(WSDL_SUFFIX_NAME)) {
String fileName = WebUtils.extractFilenameFromUrlPath(request.getRequestURI());
return wsdlDefinitions.get(fileName);
}
else {
return null;
}
}
And let's take some sample from the Spring WS documentation:
<sws:dynamic-wsdl id="holiday"
portTypeName="HumanResource"
locationUri="/holidayService/"
targetNamespace="http://mycompany.com/hr/definitions">
<sws:xsd location="/WEB-INF/hr.xsd"/>
</sws:dynamic-wsdl>
and this quote:
The id determines the URL where the WSDL can be retrieved. In this case, the id is holiday, which means that the WSDL can be retrieved as holiday.wsdl in the servlet context. The full URL will typically be http://localhost:8080/holidayService/holiday.wsdl

ZF2 User Register and creation of a Subdomain

Im using the ZF 2 Framework and have the follow scenario.
Company can register
After Register it creates a subdomain (need changes in the
.htaccess)
Example :
site.com => Frontend
company_a.site.com => Frontend for Company (company_id=1)
compaby_b.site.com => Frontend for Company (company_id=2)
What i want is that when a Users goes to company_a.site.com or company_b.site.com, that the Route is the same in the Application but the Data from DB depens on the subdomain name.
How i think it must work :
User comes to company_a.site.com
In the Main Controller i will make a Query to DB to see if exists a company with name "company_a" and if is so then assign a
global variable with the company ID from the DB. So i can based on
that ID load the content for the frontend.
I done something similar in my current project. I used a service to get the site details from a MySQL database using doctrine based on the domain name.
My service is
namespace Application\Service;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Application\Entity\Sites;
class SiteFactory implements FactoryInterface
{
/**
* #var EntityManager
*/
protected $entityManager = NULL;
/**
*
* #param \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator
* #return \Application\Entity\Sites
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$request = $serviceLocator->get('Request');
$site = new Sites();
if (method_exists($request, 'getUri')) {
$domainName = ltrim($request->getUri()->getHost(), 'www.');
$entityManager = $serviceLocator->get('entityManager');
$repository = $entityManager->getRepository('Application\Entity\Sites');
$site = $repository->findOneByDomainName($domainName);
}
return $site;
}
}
In my module.config I have
'service_manager' => array(
'factories' => array(
'site' => 'Application\Service\SiteFactory',
),
),
and to get the site in my controller I use
$this->getServiceLocator()->get('site');
to return the sites doctrine entity or an empty entity if no site found.
I hope this points you in the right direction.
I find the solution with the ZF 2 Route Hostname type

jsf spring security session timeout viewExpiredException

I have the following problem with the timeouts in Spring Security with JSF:
I've customized the sessionmanagement filter so that the user is redirected to the invalidSessionUrl just if the requested page is secured (i.e. if it is allowed just for authenticated users). The custom code I put into the session management filter provided by Spring Security is:
if (invalidSessionUrl != null) {
String pagSolicitada = UtilSpringSecurity.extraerPagina(request);
if ( UtilSpringSecurity.paginaAutenticada(pagSolicitada ) ) {
request.getSession();
redirectStrategy.sendRedirect(request, response, invalidSessionUrl);
return;
}
//the requested page doesn't require the user to be authenticated
//so i just skip this filter and continue with the filter chain
chain.doFilter(request, response);
return;
}
The method "UtilSpringSecurity.extraerPagina(request)" returns the requested page this way:
public static String extraerPagina (HttpServletRequest request) {
String uri = request.getRequestURI().toLowerCase();
String cPath = request.getContextPath().toLowerCase();
// uri = cPath + pagina
int longCPath = cPath.length();
String pagina = uri.substring(longCPath);
return pagina;
}
And the method "UtilSpringSecurity.paginaAutenticada(pagSolicitada)" returns true if the the param is a page that requires the user to be authenticated (I do the check with IFs, considering the intercept-url elements of my xml security config file which have the attribute access="isAuthenticated()"):
public static boolean paginaAutenticada (String pagina) {
if (pagina.startsWith("/faces/paginas/administracion/") || pagina.startsWith("/faces/paginas/barco/") ) {
return true;
}
return false;
}
This solution works, but it has just one problem:
If I leave the browser staying idle at a page until the session timeout expires, and then I request the same page, then I get a "viewExpiredException". This is because the filter worked well, it bypassed the redirection to the invalidSessionUrl, but as the session expired anyway, then I get that exception trying to re-render the same page.
If I request any other unsecured page when the session timout has expired, it works well, it redirects correctly to the page and I don't get the viewExpiredException.
Anyone knows how to solve this?
Thank you in advance.
Spring security should give you anonymous access to sets of pages for an un-authenticated user. Below is an excerpt of my XML configuration for how I achieved this.
<http auto-config="true" access-denied-page="/unauthorized.xhtml" >
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<intercept-url pattern="/app/**" access="ROLE_USER,ROLE_ADMIN" />
<intercept-url pattern="/*.xhtml" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<form-login login-page="/login.xhtml" login-processing-url="/j_spring_security_check"
authentication-success-handler-ref="authenticationSuccessBean"
authentication-failure-handler-ref="authenticationFailureBean" />
<session-management invalid-session-url="/login.xhtml" >
</session-management>
</http>
I essentially use intercept-url tags to claim that pages within certain relative contexts can only be accessed by the following roles. You can see that all pages at the web application default context are available to anonymous users. If the user is unauthorized to view the page then they will be redirected to access-denied-page.
The only catch is that your User bean has to implement the UserDetails interface and have a property that returns a role bean which implements the GrantedAuthority interface. Spring will look for a UserDetails to have a GrantedAuthority property to determine what the role is. If this user does not exist, is unauthenticated, or unknown then it will default to anonymous role.
Finally I solved it. It's a JSF issue, nothing to do with Spring Security.
I've overriden the restoreView method of jsf this way:
#Override
public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
UIViewRoot root = wrapped.restoreView(facesContext, viewId);
if(root == null) {
root = createView(facesContext, viewId);
}
return root;
}
Now the problem is that if the page had parameters, I lost them when I do the post to the recently created view, but that's another distinct issue (PRG pattern) dealing again with JSF.

SharePoint 2010: Disable / Hide references to SPSDisco.aspx

After upgrading some of our external websites running on SharePoint 2007 to 2010, we ran a link checker to find problems. We noticed the log showed requests for a file called spsdisco.aspx. Indeed, when examining the source of our web pages, SharePoint is adding the following link element to the page HEAD:
<link href="_vti_bin/spsdisco.aspx" rel="alternate" type="text/xml" />
This is a web service discovery file listing out the names and locations of all of SharePoint's web service endpoints. Even worse, this file is starting to show up in search indexes. At best it is embarrassing; at worst it's a potential vulnerability (these are external websites). Because it's a virtual file, it shows up under every site and subsite, so a manual approach to "hiding" each one is difficult and clumsy.
I can't seem to find any actual documentation about it -- a few references on updating it to include a custom web service, but that's about it. How might we approach a reliable, top-down approach to disabling access to these pages? I think we can find a way to suppress the LINK element in the page, but that's just obscuring the problem.
Is there a location in SharePoint (Site or Central Admin) to turn it off? Would you just add some request filtering to IIS to disallow access to SPSdisco.aspx and the ASMX files?
Update: On Kev's suggestion, I've cross-posted to sharepoint.stackexchange.com.
Update 2: See, I hadn't abandoned this question. We finally had time to get some MS guidance and build a deployable SharePoint solution to address the issue.
As a quick fix I would add a request filtering rule to deny access to SPSDisco.aspx.
But you might want to ask on the new SharePoint Stack Exchange site about a more robust fix:
https://sharepoint.stackexchange.com/
Here is the solution that we arrived at. It was in part based on recommendations by our Microsoft representative, so you might consider this an unofficial, "official" approach.
First, we need keep SharePoint from advertising the disco file to the world (i.e. Google). Simply remove the following line in your master pages:
<SharePoint:SoapDiscoveryLink runat="server"/>
This will suppress the <link href="/_vti_bin/spsdisco.aspx" rel="alternate" type="text/xml"> reference in the HEAD of your pages.
Next, we want to make sure that unauthorized users don't have access to the web services described by the disco file, or anything in _vti_bin for that matter. If your site only runs internal to your firewall (an intranet, for example), then this isn't as important. But if you've got anonymous endpoints that can be accessed externally, you want them locked down.
This is an excellent application for an HttpModule. We'll build one that intercepts any request containing _vti_bin in the path, and if the current user is unauthorized will return a 404 NOT FOUND status code. I chose to return a 404 rather than a 401 UNAUTHORIZED because I don't just want to lock those paths down, I want to hide the fact that anything even exists at those paths.
Our HttpModule looks like this:
using System;
using System.Web;
namespace Custom.SharePoint.HttpModule.SpSecureVtiBin {
public class SpSecureVtiBinModule : IHttpModule {
#region IHttpModule Members
public void Dispose() { }
public void Init( HttpApplication context ) {
context.AuthorizeRequest += new EventHandler( context_AuthorizeRequest );
}
protected virtual void context_AuthorizeRequest( object sender, EventArgs e ) {
HttpApplication app = (HttpApplication)sender;
string requestedPath = app.Request.Path;
if ( requestedPath.ToLowerInvariant().Contains( "_vti_bin" ) ) {
if ( !app.Request.IsAuthenticated ) {
app.Response.StatusCode = 404;
app.Response.StatusDescription = "Not Found";
app.Response.Write( "404 NOT FOUND" );
app.Response.End();
}
}
}
#endregion
}
}
Simple enough. To use the HttpModule, it needs to be registered in the site's web.config file with an entry under \configuration\system.webServer\modules:
<add name="SpSecureVtiBinModule" type="Custom.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule, Custom.SharePoint.HttpModule.SpSecureVtiBin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[your_public_key_token]" />
Of course, we don't want to modify a SharePoint application's web.config file manually. We'll create an SPFeatureReceiver to do the job:
using System.Collections.ObjectModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace Custom.SharePoint.HttpModule.SpSecureVtiBin {
public class ModuleFeatureReceiver : SPFeatureReceiver {
private static string _owner = "SpSecureVtiBinModule";
public override void FeatureActivated( SPFeatureReceiverProperties properties ) {
SPWebApplication app = (SPWebApplication)properties.Feature.Parent;
app.WebConfigModifications.Add( GetModificationForSystemWebServer() );
app.WebService.ApplyWebConfigModifications();
app.Update();
}
public override void FeatureDeactivating( SPFeatureReceiverProperties properties ) {
SPWebApplication app = (SPWebApplication)properties.Feature.Parent;
Collection<SPWebConfigModification> mods = app.WebConfigModifications;
int modCount = mods.Count;
bool modRemoved = false;
for ( int i = modCount - 1; i >= 0; i-- ) {
SPWebConfigModification mod = mods[i];
if ( mod.Owner.Equals( _owner ) || mod.Owner.Equals( "CHK.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule" ) ) {
app.WebConfigModifications.Remove( mod );
modRemoved = true;
}
}
if ( modRemoved ) {
app.WebService.ApplyWebConfigModifications();
app.Update();
}
}
private SPWebConfigModification GetModificationForSystemWebServer() {
return new SPWebConfigModification {
Name = "add[#name='SpSecureVtiBinModule']",
Owner = _owner,
Path = "configuration/system.webServer/modules",
Value = #"<add name=""SpSecureVtiBinModule"" type=""Custom.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule, Custom.SharePoint.HttpModule.SpSecureVtiBin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[your_public_key_token]"" />",
Sequence = 0
};
}
}
}
Now all that's left is to package up the HttpModule. You'll need to define a Feature in the package and reference the SPFeatureReceiver class. This will cause the web.config entry to be added when the Feature is activated, and the entry to be removed when the Feature is deactivated. Target the Feature for a WebApplication and the assembly deployment target to GlobalAssemblyCache.

Can i use WebSphere 6.1 for JSFunit?

I am doing work on jsfunit, and i am using WebSphere6.1 application server so can anyone give me answer that is it compatible for JSFunit or i need to do some changes in my server configuration? if possible send me the example?
Thanks
Vinod
Yes,
Read JSFUnitOnWebSphere:
So to use WebSphere with JSFUnit, you
will need to create a class that
extends one of the
InitialRequestStrategy classes. See
JSFUnitTestingSecurePages for other
examples, but the following should
work for non-secure pages
public class WebSphereRequestStrategy extends org.jboss.jsfunit.framework.SimpleInitialRequestStrategy {
public Page doInitialRequest(WebClientSpec wcSpec) throws IOException {
String jsessionid = wcSpec.removeCookie("JSESSIONID");
wcSpec.addCookie("JSESSIONID", "0000" + jsessionid); // cache ID is 0000 by default
return super.doInitialRequest(wcSpec);
}
}
Then you will use this code to start
your test:
WebClientSpec wcSpec = new WebClientSpec("/index.jsf");
wcSpec.setInitialRequestStrategy(new WebSphereRequestStrategy());
JSFSession jsfSession = new JSFSession(wcSpec);
JSFClientSession client = jsfSession.getJSFClientSession();
JSFServerSession server = jsfSession.getJSFServerSession();

Resources