[rhq] modules/plugins
by Larry O'Leary
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit d1d18876b9f22a681e7243ef54aa649d066e8656
Author: Larry O'Leary <loleary(a)redhat.com>
Date: Tue Jan 3 16:37:31 2012 -0600
[Bug 769470] TomcatWarDiscoveryComponent excludes valid WAR deployments due to eager host name regular expression
Changed regular expression used to extract host name from context name to stop at first slash instead of last slash.
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
index f6fa791..7605749 100644
--- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
+++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
@@ -1,5 +1,5 @@
/** Jopr Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -58,7 +58,7 @@ public class TomcatWarDiscoveryComponent extends MBeanResourceDiscoveryComponent
private static final List<String> EMS_ATTRIBUTE_DOC_BASE = Arrays.asList(new String[] { "docBase" });
private static final List<String> EMS_ATTRIBUTE_PATH = Arrays.asList(new String[] { "path" });
/** The name MBean attribute for each application is of the form "Tomcat WAR (//vHost/contextRoot)". */
- private static final Pattern PATTERN_NAME = Pattern.compile("//(.*)(/.*)");
+ private static final Pattern PATTERN_NAME = Pattern.compile("^//([^/]+)(.*)$");
private static final String RT_LOG_FILE_NAME_SUFFIX = "_rt.log";
private final Log log = LogFactory.getLog(this.getClass());
12 years, 5 months
[rhq] Branch 'release_jon3.0.x' - modules/plugins
by Larry O'Leary
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit b780c78458dd162fdc7d488464212f304b5b3489
Author: Larry O'Leary <loleary(a)redhat.com>
Date: Tue Jan 3 16:37:31 2012 -0600
[Bug 769470] TomcatWarDiscoveryComponent excludes valid WAR deployments due to eager host name regular expression
Changed regular expression used to extract host name from context name to stop at first slash instead of last slash.
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
index f6fa791..7605749 100644
--- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
+++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
@@ -1,5 +1,5 @@
/** Jopr Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -58,7 +58,7 @@ public class TomcatWarDiscoveryComponent extends MBeanResourceDiscoveryComponent
private static final List<String> EMS_ATTRIBUTE_DOC_BASE = Arrays.asList(new String[] { "docBase" });
private static final List<String> EMS_ATTRIBUTE_PATH = Arrays.asList(new String[] { "path" });
/** The name MBean attribute for each application is of the form "Tomcat WAR (//vHost/contextRoot)". */
- private static final Pattern PATTERN_NAME = Pattern.compile("//(.*)(/.*)");
+ private static final Pattern PATTERN_NAME = Pattern.compile("^//([^/]+)(.*)$");
private static final String RT_LOG_FILE_NAME_SUFFIX = "_rt.log";
private final Log log = LogFactory.getLog(this.getClass());
12 years, 5 months
[rhq] Branch 'release_jon2.4.2.GA' - modules/plugins
by Larry O'Leary
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit 42d3422494523dda7ad6f8036e21fdfed8c5b082
Author: Larry O'Leary <loleary(a)redhat.com>
Date: Tue Jan 3 16:37:31 2012 -0600
[Bug 769470] TomcatWarDiscoveryComponent excludes valid WAR deployments due to eager host name regular expression
Changed regular expression used to extract host name from context name to stop at first slash instead of last slash.
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
index f6fa791..7605749 100644
--- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
+++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
@@ -1,5 +1,5 @@
/** Jopr Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -58,7 +58,7 @@ public class TomcatWarDiscoveryComponent extends MBeanResourceDiscoveryComponent
private static final List<String> EMS_ATTRIBUTE_DOC_BASE = Arrays.asList(new String[] { "docBase" });
private static final List<String> EMS_ATTRIBUTE_PATH = Arrays.asList(new String[] { "path" });
/** The name MBean attribute for each application is of the form "Tomcat WAR (//vHost/contextRoot)". */
- private static final Pattern PATTERN_NAME = Pattern.compile("//(.*)(/.*)");
+ private static final Pattern PATTERN_NAME = Pattern.compile("^//([^/]+)(.*)$");
private static final String RT_LOG_FILE_NAME_SUFFIX = "_rt.log";
private final Log log = LogFactory.getLog(this.getClass());
12 years, 5 months
[rhq] Branch 'release-3.0.1' - modules/plugins
by Larry O'Leary
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit 8b30ae467afc3840f1703dd55e44b98b17688ecc
Author: Larry O'Leary <loleary(a)redhat.com>
Date: Tue Jan 3 16:37:31 2012 -0600
[Bug 769470] TomcatWarDiscoveryComponent excludes valid WAR deployments due to eager host name regular expression
Changed regular expression used to extract host name from context name to stop at first slash instead of last slash.
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
index f6fa791..7605749 100644
--- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
+++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
@@ -1,5 +1,5 @@
/** Jopr Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -58,7 +58,7 @@ public class TomcatWarDiscoveryComponent extends MBeanResourceDiscoveryComponent
private static final List<String> EMS_ATTRIBUTE_DOC_BASE = Arrays.asList(new String[] { "docBase" });
private static final List<String> EMS_ATTRIBUTE_PATH = Arrays.asList(new String[] { "path" });
/** The name MBean attribute for each application is of the form "Tomcat WAR (//vHost/contextRoot)". */
- private static final Pattern PATTERN_NAME = Pattern.compile("//(.*)(/.*)");
+ private static final Pattern PATTERN_NAME = Pattern.compile("^//([^/]+)(.*)$");
private static final String RT_LOG_FILE_NAME_SUFFIX = "_rt.log";
private final Log log = LogFactory.getLog(this.getClass());
12 years, 5 months
[rhq] Branch 'release-3.0.1' - modules/enterprise
by Larry O'Leary
modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml | 165 +++++++++-
1 file changed, 164 insertions(+), 1 deletion(-)
New commits:
commit 153e92493dc94a774f967dcdbec39fcd457ab2c1
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Fri May 13 13:11:32 2011 -0400
[BZ 693232] fix SLSB heap leak (https://bugzilla.redhat.com/show_bug.cgi?id=693232)
diff --git a/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml b/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml
index 95354d8..b7c5c66 100644
--- a/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml
+++ b/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml
@@ -1,5 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
-<jboss>
+<jboss xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
+ version="3.0">
+
+ <enterprise-beans>
+
+ <!--
+ The AlertConditionLogManagerBean, AlertConditionManagerBean, AlertDampeningManagerBean,
+ AlertDefinitionManagerBean, AlertManagerBean, AuthorizationManagerBean, CachedConditionManagerBean, and
+ SubjectManager SLSB's are all invoked, either directly or indirectly, by the AlertConditionConsumerBean MDB.
+ Since MDB invocations are always done in new threads, using the default SLSB pool impl (ThreadlocalPool) would
+ cause a new instance of these SLSB's to be created every time they were invoked by AlertConditionConsumerBean.
+ This would be bad if only because existing instances would
+ not be reused, but it is really bad because the instances would also never get destroyed, causing heap space to
+ gradually leak until the Server eventually ran out of memory. Hence, we must use a StrictMaxPool, which
+ will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool. Because lots of alert
+ definitions could result in many concurrent calls to AlertConditionConsumerBean, and because most of these
+ SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's), we set the max pool size to 100 to
+ minimize the chances of AlertConditionConsumerBean invocations, which are the most critical, from having to
+ block and potentially getting backed up in the queue. We set the pool timeout extremely high to essentially
+ prevent queued callers from timing out. Note, MDB's are configured in ejb3-interceptors-aop.xml to use a strict
+ max pool with a max of 15 and a timeout of 10000, so AlertConditionConsumerBean might become a bottleneck for
+ systems with a lot of alerts defined. (ips, 05/10/11)
+
+ For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
+ -->
+
+ <session>
+ <ejb-name>AlertConditionLogManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertConditionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertDampeningManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertDefinitionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AuthorizationManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>CachedConditionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>SubjectManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+
+ <!--
+ The CacheConsistencyManagerBean, CloudManagerBean, ServerManagerBean, StatusManagerBean, and SystemManagerBean
+ SLSB's are all invoked, either directly or indirectly, by EJB timers. Since EJB timer invocations are always
+ done in new threads, using the default SLSB pool impl (ThreadlocalPool) would cause a new instance of this
+ SLSB to be created every time it was invoked by an EJB timer. This would be bad if only because an existing
+ instance would not be reused, but it is really bad because the instance would also never get destroyed, causing
+ heap space to gradually leak until the Server eventually ran out of memory. Hence, we must use a
+ StrictMaxPool, which will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool.
+ The timer invocations will only require one or two instances at any given time, but because most of these
+ SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's, we set the max pool size to 30, to
+ minimize the chances of EJB timer invocations, which are the most critical, from having to block and
+ potentially getting backed up in the queue. We set the pool timeout extremely high to essentially prevent
+ queued callers from timing out. (ips, 05/10/11)
+
+ For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
+ -->
+
+ <session>
+ <ejb-name>CacheConsistencyManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>CloudManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>ServerManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>StatusManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>SystemManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ </enterprise-beans>
</jboss>
12 years, 5 months
[rhq] Branch 'release_jon2.4.2.GA' - modules/enterprise
by Larry O'Leary
modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml | 165 +++++++++-
1 file changed, 164 insertions(+), 1 deletion(-)
New commits:
commit 6926e2be64318a8f872bb56aed70d262ef1df502
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Fri May 13 13:11:32 2011 -0400
[BZ 693232] fix SLSB heap leak (https://bugzilla.redhat.com/show_bug.cgi?id=693232)
diff --git a/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml b/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml
index 95354d8..b7c5c66 100644
--- a/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml
+++ b/modules/enterprise/server/jar/src/main/resources/META-INF/jboss.xml
@@ -1,5 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
-<jboss>
+<jboss xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
+ version="3.0">
+
+ <enterprise-beans>
+
+ <!--
+ The AlertConditionLogManagerBean, AlertConditionManagerBean, AlertDampeningManagerBean,
+ AlertDefinitionManagerBean, AlertManagerBean, AuthorizationManagerBean, CachedConditionManagerBean, and
+ SubjectManager SLSB's are all invoked, either directly or indirectly, by the AlertConditionConsumerBean MDB.
+ Since MDB invocations are always done in new threads, using the default SLSB pool impl (ThreadlocalPool) would
+ cause a new instance of these SLSB's to be created every time they were invoked by AlertConditionConsumerBean.
+ This would be bad if only because existing instances would
+ not be reused, but it is really bad because the instances would also never get destroyed, causing heap space to
+ gradually leak until the Server eventually ran out of memory. Hence, we must use a StrictMaxPool, which
+ will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool. Because lots of alert
+ definitions could result in many concurrent calls to AlertConditionConsumerBean, and because most of these
+ SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's), we set the max pool size to 100 to
+ minimize the chances of AlertConditionConsumerBean invocations, which are the most critical, from having to
+ block and potentially getting backed up in the queue. We set the pool timeout extremely high to essentially
+ prevent queued callers from timing out. Note, MDB's are configured in ejb3-interceptors-aop.xml to use a strict
+ max pool with a max of 15 and a timeout of 10000, so AlertConditionConsumerBean might become a bottleneck for
+ systems with a lot of alerts defined. (ips, 05/10/11)
+
+ For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
+ -->
+
+ <session>
+ <ejb-name>AlertConditionLogManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertConditionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertDampeningManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertDefinitionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AuthorizationManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>CachedConditionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>SubjectManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+
+ <!--
+ The CacheConsistencyManagerBean, CloudManagerBean, ServerManagerBean, StatusManagerBean, and SystemManagerBean
+ SLSB's are all invoked, either directly or indirectly, by EJB timers. Since EJB timer invocations are always
+ done in new threads, using the default SLSB pool impl (ThreadlocalPool) would cause a new instance of this
+ SLSB to be created every time it was invoked by an EJB timer. This would be bad if only because an existing
+ instance would not be reused, but it is really bad because the instance would also never get destroyed, causing
+ heap space to gradually leak until the Server eventually ran out of memory. Hence, we must use a
+ StrictMaxPool, which will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool.
+ The timer invocations will only require one or two instances at any given time, but because most of these
+ SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's, we set the max pool size to 30, to
+ minimize the chances of EJB timer invocations, which are the most critical, from having to block and
+ potentially getting backed up in the queue. We set the pool timeout extremely high to essentially prevent
+ queued callers from timing out. (ips, 05/10/11)
+
+ For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
+ -->
+
+ <session>
+ <ejb-name>CacheConsistencyManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>CloudManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>ServerManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>StatusManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>SystemManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ </enterprise-beans>
</jboss>
12 years, 5 months
[rhq] Branch 'stefan/backingcontent' - modules/core modules/enterprise
by snegrea
modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java | 3 +
modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java | 13 ++++----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java | 3 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerBean.java | 16 ++++++----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java | 4 +-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java | 1
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java | 2 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java | 4 +-
8 files changed, 28 insertions(+), 18 deletions(-)
New commits:
commit 744169a0fdbcbbc57c6d175b5eca9d4f3daa1f2a
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Jan 3 15:07:14 2012 -0600
[BZ 771418] updateBackingContent now requires a version from the user. This version will be used as a display version for the uploaded package.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java
index 7096645..6a1af87 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java
@@ -71,7 +71,8 @@ import org.rhq.core.domain.util.OSGiVersionComparator;
+ " WHERE pv.generalPackage.name = :packageName " //
+ " AND pv.generalPackage.packageType.name = :packageTypeName " //
+ " AND pv.generalPackage.packageType.resourceType.id = :resourceTypeId " //
- + " AND pv.sha256 = :sha "),
+ + " AND pv.sha256 = :sha "
+ + " ORDER BY pv.id DESC "),
@NamedQuery(name = PackageVersion.QUERY_FIND_BY_PACKAGE_VER_ARCH, query = "SELECT pv FROM PackageVersion AS pv "
+ " WHERE pv.generalPackage.name = :name " + " AND pv.generalPackage.packageType.id = :packageTypeId "
+ " AND pv.architecture.id = :architectureId " + " AND pv.version = :version "),
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
index eade28b..5390752 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
@@ -29,11 +29,11 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import javassist.util.proxy.MethodHandler;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import javassist.util.proxy.MethodHandler;
-
import org.rhq.bindings.util.ConfigurationClassBuilder;
import org.rhq.bindings.util.LazyLoadScenario;
import org.rhq.bindings.util.ResourceTypeFingerprint;
@@ -505,7 +505,7 @@ public class ResourceClientProxy {
return remoteClient.getContentManager().getBackingPackageForResource(remoteClient.getSubject(), resourceClientProxy.resourceId);
}
- public void updateBackingContent(String filename) {
+ public void updateBackingContent(String filename, String contentVersion) {
File file = new File(filename);
if (!file.exists()) {
throw new IllegalArgumentException("File not found: " + file.getAbsolutePath());
@@ -524,7 +524,7 @@ public class ResourceClientProxy {
LOG.error("Message digest for the package bits failed.", e);
}
- String version = "[sha256="+sha+"]";
+ String packageVersion = "[sha256="+sha+"]";
InstalledPackage oldPackage = getBackingContent();
@@ -533,7 +533,8 @@ public class ResourceClientProxy {
remoteClient.getSubject(),
oldPackage.getPackageVersion().getGeneralPackage().getName(),
oldPackage.getPackageVersion().getGeneralPackage().getPackageType().getId(),
- version,
+ packageVersion,
+ contentVersion,
oldPackage.getPackageVersion().getArchitecture().getId(),
fileContents);
@@ -644,7 +645,7 @@ public class ResourceClientProxy {
public InstalledPackage getBackingContent();
- public void updateBackingContent(String fileName);
+ public void updateBackingContent(String fileName, String contentVersion);
public void retrieveBackingContent(String fileName) throws IOException;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
index 3c2111a..20c53bc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
@@ -28,7 +28,6 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -760,7 +759,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
architecture = (Architecture) q.getSingleResult();
}
PackageVersion packageVersion = contentManager.createPackageVersion(subject, name, packageType.getId(),
- version, architecture.getId(), fileStream);
+ version, null, architecture.getId(), fileStream);
// set the PackageVersion's filename to the bundleFile name, it's left null by default
packageVersion.setFileName(name);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerBean.java
index 5b03fd2..fd1db2a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerBean.java
@@ -93,7 +93,6 @@ import org.rhq.core.domain.criteria.PackageCriteria;
import org.rhq.core.domain.criteria.PackageVersionCriteria;
import org.rhq.core.domain.resource.Agent;
import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceCreationDataType;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.util.MessageDigestGenerator;
@@ -1234,7 +1233,7 @@ public class ContentManagerBean implements ContentManagerLocal, ContentManagerRe
}
}
- public PackageVersion createPackageVersion(Subject subject, String packageName, int packageTypeId, String version,
+ public PackageVersion createPackageVersion(Subject subject, String packageName, int packageTypeId, String version, String displayVersion,
Integer architectureId, byte[] packageBytes) {
// Check permissions first
@@ -1243,13 +1242,13 @@ public class ContentManagerBean implements ContentManagerLocal, ContentManagerRe
+ "] does not have permission to create package versions");
}
- return createPackageVersion(subject, packageName, packageTypeId, version, (null == architectureId) ? getNoArchitecture()
+ return createPackageVersion(subject, packageName, packageTypeId, version, displayVersion, (null == architectureId) ? getNoArchitecture()
.getId() : architectureId, new ByteArrayInputStream(packageBytes));
}
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public PackageVersion createPackageVersion(Subject subject, String packageName, int packageTypeId,
- String version, int architectureId, InputStream packageBitStream) {
+ String version, String displayVersion, int architectureId, InputStream packageBitStream) {
// See if the package version already exists and return that if it does
Query packageVersionQuery = entityManager.createNamedQuery(PackageVersion.QUERY_FIND_BY_PACKAGE_VER_ARCH);
packageVersionQuery.setParameter("name", packageName);
@@ -1260,7 +1259,13 @@ public class ContentManagerBean implements ContentManagerLocal, ContentManagerRe
// Result of the query should be either 0 or 1
List existingVersionList = packageVersionQuery.getResultList();
if (existingVersionList.size() > 0) {
- return (PackageVersion) existingVersionList.get(0);
+ PackageVersion existingPackageVersion = (PackageVersion) existingVersionList.get(0);
+ if (displayVersion != null && !displayVersion.trim().isEmpty()) {
+ existingPackageVersion.setDisplayVersion(displayVersion);
+ existingPackageVersion = persistOrMergePackageVersionSafely(existingPackageVersion);
+ }
+
+ return existingPackageVersion;
}
Architecture architecture = entityManager.find(Architecture.class, architectureId);
@@ -1315,6 +1320,7 @@ public class ContentManagerBean implements ContentManagerLocal, ContentManagerRe
newPackageVersion.setPackageBits(bits);
newPackageVersion.setFileSize(Long.valueOf(contentDetails.get(UPLOAD_FILE_SIZE)).longValue());
newPackageVersion.setSHA256(contentDetails.get(UPLOAD_SHA256));
+ newPackageVersion.setDisplayVersion(displayVersion);
existingPackage.addVersion(newPackageVersion);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
index 566b4fc..9819ee7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
@@ -240,7 +240,7 @@ public interface ContentManagerLocal {
* one was found
*/
PackageVersion createPackageVersion(Subject subject, String packageName, int packageTypeId, String version,
- int architectureId, InputStream packageBitStream);
+ String displayVersion, int architectureId, InputStream packageBitStream);
/**
* This method is essentially the same as {@link #createPackageVersion(Subject, String, int, String, int, InputStream)}
@@ -350,7 +350,7 @@ public interface ContentManagerLocal {
* @see {@link createPackageVersion(Subject, String, int, String, int, byte[]);
*/
PackageVersion createPackageVersion(Subject subject, String packageName, int packageTypeId, String version,
- Integer architectureId, byte[] packageBytes);
+ String displayVersion, Integer architectureId, byte[] packageBytes);
/**
* @see {@link ContentManagerRemote#deletePackages(Subject, int, int[], String)}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
index 0038824..439c8a7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
@@ -69,6 +69,7 @@ public interface ContentManagerRemote {
@WebParam(name = "packageName") String packageName, //
@WebParam(name = "packageTypeId") int packageTypeId, //
@WebParam(name = "version") String version, //
+ @WebParam(name = "displayVersion") String displayVersion, //
@WebParam(name = "architectureId") Integer architectureId, //
@WebParam(name = "packageBytes") byte[] packageBytes);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
index 2395503..0e5a0ca 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
@@ -447,7 +447,7 @@ public class ResourceFactoryManagerBean implements ResourceFactoryManagerLocal,
PackageVersion packageVersion = null;
if (packageUploadDetails == null) {
packageVersion = contentManager.createPackageVersion(user, packageName, newPackageType.getId(),
- packageVersionNumber, architectureId, packageBitStream);
+ packageVersionNumber, null, architectureId, packageBitStream);
} else {
packageVersion = contentManager.getUploadedPackageVersion(user, packageName, newPackageType.getId(),
packageVersionNumber, architectureId, packageBitStream, packageUploadDetails, null);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
index 54725a6..f5d4a36 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
@@ -507,8 +507,10 @@ public class WebservicesManagerBean implements WebservicesRemote {
//CONTENTMANAGER: BEGIN ----------------------------------
public PackageVersion createPackageVersion(Subject subject, String packageName, int packageTypeId, String version,
+ String displayVersion,
Integer architectureId, byte[] packageBytes) {
- return contentManager.createPackageVersion(subject, packageName, packageTypeId, version, architectureId,
+ return contentManager.createPackageVersion(subject, packageName, packageTypeId, version, displayVersion,
+ architectureId,
packageBytes);
}
12 years, 5 months
[rhq] modules/enterprise
by Heiko W. Rupp
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java | 103 +++++-----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java | 10
2 files changed, 60 insertions(+), 53 deletions(-)
New commits:
commit caff389ecc3e3f6c53e9880f840c1995241a92a4
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jan 3 15:19:18 2012 +0100
Some cleanup, return location for PUT metric, allow to expose raw metrics as xml too.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 77e36a4..a772ab4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -123,30 +123,8 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
List<List<MeasurementDataNumericHighLowComposite>> listList = dataManager.findDataForResource(caller,
schedule.getResource().getId(), new int[]{definitionId}, startTime, endTime, dataPoints);
-/*
- long minTime=Long.MAX_VALUE;
- long maxTime=0;
-*/
-
if (!listList.isEmpty()) {
List<MeasurementDataNumericHighLowComposite> list = listList.get(0);
-/*
- for (MeasurementDataNumericHighLowComposite c : list) {
- long timestamp = c.getTimestamp();
- if (!Double.isNaN(c.getValue()) || !hideEmpty) {
- MetricAggregate.DataPoint dp = new MetricAggregate.DataPoint(timestamp,c.getValue(),c.getHighValue(),c.getLowValue());
- res.addDataPoint(dp);
- }
- if (timestamp <minTime)
- minTime= timestamp;
- if (timestamp >maxTime)
- maxTime= timestamp;
- }
- res.setNumDataPoints(list.size());
- }
- res.setMaxTimeStamp(maxTime);
- res.setMinTimeStamp(minTime);
-*/
fill(res, list,scheduleId,hideEmpty);
}
@@ -156,7 +134,6 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
cc.setPrivate(false);
cc.setNoCache(false);
-
Response.ResponseBuilder builder;
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
@@ -224,6 +201,8 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
@QueryParam("hideEmpty") boolean hideEmpty, @Context Request request,
@Context HttpHeaders headers) {
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+
if (startTime==0) {
endTime = System.currentTimeMillis();
startTime = endTime - EIGHT_HOURS;
@@ -259,7 +238,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
GenericEntity<List<MetricAggregate>> metAgg = new GenericEntity<List<MetricAggregate>>(resList) {};
- return Response.ok(metAgg).build();
+ return Response.ok(metAgg,mediaType).build();
}
@@ -275,8 +254,10 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
*/
public Response getSchedule(int scheduleId, Request request, HttpHeaders headers, UriInfo uriInfo) {
- MeasurementSchedule schedule=null;
- Response.ResponseBuilder builder=null;
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+
+ MeasurementSchedule schedule;
+ Response.ResponseBuilder builder;
// Create a cache control
CacheControl cc = new CacheControl();
@@ -351,9 +332,6 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
Link updateLink = new Link("edit",uri.toString());
metricSchedule.addLink(updateLink);
- // What media type does the user request?
- MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
-
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder = Response.ok(renderTemplate("metricSchedule", metricSchedule), mediaType);
}
@@ -427,6 +405,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
Request request,
HttpHeaders headers) {
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
if (endTime==0)
endTime = System.currentTimeMillis();
@@ -441,10 +420,11 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
// Check if the schedule exists
obtainSchedule(scheduleId);
- RawNumericJsonStreamingOutput so = new RawNumericJsonStreamingOutput();
+ RawNumericStreamingOutput so = new RawNumericStreamingOutput();
so.scheduleId = scheduleId;
so.startTime = startTime;
so.endTime = endTime;
+ so.mediaType = mediaType;
return so;
@@ -456,8 +436,9 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("data/{scheduleId}/raw/{timeStamp}")
public Response putMetricValue(@PathParam("scheduleId") int scheduleId, @PathParam("timeStamp") long timestamp,
- NumericDataPoint point, @Context HttpHeaders headers) {
+ NumericDataPoint point, @Context HttpHeaders headers, UriInfo uriInfo) {
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
MeasurementSchedule schedule = obtainSchedule(scheduleId);
Set<MeasurementDataNumeric> data = new HashSet<MeasurementDataNumeric>(1);
@@ -465,7 +446,13 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
dataManager.addNumericData(data);
- return Response.ok().build(); // TODO correct code?
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/metric/data/{scheduleId}/raw");
+ uriBuilder.queryParam("startTime",timestamp);
+ uriBuilder.queryParam("endTime",timestamp);
+ URI uri = uriBuilder.build(scheduleId);
+
+ return Response.created(uri).type(mediaType).build();
}
@@ -475,6 +462,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response postMetricValues(Collection<NumericDataPoint> points, @Context HttpHeaders headers) {
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
Set<MeasurementDataNumeric> data = new HashSet<MeasurementDataNumeric>(points.size());
for (NumericDataPoint point : points) {
data.add(new MeasurementDataNumeric(point.getTimeStamp(), point.getScheduleId(),point.getValue()));
@@ -482,7 +470,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
dataManager.addNumericData(data);
- return Response.ok().build();
+ return Response.noContent().type(mediaType).build();
}
@@ -491,11 +479,12 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
* without creating tons of objects in the middle to have them marshalled
* by JAX-RS
*/
- private class RawNumericJsonStreamingOutput implements StreamingOutput {
+ private class RawNumericStreamingOutput implements StreamingOutput {
int scheduleId;
long startTime;
long endTime;
+ MediaType mediaType;
@Override
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
@@ -528,22 +517,38 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
rs = ps.executeQuery();
PrintWriter pw = new PrintWriter(outputStream);
- pw.println("[");
- while (rs.next()) {
- pw.print("{");
- pw.print("\"scheduleId\":");
- pw.print(scheduleId);
- pw.print(", ");
- pw.print("\"timeStamp\":");
- pw.print(rs.getLong(1));
- pw.print(", ");
- pw.print("\"value\":");
- pw.print(rs.getLong(2));
- pw.print("}");
- if (!rs.isLast())
- pw.print(",\n");
+
+ if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
+ pw.println("[");
+ while (rs.next()) {
+ pw.print("{");
+ pw.print("\"scheduleId\":");
+ pw.print(scheduleId);
+ pw.print(", ");
+ pw.print("\"timeStamp\":");
+ pw.print(rs.getLong(1));
+ pw.print(", ");
+ pw.print("\"value\":");
+ pw.print(rs.getDouble(2));
+ pw.print("}");
+ if (!rs.isLast())
+ pw.print(",\n");
+ }
+ pw.println("]");
+ }
+ else if (mediaType.equals(MediaType.APPLICATION_XML_TYPE)) {
+ pw.println("<collection>");
+ while(rs.next()) {
+ pw.print(" <numericDataPoint scheduleId=\"");
+ pw.print(scheduleId);
+ pw.print("\" timeStamp=\"");
+ pw.print(rs.getLong(1));
+ pw.print("\" value=\"");
+ pw.print(rs.getDouble(2));
+ pw.println("\"/>");
+ }
+ pw.println("</collection>");
}
- pw.println("]");
pw.flush();
pw.close();
} catch (SQLException e) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 2c75a55..6f76bce 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -119,7 +119,7 @@ public interface MetricHandlerLocal {
*/
@GET
@Path("data/{scheduleId}/raw")
- @Produces({MediaType.APPLICATION_JSON})
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
StreamingOutput getMetricDataRaw(@PathParam("scheduleId") int scheduleId,
@QueryParam("startTime") long startTime,
@QueryParam("endTime") long endTime,
@@ -133,15 +133,17 @@ public interface MetricHandlerLocal {
* @param timestamp Timestamp of the entry
* @param point Datapoint of class NumericDataPoint
* @param headers Injected HTTP headers
+ * @param uriInfo Injected info about the uri
* @return
*/
@PUT
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Path("data/{scheduleId}/raw/{timeStamp}")
- Response putMetricValue(@PathParam("scheduleId")int scheduleId,
- @PathParam("timeStamp")long timestamp, NumericDataPoint point,
- @Context HttpHeaders headers);
+ Response putMetricValue(@PathParam("scheduleId") int scheduleId,
+ @PathParam("timeStamp") long timestamp, NumericDataPoint point,
+ @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
/**
* Submit a series of (numerical) metric values to the server
12 years, 5 months
[rhq] 12 commits - modules/enterprise modules/integration-tests
by lkrejci
modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardScriptPermissions.java | 6
modules/enterprise/server/client-api/pom.xml | 347 +++++++++-
modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java | 20
modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java | 198 +++++
modules/enterprise/server/client-api/src/test/resources/hibernate.properties | 26
modules/enterprise/server/client-api/src/test/resources/jms-ra.rar |binary
modules/enterprise/server/client-api/src/test/resources/security.policy | 10
modules/enterprise/server/container-lib/pom.xml | 6
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java | 237 ++++++
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java | 177 +++++
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java | 60 +
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java | 36 +
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java | 105 +++
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java | 52 +
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java | 45 +
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java | 32
modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml | 7
modules/enterprise/server/jar/pom.xml | 7
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java | 36 -
modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml | 10
modules/integration-tests/jndi-access/jndi-access-test/pom.xml | 315 +++++++++
modules/integration-tests/jndi-access/jndi-access-test/src/test/java/org/rhq/jndi/test/JndiAccessTest.java | 193 +++++
modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/hibernate.properties | 26
modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/jms-ra.rar |binary
modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/log4j.xml | 78 ++
modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/security.policy | 10
modules/integration-tests/jndi-access/pom.xml | 21
modules/integration-tests/jndi-access/remote-server/pom.xml | 72 ++
modules/integration-tests/jndi-access/remote-server/src/main/java/org/rhq/jndi/test/Server.java | 79 ++
modules/integration-tests/jndi-access/remote-server/src/main/resources/jndi.properties | 2
modules/integration-tests/jndi-access/remote-server/src/main/resources/log4j.properties | 5
modules/integration-tests/pom.xml | 1
32 files changed, 2201 insertions(+), 18 deletions(-)
New commits:
commit 6945397a12e96fcaa7c92161e5f474abd98f7cad
Merge: 89027fe eb92c16
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jan 3 15:26:38 2012 +0100
Merge branch 'lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs'
commit eb92c16f4ac8151e1984406af677f950f9984af4
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jan 3 15:07:13 2012 +0100
updating the javadocs to correctly explain the purpose of the URLPreferringContext
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
index b291c3e..c6456a2 100644
--- a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
@@ -35,17 +35,18 @@ import javax.naming.spi.NamingManager;
* <p>
* This is important because RHQ server has its own initial context factory
* builder that creates factories that in turn create contexts. If the default
- * {@link InitialContext} implementation was used, we'd end up with a stack overflow
- * error caused by the callchain loop when the {@link InitialContext} would ask
- * the builder for a factory that would create another context that would ask the
- * builder for the factory, etc. ad infinitum.
+ * {@link InitialContext} implementation was used, we'd never be able to lookup
+ * scheme-based names because the default implementation of the {@link InitialContext}
+ * always uses the default context of the builder if one is installed no matter
+ * the scheme in the name.
* <p>
- * This class prevents that by acting exactly like the InitialContext would if
- * the initial context factory builder wasn't installed. This enables the callers
- * to still use the standard InitialContext when doing lookups etc. This standard
- * initial context will ask our initial context factory builder which will then
- * in chain create this {@link URLPreferringContext} that behaves like the original
- * InitialContext would if the builder wasn't there.
+ * The {@link AccessCheckingInitialContextFactoryBuilder} wraps the context returned
+ * by the factory in an instance of this class and thus is restoring the original
+ * intended behavior of the {@link InitialContext}. It looks at the name being looked
+ * up (bound or whatever) and prefers to use the URL context factories if the name
+ * contains the scheme (as does the {@link InitialContext} if no builder is installed).
+ * If the name doesn't contain a scheme, the provided default context factory is used to
+ * look up the name.
*
* @author Lukas Krejci
*/
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
index 6c311c7..609e98c 100644
--- a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
@@ -22,7 +22,6 @@ package org.rhq.jndi;
import java.util.Hashtable;
import javax.naming.Context;
-import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
@@ -31,8 +30,7 @@ import javax.naming.spi.InitialContextFactory;
* backed by the wrapped initial context factory.
* <p>
* This is to support contexts that don't need to be secured, yet we need to make sure to
- * break the call-chain loop caused by the {@link InitialContext} asking the RHQ's {@link AccessCheckingInitialContextFactoryBuilder} for
- * default contexts.
+ * re-enable lookup of scheme-based names.
*
* @author Lukas Krejci
*/
commit 0dcc5c33c0cc9ca03a32bd17dd8e188ca27b243d
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jan 3 14:47:12 2012 +0100
Adding integration tests for the ability of serverside scripts to access remote JNDI servers (unlike the JNDI directory of the RHQ server itself).
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
new file mode 100644
index 0000000..1991e0e
--- /dev/null
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -0,0 +1,315 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>jndi-access-test-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.3.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>jndi-access-test</artifactId>
+ <packaging>jar</packaging>
+
+ <name>JNDI access integration test</name>
+ <description>Tests for local and remote JNDI access from within serverside scripts.</description>
+
+ <properties>
+ <rhq.server.datasource>java:/RHQDS</rhq.server.datasource>
+ <rhq.server.ds-mapping>PostgreSQL</rhq.server.ds-mapping>
+ <jboss-embeddable-ejb3.version>1.0.0.Alpha9</jboss-embeddable-ejb3.version>
+ <jnp.port>54987</jnp.port>
+ <jnp.rmiPort>54988</jnp.rmiPort>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <!--================ Test Deps ================ -->
+
+ <!-- Note, the test deps are intentionally placed above the other
+ scoped deps because of classpath reasons. Maven orders the [test] classpath
+ in the order listed in the pom. We specifically need the embeddable-ejb3
+ jar above the standard ejb3 jars because we need the embeddble packages loaded
+ when testing. -->
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>test-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-core-client-api</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-container-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-server-client-api</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>jndi-access-remote-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss.jboss-embeddable-ejb3</groupId>
+ <artifactId>jboss-ejb3-all</artifactId>
+ <version>${jboss-embeddable-ejb3.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- NOTE: The remaining test deps correspond to the classes contained
+ in hibernate-all.jar and thirdparty-all.jar. -->
+
+ <dependency>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- needed by embedded ejb container -->
+ <dependency>
+ <groupId>trove</groupId>
+ <artifactId>trove</artifactId>
+ <version>1.0.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- needed by embedded ejb container -->
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.8.1</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- 3rd Party Deps -->
+
+ <!-- required by RHQ server classes, as well as EJB3 Embedded -->
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1-jboss</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>hibernate</groupId>
+ <artifactId>hibernate3</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement
+ section. -->
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
+ <dependency>
+ <groupId>hibernate-annotations</groupId>
+ <artifactId>hibernate-annotations</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement
+ section. -->
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
+ <dependency>
+ <groupId>hibernate-entitymanager</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ <version>1.4</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-annotations-ejb3</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement
+ section. -->
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
+ <!-- includes the org.jboss.ejb3.StrictMaxPool class, which is needed
+ by the PoolClass annotation used on some of our SLSB's -->
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-ejb3</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement
+ section. -->
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
+ <!-- for the transaction interrupt EJB3 interceptor -->
+ <dependency>
+ <groupId>org.jboss.transaction</groupId>
+ <artifactId>jboss-jta</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement
+ section. -->
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
+ <dependency>
+ <groupId>org.opensymphony.quartz</groupId>
+ <artifactId>quartz</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement
+ section. -->
+ <scope>provided</scope> <!-- by JBossAS itself, which the container build has packaged with 1.6.5 -->
+ </dependency>
+
+ <dependency>
+ <groupId>org.opensymphony.quartz</groupId>
+ <artifactId>quartz-oracle</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement
+ section. -->
+ <scope>provided</scope> <!-- by JBossAS itself, which the container build has packaged with 1.6.5 -->
+ </dependency>
+
+ <!-- This is needed cglib which is in turn needed by hibernate -->
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>2.3.18</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>${resteasy.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <!-- in order to get JMS to work properly in embedded
+ test container, extract jms-rs.rar classes -->
+ <execution>
+ <id>Extract JMS classes from RAR needed for JMS tests</id>
+ <phase>process-classes</phase>
+ <configuration>
+ <tasks>
+ <unzip src="src/test/resources/jms-ra.rar"
+ dest="target">
+ <patternset>
+ <include name="jms-ra.jar" />
+ </patternset>
+ </unzip>
+ <unzip src="target/jms-ra.jar"
+ dest="target/test-classes">
+ <patternset>
+ <include name="org/**" />
+ </patternset>
+ </unzip>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <!-- Everything but the web service tests, this is the standard
+ test execution -->
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <groups>${rhq.testng.includedGroups}</groups>
+ <systemPropertyVariables>
+ <embeddedDeployment>true</embeddedDeployment>
+ <deploymentDirectory>target/test-classes</deploymentDirectory>
+ <hibernate.dialect>${rhq.test.ds.hibernate-dialect}</hibernate.dialect>
+ <clean.db>${clean.db}</clean.db>
+ <test.server.jar.path>${settings.localRepository}/org/rhq/jndi-access-remote-server/${project.version}/jndi-access-remote-server-${project.version}.jar</test.server.jar.path>
+ <jnp.port>${jnp.port}</jnp.port>
+ <jnp.rmiPort>${jnp.rmiPort}</jnp.rmiPort>
+ </systemPropertyVariables>
+ <argLine>-Djava.security.manager -Djava.security.policy==target/test-classes/security.policy</argLine>
+ <additionalClasspathElements>
+ <!-- The below is required for tests to run against
+ Oracle. -->
+ <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc5/${ojdbc5.version}/ojdbc5-${ojdbc5.version}.jar</additionalClasspathElement>
+ </additionalClasspathElements>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/src/test/java/org/rhq/jndi/test/JndiAccessTest.java b/modules/integration-tests/jndi-access/jndi-access-test/src/test/java/org/rhq/jndi/test/JndiAccessTest.java
new file mode 100644
index 0000000..f20d4f1
--- /dev/null
+++ b/modules/integration-tests/jndi-access/jndi-access-test/src/test/java/org/rhq/jndi/test/JndiAccessTest.java
@@ -0,0 +1,193 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi.test;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.SerializablePermission;
+import java.security.PermissionCollection;
+import java.util.Collections;
+import java.util.Properties;
+
+import javax.naming.InitialContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Parameters;
+import org.testng.annotations.Test;
+
+import org.rhq.bindings.SandboxedScriptEngine;
+import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.StandardScriptPermissions;
+import org.rhq.bindings.util.PackageFinder;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.client.LocalClient;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.jndi.AllowRhqServerInternalsAccessPermission;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class JndiAccessTest extends AbstractEJB3Test {
+ private static final Log JNP_SERVER_LOG = LogFactory.getLog("Test JNP Server");
+
+ private Process testServerProcess;
+ private Thread testServerStdErrReader;
+ private Thread testServerStdOutReader;
+
+ @BeforeClass
+ @Parameters({"test.server.jar.path", "jnp.port", "jnp.rmiPort"})
+ public void startTestJnpServer(String testServerJar, int jnpPort, int rmiPort) throws Exception {
+ ProcessBuilder bld = new ProcessBuilder("java", "-Djnp.port=" + jnpPort, "-Djnp.rmiPort=" + rmiPort, "-jar", testServerJar);
+
+ testServerProcess = bld.start();
+
+ testServerStdErrReader = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ BufferedReader rdr = new BufferedReader(new InputStreamReader(testServerProcess.getErrorStream()));
+ try {
+ String line;
+ while((line = rdr.readLine()) != null) {
+ JNP_SERVER_LOG.warn(line);
+ }
+ } catch (IOException e) {
+ JNP_SERVER_LOG.error("Reading test JNP server error output failed.", e);
+ } finally {
+ try {
+ rdr.close();
+ } catch (IOException e) {
+ JNP_SERVER_LOG.error("Failed to close the test server error stream.", e);
+ }
+ }
+ }
+ });
+ testServerStdErrReader.start();
+
+ testServerStdOutReader = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ BufferedReader rdr = new BufferedReader(new InputStreamReader(testServerProcess.getInputStream()));
+ try {
+ String line;
+ while((line = rdr.readLine()) != null) {
+ JNP_SERVER_LOG.debug(line);
+ }
+ } catch (IOException e) {
+ JNP_SERVER_LOG.error("Reading test JNP server standard output failed.", e);
+ } finally {
+ try {
+ rdr.close();
+ } catch (IOException e) {
+ JNP_SERVER_LOG.error("Failed to close the test server standard output stream.", e);
+ }
+ }
+ }
+ });
+ testServerStdOutReader.start();
+
+ //give the JNP server some time to start up
+ Thread.sleep(5000);
+ }
+
+ @AfterClass
+ public void stopTestJnpServer() throws Exception {
+ testServerProcess.destroy();
+ testServerStdErrReader.join();
+ testServerStdOutReader.join();
+ }
+
+ @Parameters("jnp.port")
+ public void testRemoteConnectionWorkingFromJava(int jnpPort) throws Exception {
+ Properties env = new Properties();
+ env.put("java.naming.factory.initial", "org.jboss.naming.NamingContextFactory");
+ env.put("java.naming.provider.url", "jnp://localhost:" + jnpPort);
+ InitialContext ctx = new InitialContext(env);
+ Object kachny = ctx.lookup("kachny");
+
+ assert kachny != null;
+ }
+
+ public void testLocalJNDILookupFailsFromScripts() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "context = new javax.naming.InitialContext();\n"
+ + "entityManagerFactory = context.lookup('java:/RHQEntityManagerFactory');\n"
+ + "entityManager = entityManagerFactory.createEntityManager();\n"
+ + "entityManager.find(java.lang.Class.forName('org.rhq.core.domain.resource.Resource'), java.lang.Integer.valueOf('10001'));");
+
+ Assert.fail("The script shouldn't have been able to use the EntityManager.");
+ } catch (ScriptException e) {
+ checkIsDesiredSecurityException(e);
+ }
+ }
+
+ @Parameters("jnp.port")
+ public void testRemoteJNDILookupWorksFromScripts(int jnpPort) throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "env = new java.util.Hashtable();"
+ + "env.put('java.naming.factory.initial', 'org.jboss.naming.NamingContextFactory');"
+ + "env.put('java.naming.provider.url', 'jnp://localhost:" + jnpPort + "');"
+ + "context = new javax.naming.InitialContext(env);\n"
+ + "kachny = context.lookup('kachny');\n"
+ + "assertNotNull(kachny);\n");
+ } catch (ScriptException e) {
+ Assert.fail("The script should have been able to access a remote JNDI server.", e);
+ }
+ }
+
+ private ScriptEngine getEngine(Subject subject) throws ScriptException, IOException {
+ StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new LocalClient(subject));
+ ScriptEngine engine = ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), bindings);
+
+ PermissionCollection perms = new StandardScriptPermissions();
+
+ return new SandboxedScriptEngine(engine, perms);
+ }
+
+ private static void checkIsDesiredSecurityException(ScriptException e) {
+ String message = e.getMessage();
+ String permissionTrace = AllowRhqServerInternalsAccessPermission.class.getName();
+
+ Assert.assertTrue(message.contains(permissionTrace), "The script exception doesn't seem to be caused by the AllowRhqServerInternalsAccessPermission security exception. " + message);
+ }
+}
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/hibernate.properties b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/hibernate.properties
new file mode 100644
index 0000000..1951b84
--- /dev/null
+++ b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/hibernate.properties
@@ -0,0 +1,26 @@
+# FOR SOME STRANGE REASON, THIS FILE NEEDS TO BE HERE FOR THE HIBERNATE TO CORRECTLY
+# INITIALIZE. I DON'T KNOW WHY THE STANDARD default.persistence.properties FILE DOESN'T
+# WORK IN THIS MODULE.
+
+hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
+#hibernate.connection.release_mode=after_statement
+#hibernate.transaction.flush_before_completion=false
+#hibernate.transaction.auto_close_session=false
+#hibernate.query.factory_class=org.hibernate.hql.ast.ASTQueryTranslatorFactory
+#hibernate.hbm2ddl.auto=create-drop
+#hibernate.hbm2ddl.auto=create
+hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
+# Clustered cache with TreeCache
+#hibernate.cache.provider_class=org.jboss.ejb3.entity.TreeCacheProviderHook
+#hibernate.treecache.mbean.object_name=jboss.cache:service=EJB3EntityTreeCache
+#hibernate.dialect=org.hibernate.dialect.HSQLDialect
+hibernate.jndi.java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+hibernate.jndi.java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
+hibernate.bytecode.use_reflection_optimizer=false
+# I don't think this is honored, but EJB3Deployer uses it
+hibernate.bytecode.provider=javassist
+hibernate.jdbc.use_streams_for_binary=true
+hibernate.show_sql=false
+hibernate.format_sql=true
+hibernate.default_batch_fetch_size=16
+hibernate.jdbc.batch_size=20
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/jms-ra.rar b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/jms-ra.rar
new file mode 100644
index 0000000..c4807c6
Binary files /dev/null and b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/jms-ra.rar differ
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/log4j.xml b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/log4j.xml
new file mode 100644
index 0000000..ec09ed7
--- /dev/null
+++ b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/log4j.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Log4j Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: log4j.xml 39945 2006-01-12 02:44:07Z bill $ -->
+
+<!--
+ | For more configuration infromation and examples see the Jakarta Log4j
+ | owebsite: http://jakarta.apache.org/log4j
+ -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
+ <param name="Target" value="System.out"/>
+ <param name="Threshold" value="WARN"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- The default pattern: Date Priority [Category] Messagen -->
+ <!--
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ -->
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} [%c] (%F:%M:%L) -%m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
+ <param name="File" value="target/server-jar-test.log"/>
+ <param name="Threshold" value="WARN"/>
+ <param name="Append" value="false"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- The default pattern: Date Priority [Category] Messagen -->
+ <!--
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ -->
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} [%c] (%F:%M:%L) -%m%n"/>
+ </layout>
+ </appender>
+
+ <category name="Test JNP Server">
+ <priority value="DEBUG"/>
+ </category>
+
+ <!-- Hibernate logs WARNINGS frequent from this class, in test envs. -->
+ <category name="org.hibernate.hql.ast.QueryTranslatorImpl">
+ <priority value="ERROR"/>
+ </category>
+
+ <!-- hides the TIMER SERVICE IS NOT INSTALLED warning - we know embedded EJB3 container doesn't support timers -->
+ <category name="org.jboss.ejb3.timerservice.jboss.JBossTimerServiceFactory">
+ <priority value="ERROR"/>
+ </category>
+
+ <!-- hides the shutdown warnings - for some reason, the container spits out some warnings when shutting down -->
+ <category name="org.jboss.kernel.plugins.dependency.StartStopLifecycleAction">
+ <priority value="ERROR"/>
+ </category>
+
+ <!-- Hibernate SQL logs -->
+ <!--
+ <category name="org.hibernate.SQL">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <root>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/security.policy b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/security.policy
new file mode 100644
index 0000000..8860b47
--- /dev/null
+++ b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/security.policy
@@ -0,0 +1,10 @@
+// We need the SecurityManager installed to enable sandboxing of CLI scripts
+// but we don't define any other security measures on the RHQ server itself.
+//
+// Granting all permissions allows us to run the RHQ server as if no security
+// manager was in place (which is assumed by default by JBoss AS) but be able
+// to use it when we need it for our own purposes.
+
+grant {
+ permission java.security.AllPermission;
+};
diff --git a/modules/integration-tests/jndi-access/pom.xml b/modules/integration-tests/jndi-access/pom.xml
new file mode 100644
index 0000000..6e9c673
--- /dev/null
+++ b/modules/integration-tests/jndi-access/pom.xml
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>rhq-integration-tests</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.3.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>jndi-access-test-parent</artifactId>
+ <packaging>pom</packaging>
+
+ <name>JNDI access tests</name>
+ <description>Tests for the secured JNDI access tests</description>
+
+ <modules>
+ <module>remote-server</module>
+ <module>jndi-access-test</module>
+ </modules>
+</project>
diff --git a/modules/integration-tests/jndi-access/remote-server/pom.xml b/modules/integration-tests/jndi-access/remote-server/pom.xml
new file mode 100644
index 0000000..9046e6f
--- /dev/null
+++ b/modules/integration-tests/jndi-access/remote-server/pom.xml
@@ -0,0 +1,72 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>jndi-access-test-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.3.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>jndi-access-remote-server</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Test JNDI-enabled remote server</name>
+ <description>
+ A testing JNDI-enabled server to test the ability to connect to remote servers without security
+ checks from within the scripts running inside the RHQ server.
+ </description>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jnpserver</artifactId>
+ <version>4.2.2.GA</version>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-common</artifactId>
+ <version>4.2.2.GA</version>
+ </dependency>
+
+ <dependency>
+ <groupId>oswego-concurrent</groupId>
+ <artifactId>concurrent</artifactId>
+ <version>1.3.4-jboss</version>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>package</id>
+ <phase>package</phase>
+ <goals><goal>single</goal></goals>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.rhq.jndi.test.Server</mainClass>
+ </manifest>
+ </archive>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/modules/integration-tests/jndi-access/remote-server/src/main/java/org/rhq/jndi/test/Server.java b/modules/integration-tests/jndi-access/remote-server/src/main/java/org/rhq/jndi/test/Server.java
new file mode 100644
index 0000000..7bfb8e8
--- /dev/null
+++ b/modules/integration-tests/jndi-access/remote-server/src/main/java/org/rhq/jndi/test/Server.java
@@ -0,0 +1,79 @@
+package org.rhq.jndi.test;
+import java.util.Properties;
+
+import javax.naming.CompoundName;
+
+import org.jnp.server.Main;
+import org.jnp.server.NamingBeanImpl;
+
+import org.jboss.logging.Logger;
+
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class Server {
+ private static final Logger LOG = Logger.getLogger(Server.class);
+
+ private static Server INSTANCE;
+
+ private Main jnpServer;
+
+ public static void main(String[] args) throws Exception {
+ LOG.debug("System properties: " + System.getProperties());
+ Server.start();
+ }
+
+ private Server() {
+ jnpServer = new Main("org.rhq.jndi.access.test.server");
+ }
+
+ public static synchronized Server getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new Server();
+ }
+
+ return INSTANCE;
+ }
+
+ public static void start() throws Exception {
+ LOG.debug("Initializing the JNP server");
+
+ NamingBeanImpl nbi = new NamingBeanImpl();
+ getInstance().jnpServer.setNamingInfo(nbi);
+ nbi.start();
+
+ LOG.debug("Binding kachny");
+
+ nbi.getNamingInstance().bind(new CompoundName("kachny", new Properties()), "KACHNY!", String.class.getName());
+
+ LOG.debug("Starting the JNP server");
+
+ getInstance().jnpServer.start();
+ }
+
+ public static void stop() {
+ LOG.debug("Stopping the JNP server");
+ getInstance().jnpServer.stop();
+ }
+}
diff --git a/modules/integration-tests/jndi-access/remote-server/src/main/resources/jndi.properties b/modules/integration-tests/jndi-access/remote-server/src/main/resources/jndi.properties
new file mode 100644
index 0000000..a45f2ce
--- /dev/null
+++ b/modules/integration-tests/jndi-access/remote-server/src/main/resources/jndi.properties
@@ -0,0 +1,2 @@
+java.naming.factory.initial=org.jboss.naming.NamingContextFactory
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
\ No newline at end of file
diff --git a/modules/integration-tests/jndi-access/remote-server/src/main/resources/log4j.properties b/modules/integration-tests/jndi-access/remote-server/src/main/resources/log4j.properties
new file mode 100644
index 0000000..2d41f83
--- /dev/null
+++ b/modules/integration-tests/jndi-access/remote-server/src/main/resources/log4j.properties
@@ -0,0 +1,5 @@
+log4j.rootCategory=TRACE, CONSOLE
+
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c] %m%n
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index 0290729..969b94a 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -62,6 +62,7 @@
<id>integration-tests</id>
<modules>
<module>apache-plugin-test</module>
+ <module>jndi-access</module>
<!--<module>mod_cluster-plugin-test</module>-->
</modules>
</profile>
commit 14141686e5d0c9cac395a13ceb52f2817287ce7b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Dec 22 15:31:49 2011 +0100
Jnp port is now detected from system properties rather than hardcoded.
jnpserver is declared as a provided dep.
diff --git a/modules/enterprise/server/container-lib/pom.xml b/modules/enterprise/server/container-lib/pom.xml
index 9d7d603..0974431 100644
--- a/modules/enterprise/server/container-lib/pom.xml
+++ b/modules/enterprise/server/container-lib/pom.xml
@@ -43,6 +43,7 @@
<groupId>jboss</groupId>
<artifactId>jnpserver</artifactId>
<version>4.2.2.GA</version>
+ <scope>provided</scope>
</dependency>
</dependencies>
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java
index 1a9562a..e529347 100644
--- a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java
@@ -77,7 +77,6 @@ public class AccessCheckingInitialContextFactoryBuilder implements InitialContex
private static final String[] CHECKED_SCHEMES = { "java" };
private static final Set<InetAddress> SERVER_BIND_IPS;
-
static {
SERVER_BIND_IPS = new HashSet<InetAddress>();
@@ -98,10 +97,11 @@ public class AccessCheckingInitialContextFactoryBuilder implements InitialContex
LOG.error("Could not obtain the list of local IPs", e);
} catch (UnknownHostException e) {
LOG.error("Failed to get the binding address of the RHQ server.", e);
- }
-
+ }
}
+ private static final int JNP_PORT = Integer.parseInt(System.getProperty("rhq.server.startup.namingservice.port", "2099"));
+
/**
* This is the default initial context factory that is returned when no other is
* configured using the environment variables.
@@ -159,10 +159,7 @@ public class AccessCheckingInitialContextFactoryBuilder implements InitialContex
//check if we are accessing the RHQ server through some remoting
//interface.
- //I just can't find where to read the magic number 1099 from.
- //it is defined in the jboss config files, but in the code
- //it seems hardcoded - see JDBCLoginModule.
- if (uri.getPort() == 1099 && SERVER_BIND_IPS.contains(providerHost)) {
+ if (uri.getPort() == JNP_PORT && SERVER_BIND_IPS.contains(providerHost)) {
return new AccessCheckingInitialContextFactoryDecorator(factory, CHECKED_SCHEMES);
} else {
return new URLPreferringInitialContextFactoryDecorator(factory);
commit 846c73c606a445dbe9f4627d28eafc154421eec6
Merge: f2803b9 572db8c
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Dec 19 19:57:58 2011 +0100
Merge branch 'master' into lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs
commit f2803b9046bfe26c9cbc80ec15bd458ac4f46db5
Merge: 8f9acfd 35fcafb
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Dec 19 19:56:15 2011 +0100
Merge branch 'master' into lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs
commit 8f9acfd64f725fb1ce4d1fafb3e44fde57de4b99
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Dec 19 19:55:08 2011 +0100
Revamped the script security to apply the checks at the JNDI lookup level
to support restricting access to EntityManager or a datasource.
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 6932b60..4dfd109 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -93,6 +93,13 @@
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-container-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>hibernate</groupId>
<artifactId>hibernate3</artifactId>
<!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
index 9c9d1bb..dc1fc83 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
@@ -22,9 +22,6 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.SerializablePermission;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.security.PermissionCollection;
import java.util.Collections;
@@ -41,9 +38,9 @@ import org.rhq.bindings.StandardScriptPermissions;
import org.rhq.bindings.util.PackageFinder;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.client.LocalClient;
-import org.rhq.enterprise.server.security.AllowEjbAccessPermission;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.jndi.AllowRhqServerInternalsAccessPermission;
/**
*
@@ -78,7 +75,7 @@ public class EjbAccessTest extends AbstractEJB3Test {
Assert.fail("The script shouldn't have been able to call local SLSB method.");
} catch (ScriptException e) {
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ checkIsDesiredSecurityException(e);
}
}
@@ -95,66 +92,34 @@ public class EjbAccessTest extends AbstractEJB3Test {
Assert.fail("The script shouldn't have been able to call remote SLSB method directly.");
} catch (ScriptException e) {
- //TODO java.io.IOException: access denied (java.io.SerializablePermission enableSubclassImplementation)
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ checkIsDesiredSecurityException(e);
}
}
- public void testScriptCantUseSessionManager() throws ScriptException, IOException {
- Subject overlord = LookupUtil.getSubjectManager().getOverlord();
-
- ScriptEngine engine = getEngine(overlord);
-
- try {
- engine.eval("org.rhq.enterprise.server.auth.SessionManager.getInstance();");
-
- Assert.fail("The script shouldn't have been able to get instance of SessionManager.");
- } catch (ScriptException e) {
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
- }
- }
-
- @SuppressWarnings("unused")
public void testScriptCantUseSessionManagerMethods() throws Exception {
- //The code below cannot work in Rhino because as of now, Rhino modifies
- //the return value of Class.getDeclaredField() to be null when there
- //is a security manager installed.
- //This has been filed as a bug at Oracle (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7119959)
-
- if (true) {
- return;
- }
-
Subject overlord = LookupUtil.getSubjectManager().getOverlord();
final ScriptEngine engine = getEngine(overlord);
class G {
- private String obtainSessionManagerUsingReflection = ""
- + "var sessionManagerClass = java.lang.Class.forName(\"org.rhq.enterprise.server.auth.SessionManager\");\n"
- + "println(sessionManagerClass);\n"
- + "var managerField = sessionManagerClass.getDeclaredField(\"_manager\");\n"
- + "println(managerField);\n"
- + "managerField.setAccessible(true);\n"
- + "var manager = managerField.get(null);\n"
- + "println(manager);\n"
- + "manager.";
+ private String sessionManager = ""
+ + "org.rhq.enterprise.server.auth.SessionManager.getInstance().";
public void testInvoke(String methodCall) throws ScriptException {
- String code = obtainSessionManagerUsingReflection + methodCall;
+ String code = sessionManager + methodCall;
try {
engine.eval(code);
- Assert.fail("The script shouldn't have been able to a method on a SessionManager.");
+ Assert.fail("The script shouldn't have been able to call a method on a SessionManager: " + methodCall);
} catch (ScriptException e) {
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ checkIsDesiredSecurityException(e);
}
}
};
G manager = new G();
- manager.testInvoke("getLastAccess(0);");
+ manager.testInvoke("getlastAccess(0);");
manager.testInvoke("getOverlord()");
manager.testInvoke("getSubject(2);");
manager.testInvoke("invalidate(0);");
@@ -163,6 +128,57 @@ public class EjbAccessTest extends AbstractEJB3Test {
manager.testInvoke("put(new org.rhq.core.domain.auth.Subject(), 0);");
}
+ public void testScriptCantObtainRawJDBCConnectionsWithoutCredentials() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "context = new javax.naming.InitialContext();\n"
+ + "datasource = context.lookup('java:/RHQDS');\n"
+ + "con = datasource.getConnection();");
+
+ Assert.fail("The script shouldn't have been able to obtain the datasource from the JNDI.");
+ } catch (ScriptException e) {
+ checkIsDesiredSecurityException(e);
+ }
+ }
+
+ public void testScriptCantUseEntityManager() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "context = new javax.naming.InitialContext();\n"
+ + "entityManagerFactory = context.lookup('java:/RHQEntityManagerFactory');\n"
+ + "entityManager = entityManagerFactory.createEntityManager();\n"
+ + "entityManager.find(java.lang.Class.forName('org.rhq.core.domain.resource.Resource'), java.lang.Integer.valueOf('10001'));");
+
+ Assert.fail("The script shouldn't have been able to use the EntityManager.");
+ } catch (ScriptException e) {
+ checkIsDesiredSecurityException(e);
+ }
+
+ //try harder with manually specifying the initial context factory
+ try {
+ engine.eval(""
+ + "env = new java.util.Hashtable();"
+ + "env.put('java.naming.factory.initial', 'org.jnp.interfaces.LocalOnlyContextFactory');"
+ + "env.put('java.naming.factory.url.pkgs', 'org.jboss.naming:org.jnp.interfaces');"
+ + "context = new javax.naming.InitialContext(env);\n"
+ + "entityManagerFactory = context.lookup('java:/RHQEntityManagerFactory');\n"
+ + "entityManager = entityManagerFactory.createEntityManager();\n"
+ + "entityManager.find(java.lang.Class.forName('org.rhq.core.domain.resource.Resource'), java.lang.Integer.valueOf('10001'));");
+
+ Assert.fail("The script shouldn't have been able to use the EntityManager even using custom initial context factory.");
+ } catch (ScriptException e) {
+ checkIsDesiredSecurityException(e);
+ }
+ }
+
private ScriptEngine getEngine(Subject subject) throws ScriptException, IOException {
StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new LocalClient(subject));
ScriptEngine engine = ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), bindings);
@@ -172,4 +188,11 @@ public class EjbAccessTest extends AbstractEJB3Test {
return new SandboxedScriptEngine(engine, perms);
}
+
+ private static void checkIsDesiredSecurityException(ScriptException e) {
+ String message = e.getMessage();
+ String permissionTrace = AllowRhqServerInternalsAccessPermission.class.getName();
+
+ Assert.assertTrue(message.contains(permissionTrace), "The script exception doesn't seem to be caused by the AllowRhqServerInternalsAccessPermission security exception. " + message);
+ }
}
diff --git a/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml b/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml
deleted file mode 100644
index caa7513..0000000
--- a/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
- version="3.0">
-
- <description>RHQ</description>
- <display-name>RHQ</display-name>
-
- <assembly-descriptor>
-
- <!-- This interceptor checks that the alert CLI scripts don't try to circumvent our access objects by accessing the local SLSB beans directly. -->
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.security.AllowEjbAccessInterceptor</interceptor-class>
- </interceptor-binding>
-
- <!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.authz.RequiredPermissionsInterceptor</interceptor-class>
- </interceptor-binding>
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.common.TransactionInterruptInterceptor</interceptor-class>
- </interceptor-binding>
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.common.PerformanceMonitorInterceptor</interceptor-class>
- </interceptor-binding>
-
- </assembly-descriptor>
-
-</ejb-jar>
diff --git a/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml b/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml
deleted file mode 100644
index b7c5c66..0000000
--- a/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml
+++ /dev/null
@@ -1,168 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<jboss xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
- version="3.0">
-
- <enterprise-beans>
-
- <!--
- The AlertConditionLogManagerBean, AlertConditionManagerBean, AlertDampeningManagerBean,
- AlertDefinitionManagerBean, AlertManagerBean, AuthorizationManagerBean, CachedConditionManagerBean, and
- SubjectManager SLSB's are all invoked, either directly or indirectly, by the AlertConditionConsumerBean MDB.
- Since MDB invocations are always done in new threads, using the default SLSB pool impl (ThreadlocalPool) would
- cause a new instance of these SLSB's to be created every time they were invoked by AlertConditionConsumerBean.
- This would be bad if only because existing instances would
- not be reused, but it is really bad because the instances would also never get destroyed, causing heap space to
- gradually leak until the Server eventually ran out of memory. Hence, we must use a StrictMaxPool, which
- will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool. Because lots of alert
- definitions could result in many concurrent calls to AlertConditionConsumerBean, and because most of these
- SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's), we set the max pool size to 100 to
- minimize the chances of AlertConditionConsumerBean invocations, which are the most critical, from having to
- block and potentially getting backed up in the queue. We set the pool timeout extremely high to essentially
- prevent queued callers from timing out. Note, MDB's are configured in ejb3-interceptors-aop.xml to use a strict
- max pool with a max of 15 and a timeout of 10000, so AlertConditionConsumerBean might become a bottleneck for
- systems with a lot of alerts defined. (ips, 05/10/11)
-
- For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
- -->
-
- <session>
- <ejb-name>AlertConditionLogManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertConditionManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertDampeningManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertDefinitionManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AuthorizationManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>CachedConditionManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>SubjectManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
-
- <!--
- The CacheConsistencyManagerBean, CloudManagerBean, ServerManagerBean, StatusManagerBean, and SystemManagerBean
- SLSB's are all invoked, either directly or indirectly, by EJB timers. Since EJB timer invocations are always
- done in new threads, using the default SLSB pool impl (ThreadlocalPool) would cause a new instance of this
- SLSB to be created every time it was invoked by an EJB timer. This would be bad if only because an existing
- instance would not be reused, but it is really bad because the instance would also never get destroyed, causing
- heap space to gradually leak until the Server eventually ran out of memory. Hence, we must use a
- StrictMaxPool, which will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool.
- The timer invocations will only require one or two instances at any given time, but because most of these
- SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's, we set the max pool size to 30, to
- minimize the chances of EJB timer invocations, which are the most critical, from having to block and
- potentially getting backed up in the queue. We set the pool timeout extremely high to essentially prevent
- queued callers from timing out. (ips, 05/10/11)
-
- For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
- -->
-
- <session>
- <ejb-name>CacheConsistencyManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>CloudManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>ServerManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>StatusManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>SystemManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- </enterprise-beans>
-
-</jboss>
diff --git a/modules/enterprise/server/container-lib/pom.xml b/modules/enterprise/server/container-lib/pom.xml
index b832b06..9d7d603 100644
--- a/modules/enterprise/server/container-lib/pom.xml
+++ b/modules/enterprise/server/container-lib/pom.xml
@@ -39,6 +39,11 @@
<scope>provided</scope> <!-- by JBossAS -->
</dependency>
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jnpserver</artifactId>
+ <version>4.2.2.GA</version>
+ </dependency>
</dependencies>
<profiles>
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java
new file mode 100644
index 0000000..df42afe
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java
@@ -0,0 +1,237 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi;
+
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+
+/**
+ * This is the "meat" of the RHQ's secured JNDI access. This {@link Context} decorator
+ * applied security checks in each method (lookups, (un)bindings, etc).
+ * <p>
+ * The security check consists of checking if the current callstack has the {@link AllowRhqServerInternalsAccessPermission}.
+ * <p>
+ * This decorator applies the security check on any JNDI name without a scheme and
+ * on any name that has a scheme listed in the {@link #checkedSchemes} list supplied
+ * in the constructor.
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingContextDecorator implements Context {
+
+ private static final AllowRhqServerInternalsAccessPermission PERM = new AllowRhqServerInternalsAccessPermission();
+ private Context original;
+ private List<String> checkedSchemes;
+
+ public AccessCheckingContextDecorator(Context original, String... checkedSchemes) {
+ this.original = original;
+ this.checkedSchemes = Arrays.asList(checkedSchemes);
+ }
+
+ private static void check() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) sm.checkPermission(PERM);
+ }
+
+ private void checkScheme(String scheme) {
+ if (scheme == null || checkedSchemes.contains(scheme)) {
+ check();
+ }
+ }
+
+ private void check(String name) {
+ checkScheme(getURLScheme(name));
+ }
+
+ private void check(Name name) {
+ if (name.size() == 0) {
+ check();
+ } else {
+ String first = name.get(0);
+ checkScheme(getURLScheme(first));
+ }
+ }
+
+ public Object lookup(Name name) throws NamingException {
+ check(name);
+ return original.lookup(name);
+ }
+
+ public Object lookup(String name) throws NamingException {
+ check(name);
+ return original.lookup(name);
+ }
+
+ public void bind(Name name, Object obj) throws NamingException {
+ check(name);
+ original.bind(name, obj);
+ }
+
+ public void bind(String name, Object obj) throws NamingException {
+ check(name);
+ original.bind(name, obj);
+ }
+
+ public void rebind(Name name, Object obj) throws NamingException {
+ check(name);
+ original.rebind(name, obj);
+ }
+
+ public void rebind(String name, Object obj) throws NamingException {
+ check(name);
+ original.rebind(name, obj);
+ }
+
+ public void unbind(Name name) throws NamingException {
+ check(name);
+ original.unbind(name);
+ }
+
+ public void unbind(String name) throws NamingException {
+ check(name);
+ original.unbind(name);
+ }
+
+ public void rename(Name oldName, Name newName) throws NamingException {
+ check(oldName);
+ check(newName);
+ original.rename(oldName, newName);
+ }
+
+ public void rename(String oldName, String newName) throws NamingException {
+ check(oldName);
+ check(newName);
+ original.rename(oldName, newName);
+ }
+
+ public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
+ check(name);
+ return original.list(name);
+ }
+
+ public NamingEnumeration<NameClassPair> list(String name) throws NamingException {
+ check(name);
+ return original.list(name);
+ }
+
+ public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
+ check(name);
+ return original.listBindings(name);
+ }
+
+ public NamingEnumeration<Binding> listBindings(String name) throws NamingException {
+ check(name);
+ return original.listBindings(name);
+ }
+
+ public void destroySubcontext(Name name) throws NamingException {
+ check(name);
+ original.destroySubcontext(name);
+ }
+
+ public void destroySubcontext(String name) throws NamingException {
+ check(name);
+ original.destroySubcontext(name);
+ }
+
+ public Context createSubcontext(Name name) throws NamingException {
+ check(name);
+ return original.createSubcontext(name);
+ }
+
+ public Context createSubcontext(String name) throws NamingException {
+ check(name);
+ return original.createSubcontext(name);
+ }
+
+ public Object lookupLink(Name name) throws NamingException {
+ check(name);
+ return original.lookupLink(name);
+ }
+
+ public Object lookupLink(String name) throws NamingException {
+ check(name);
+ return original.lookupLink(name);
+ }
+
+ public NameParser getNameParser(Name name) throws NamingException {
+ check(name);
+ return original.getNameParser(name);
+ }
+
+ public NameParser getNameParser(String name) throws NamingException {
+ check(name);
+ return original.getNameParser(name);
+ }
+
+ public Name composeName(Name name, Name prefix) throws NamingException {
+ check(name);
+ return original.composeName(name, prefix);
+ }
+
+ public String composeName(String name, String prefix) throws NamingException {
+ check(name);
+ return original.composeName(name, prefix);
+ }
+
+ public Object addToEnvironment(String propName, Object propVal) throws NamingException {
+ check();
+ return original.addToEnvironment(propName, propVal);
+ }
+
+ public Object removeFromEnvironment(String propName) throws NamingException {
+ check();
+ return original.removeFromEnvironment(propName);
+ }
+
+ public Hashtable<?, ?> getEnvironment() throws NamingException {
+ check();
+ return original.getEnvironment();
+ }
+
+ public void close() throws NamingException {
+ check();
+ original.close();
+ }
+
+ public String getNameInNamespace() throws NamingException {
+ check();
+ return original.getNameInNamespace();
+ }
+
+ //copied from InitialContext
+ private static String getURLScheme(String str) {
+ int colon_posn = str.indexOf(':');
+ int slash_posn = str.indexOf('/');
+
+ if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
+ return str.substring(0, colon_posn);
+ return null;
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java
new file mode 100644
index 0000000..1a9562a
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java
@@ -0,0 +1,180 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.InitialContextFactoryBuilder;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jnp.interfaces.NamingContextFactory;
+
+/**
+ * This initial context factory builder is installed early on during the RHQ server startup
+ * and is later on used for obtaining the {@link Context}s for all JNDI lookups in the
+ * RHQ server.
+ * <p>
+ * We use a custom initial context factory builder to prevent the potential malicious 3rd party
+ * code (like CLI alert scripts) from supplying custom environment variables to {@link InitialContext}
+ * that would modify the JNDI lookup to skip our security access checks.
+ * <p>
+ * By using a builder we effectively take control of the initial context creation process
+ * and are free to ignore whatever the script is trying to supply.
+ * <p>
+ * This builder makes sure to install the RHQ server's security access checks to whatever
+ * initial context that is configured by the standard environment variables
+ * ({@link Context#INITIAL_CONTEXT_FACTORY}, etc.)
+ * <p>
+ * This class is heavily inspired by the implementation of a similar builder in JBoss AS 7.
+ *
+ * @see AllowRhqServerInternalsAccessPermission
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingInitialContextFactoryBuilder implements InitialContextFactoryBuilder {
+ private static final Log LOG = LogFactory.getLog(AccessCheckingInitialContextFactoryBuilder.class);
+
+ /**
+ * The list of JNDI name schemes that should be checked for security permissions
+ * (in addition to the names with no scheme).
+ *
+ * @see AccessCheckingContextDecorator
+ */
+ private static final String[] CHECKED_SCHEMES = { "java" };
+
+ private static final Set<InetAddress> SERVER_BIND_IPS;
+
+ static {
+ SERVER_BIND_IPS = new HashSet<InetAddress>();
+
+ try {
+ String bindingAddressString = System.getProperty("jboss.bind.address");
+ InetAddress bindingAddress = InetAddress.getByName(bindingAddressString);
+
+ if (bindingAddress.isAnyLocalAddress()) {
+ Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+ while(ifaces.hasMoreElements()) {
+ NetworkInterface iface = ifaces.nextElement();
+ SERVER_BIND_IPS.addAll(Collections.list(iface.getInetAddresses()));
+ }
+ } else {
+ SERVER_BIND_IPS.add(bindingAddress);
+ }
+ } catch (SocketException e) {
+ LOG.error("Could not obtain the list of local IPs", e);
+ } catch (UnknownHostException e) {
+ LOG.error("Failed to get the binding address of the RHQ server.", e);
+ }
+
+ }
+
+ /**
+ * This is the default initial context factory that is returned when no other is
+ * configured using the environment variables.
+ * <p>
+ * It uses {@link NamingContextFactory} as the underlying mechanism - the same
+ * as the default configuration in JBoss 4.
+ */
+ private static final InitialContextFactory DEFAULT_FACTORY = new InitialContextFactory() {
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+ return createSecureWrapper(new NamingContextFactory(), environment).getInitialContext(environment);
+ }
+ };
+
+ /**
+ * Create a InitialContext factory. If the environment does not override the factory class it will use the
+ * default context factory.
+ *
+ * @param environment The environment
+ * @return An initial context factory
+ * @throws NamingException If an error occurs loading the factory class.
+ */
+ public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment) throws NamingException {
+ final String factoryClassName = (String) environment.get(Context.INITIAL_CONTEXT_FACTORY);
+ if (factoryClassName == null) {
+ return DEFAULT_FACTORY;
+ }
+ final ClassLoader classLoader = getContextClassLoader();
+ try {
+ final Class<?> factoryClass = Class.forName(factoryClassName, true, classLoader);
+ InitialContextFactory configuredFactory = (InitialContextFactory) factoryClass.newInstance();
+ return createSecureWrapper(configuredFactory, environment);
+ } catch (Exception e) {
+ throw new NamingException("Failed instantiate InitialContextFactory " + factoryClassName
+ + " from classloader " + classLoader);
+ }
+ }
+
+ private ClassLoader getContextClassLoader() {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+
+ private static InitialContextFactory createSecureWrapper(InitialContextFactory factory, Hashtable<?, ?> environment) {
+ String providerUrl = (String) environment.get(Context.PROVIDER_URL);
+
+ if (providerUrl == null) {
+ return new AccessCheckingInitialContextFactoryDecorator(factory, CHECKED_SCHEMES);
+ } else {
+ try {
+ URI uri = new URI(providerUrl);
+ InetAddress providerHost = InetAddress.getByName(uri.getHost());
+
+ //check if we are accessing the RHQ server through some remoting
+ //interface.
+ //I just can't find where to read the magic number 1099 from.
+ //it is defined in the jboss config files, but in the code
+ //it seems hardcoded - see JDBCLoginModule.
+ if (uri.getPort() == 1099 && SERVER_BIND_IPS.contains(providerHost)) {
+ return new AccessCheckingInitialContextFactoryDecorator(factory, CHECKED_SCHEMES);
+ } else {
+ return new URLPreferringInitialContextFactoryDecorator(factory);
+ }
+ } catch (URISyntaxException e) {
+ return new AccessCheckingInitialContextFactoryDecorator(factory, CHECKED_SCHEMES);
+ } catch (UnknownHostException e) {
+ //let the factory deal with the unknown host...
+ //this most probably shouldn't be secured because localhost addresses
+ //should be resolvable.
+ return new URLPreferringInitialContextFactoryDecorator(factory);
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java
new file mode 100644
index 0000000..b23935f
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java
@@ -0,0 +1,60 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+/**
+ * A decorator of an {@link InitialContextFactory} that adds the security checking
+ * machinery to the returned initial contexts.
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingInitialContextFactoryDecorator extends URLPreferringInitialContextFactoryDecorator {
+
+ private final String[] checkedSchemes;
+
+ /**
+ * @param factory the factory to wrap
+ * @param checkedSchemes the list of JNDI name schemes to check for permissions
+ * @see AccessCheckingContextDecorator
+ */
+ public AccessCheckingInitialContextFactoryDecorator(InitialContextFactory factory, String... checkedSchemes) {
+ super(factory);
+ this.checkedSchemes = checkedSchemes;
+ }
+
+ /**
+ * @param environment the environment variables for the return {@link Context} to use
+ *
+ * @return the initial context returned by the decorated factory wrapped in
+ * {@link URLPreferringContext} and {@link AccessCheckingContextDecorator} in that
+ * order.
+ */
+ @Override
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+ return new AccessCheckingContextDecorator(super.getInitialContext(environment), checkedSchemes);
+ }
+
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java
new file mode 100644
index 0000000..aa807d6
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java
@@ -0,0 +1,36 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi;
+
+import java.security.BasicPermission;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AllowRhqServerInternalsAccessPermission extends BasicPermission {
+
+ private static final long serialVersionUID = 1L;
+
+ public AllowRhqServerInternalsAccessPermission() {
+ super("org.rhq.allow.server.internals.access");
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
new file mode 100644
index 0000000..b291c3e
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
@@ -0,0 +1,104 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.NamingManager;
+
+/**
+ * This is a modification of the default {@link InitialContext} class that
+ * ignores the initial context factory builder when constructing the default
+ * context to use in lookups etc.
+ * <p>
+ * This is important because RHQ server has its own initial context factory
+ * builder that creates factories that in turn create contexts. If the default
+ * {@link InitialContext} implementation was used, we'd end up with a stack overflow
+ * error caused by the callchain loop when the {@link InitialContext} would ask
+ * the builder for a factory that would create another context that would ask the
+ * builder for the factory, etc. ad infinitum.
+ * <p>
+ * This class prevents that by acting exactly like the InitialContext would if
+ * the initial context factory builder wasn't installed. This enables the callers
+ * to still use the standard InitialContext when doing lookups etc. This standard
+ * initial context will ask our initial context factory builder which will then
+ * in chain create this {@link URLPreferringContext} that behaves like the original
+ * InitialContext would if the builder wasn't there.
+ *
+ * @author Lukas Krejci
+ */
+public class URLPreferringContext extends InitialContext {
+
+ public URLPreferringContext(InitialContextFactory defaultContextFactory) throws NamingException {
+ super(true);
+ this.defaultInitCtx = defaultContextFactory.getInitialContext(null);
+ this.gotDefault = true;
+ init(null);
+ }
+
+ public URLPreferringContext(Hashtable<?, ?> environment, InitialContextFactory defaultContextFactory) throws NamingException {
+ super(true);
+ this.defaultInitCtx = defaultContextFactory.getInitialContext(environment);
+ this.gotDefault = true;
+ init(environment);
+ }
+
+ @Override
+ protected Context getURLOrDefaultInitCtx(Name name) throws NamingException {
+ if (name.size() > 0) {
+ String first = name.get(0);
+ String scheme = getURLScheme(first);
+ if (scheme != null) {
+ Context ctx = NamingManager.getURLContext(scheme, myProps);
+ if (ctx != null) {
+ return ctx;
+ }
+ }
+ }
+ return getDefaultInitCtx();
+ }
+
+ @Override
+ protected Context getURLOrDefaultInitCtx(String name) throws NamingException {
+ String scheme = getURLScheme(name);
+ if (scheme != null) {
+ Context ctx = NamingManager.getURLContext(scheme, myProps);
+ if (ctx != null) {
+ return ctx;
+ }
+ }
+ return getDefaultInitCtx();
+ }
+
+ //copied from InitialContext
+ private static String getURLScheme(String str) {
+ int colon_posn = str.indexOf(':');
+ int slash_posn = str.indexOf('/');
+
+ if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
+ return str.substring(0, colon_posn);
+ return null;
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
new file mode 100644
index 0000000..6c311c7
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
@@ -0,0 +1,54 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+/**
+ * A decorator of an {@link InitialContextFactory} that returns an {@link URLPreferringContext}
+ * backed by the wrapped initial context factory.
+ * <p>
+ * This is to support contexts that don't need to be secured, yet we need to make sure to
+ * break the call-chain loop caused by the {@link InitialContext} asking the RHQ's {@link AccessCheckingInitialContextFactoryBuilder} for
+ * default contexts.
+ *
+ * @author Lukas Krejci
+ */
+public class URLPreferringInitialContextFactoryDecorator implements InitialContextFactory {
+
+ private final InitialContextFactory factory;
+
+ public URLPreferringInitialContextFactoryDecorator(InitialContextFactory factory) {
+ this.factory = factory;
+ }
+
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+ return new URLPreferringContext(environment, getFactory());
+ }
+
+ protected InitialContextFactory getFactory() {
+ return factory;
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java
new file mode 100644
index 0000000..d938c50
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java
@@ -0,0 +1,45 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi.mbean;
+
+import javax.naming.spi.NamingManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.jndi.AccessCheckingInitialContextFactoryBuilder;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingInitialContextFactoryBuilderInstaller implements AccessCheckingInitialContextFactoryBuilderInstallerMBean {
+ private static final Log LOG = LogFactory.getLog(AccessCheckingInitialContextFactoryBuilder.class);
+
+ public void start() throws Exception {
+ LOG.info("Installing RHQ's access permission checking initial context factory builder");
+
+ NamingManager.setInitialContextFactoryBuilder(new AccessCheckingInitialContextFactoryBuilder());
+ }
+
+ public void stop() throws Exception {
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java
new file mode 100644
index 0000000..87d19ab
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java
@@ -0,0 +1,32 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.jndi.mbean;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public interface AccessCheckingInitialContextFactoryBuilderInstallerMBean {
+
+ void start() throws Exception;
+
+ void stop() throws Exception;
+}
diff --git a/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml
index 859b552..f231f15 100644
--- a/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml
+++ b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml
@@ -225,6 +225,13 @@
<!-- JNDI -->
<!-- ==================================================================== -->
+ <!-- This installs a custom initial context factory builder into the JVM
+ that will ensure that all the default InitialContexts are going to check
+ for the permission to access the RHQ internals. -->
+ <mbean code="org.rhq.jndi.mbean.AccessCheckingInitialContextFactoryBuilderInstaller"
+ name="org.rhq:service=AccessCheckingInitialContextFactoryBuilderInstaller">
+ </mbean>
+
<!-- A simple mbean wrapper around the jndi Naming object. This
only handles an in memory instance. The NamingService uses this
as the JNDI store and exposes it remotely.
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index db286a1..a876809 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -78,6 +78,13 @@
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-container-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
<dependency>
<groupId>com.googlecode.java-diff-utils</groupId>
<artifactId>diffutils</artifactId>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
index b4a19b7..ecf2f6f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
@@ -25,8 +25,8 @@ import java.util.Map;
import java.util.Random;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.security.AllowEjbAccessPermission;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.jndi.AllowRhqServerInternalsAccessPermission;
/**
* This is the JON Server's own session ID generator. It is outside any container-provided session mechanism. Its sole
@@ -45,7 +45,7 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
public final class SessionManager {
- private static final AllowEjbAccessPermission ACCESS_PERMISSION = new AllowEjbAccessPermission();
+ private static final AllowRhqServerInternalsAccessPermission ACCESS_PERMISSION = new AllowRhqServerInternalsAccessPermission();
/**
* Our source for random session IDs.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java
deleted file mode 100644
index 350453fb..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.enterprise.server.security;
-
-import java.security.Permission;
-
-import javax.interceptor.AroundInvoke;
-import javax.interceptor.InvocationContext;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class AllowEjbAccessInterceptor {
-
- private static final Permission PERM = new AllowEjbAccessPermission();
-
- @AroundInvoke
- public Object intercept(InvocationContext invocationContext) throws Exception {
- //check that the caller has permissions to access the EJBs.
- //normal code does, only alert CLI scripts that try to circumvent our
- //manager proxies don't.
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) sm.checkPermission(PERM);
-
- return invocationContext.proceed();
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java
deleted file mode 100644
index 67f418d..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.enterprise.server.security;
-
-import java.security.BasicPermission;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class AllowEjbAccessPermission extends BasicPermission {
-
- private static final long serialVersionUID = 1L;
-
- public AllowEjbAccessPermission() {
- super("rhq.allow.ejb.access");
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
index caa7513..8222948 100644
--- a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
+++ b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
@@ -9,12 +9,6 @@
<assembly-descriptor>
- <!-- This interceptor checks that the alert CLI scripts don't try to circumvent our access objects by accessing the local SLSB beans directly. -->
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.security.AllowEjbAccessInterceptor</interceptor-class>
- </interceptor-binding>
-
<!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
<interceptor-binding>
<ejb-name>*</ejb-name>
diff --git a/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml b/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
index 05edefa..85e2fb3 100644
--- a/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
+++ b/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
@@ -4,6 +4,14 @@
xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
xmlns="urn:jboss:bean-deployer:2.0">
+ <!-- This installs a custom initial context factory builder into the JVM
+ that will ensure that all the default InitialContexts are going to check
+ for the permission to access the RHQ internals. -->
+ <bean class="org.rhq.jndi.mbean.AccessCheckingInitialContextFactoryBuilderInstaller"
+ name="AccessCheckingInitialContextFactoryBuilderInstaller">
+ </bean>
+
+
<bean name="Naming" class="org.jnp.server.SingletonNamingServer"/>
<bean name="InitialContextProperties" class="java.util.Hashtable">
@@ -20,7 +28,7 @@
</entry>
</map>
</parameter>
- </constructor>
+ </constructor>
</bean>
<bean name="java:comp/Initializer" class="org.jboss.ejb3.embedded.JavaCompInitializer">
commit ca4757776c008f12a053c816d7b9cf8c6a310596
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Sat Dec 10 01:19:40 2011 +0100
Adding EjbAccessTest to make sure the CLI scripts can access the business
layer only through the designated interface. No direct local or remote
EJB access is possible.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardScriptPermissions.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardScriptPermissions.java
index 894c953..5822d44 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardScriptPermissions.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardScriptPermissions.java
@@ -20,6 +20,7 @@
package org.rhq.bindings;
import java.io.FilePermission;
+import java.io.SerializablePermission;
import java.lang.reflect.ReflectPermission;
import java.net.SocketPermission;
import java.security.Permission;
@@ -83,6 +84,11 @@ public class StandardScriptPermissions extends PermissionCollection {
add(new PropertyPermission("*", "read"));
add(new ReflectPermission("suppressAccessChecks"));
+
+ //these 2 are required for server-side scripts to be able to
+ //invoke remote EJBs.
+ add(new SerializablePermission("enableSubclassImplementation"));
+ add(new RuntimePermission("reflectionFactoryAccess"));
}
public void add(Permission permission) {
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index b125b3b..6932b60 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -17,9 +17,28 @@
<properties>
<persistence-api.version>1.0</persistence-api.version>
+ <rhq.server.datasource>java:/RHQDS</rhq.server.datasource>
+ <rhq.server.ds-mapping>PostgreSQL</rhq.server.ds-mapping>
+
+ <!-- dependency versions -->
+ <jboss-embeddable-ejb3.version>1.0.0.Alpha9</jboss-embeddable-ejb3.version>
+
+ <clean.db>true</clean.db>
</properties>
<dependencies>
+
+ <!-- Note, the test deps are intentionally placed above the other scoped deps because of classpath
+ reasons. Maven orders the [test] classpath in the order listed in the pom. We specifically
+ need the embeddable-ejb3 jar above the standard ejb3 jars because we need the embeddble packages
+ loaded when testing. -->
+ <dependency>
+ <groupId>jboss.jboss-embeddable-ejb3</groupId>
+ <artifactId>jboss-ejb3-all</artifactId>
+ <version>${jboss-embeddable-ejb3.version}</version>
+ <scope>test</scope>
+ </dependency>
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-script-bindings</artifactId>
@@ -48,21 +67,319 @@
<!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
<scope>provided</scope> <!-- by JBossAS -->
</dependency>
-
+
+ <!-- Test deps - this insane list of deps is needed to get the embedded JBoss server with RHQ server deployed running -->
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>test-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>hibernate</groupId>
+ <artifactId>hibernate3</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>hibernate-entitymanager</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-javamail_1.3.1_spec</artifactId>
+ <!-- The Sun javamail jar isn't available from a public repo due to licensing issues,
+ so use the Geronimo one instead. -->
+ <version>1.3</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.0</version>
+ <scope>test</scope>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.opensymphony.quartz</groupId>
+ <artifactId>quartz</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opensymphony.quartz</groupId>
+ <artifactId>quartz-oracle</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-annotations-ejb3</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-cache</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-common</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <!-- includes the org.jboss.ejb3.StrictMaxPool class, which is needed by the PoolClass annotation used on some
+ of our SLSB's -->
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-ejb3</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-j2ee</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-jmx</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-system</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jbosssx</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jbpm</artifactId>
+ <version>3.1.1</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>antlr</groupId>
+ <artifactId>antlr</artifactId>
+ <version>2.7.7</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>trove</groupId>
+ <artifactId>trove</artifactId>
+ <version>1.0.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.8.1</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sf.opencsv</groupId>
+ <artifactId>opencsv</artifactId>
+ <version>1.8</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-jxpath</groupId>
+ <artifactId>commons-jxpath</artifactId>
+ <version>1.3</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- for the transaction interrupt EJB3 interceptor -->
+ <dependency>
+ <groupId>org.jboss.transaction</groupId>
+ <artifactId>jboss-jta</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>tomcat</groupId>
+ <artifactId>catalina</artifactId>
+ <version>5.5.20</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>tomcat</groupId>
+ <artifactId>tomcat-jk</artifactId>
+ <version>4.1.31</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- Needed by com.jboss.jbossnetwork.apl.actions.xml.XPathProcessor; TODO: Remove once APL has been excised. -->
+ <dependency>
+ <groupId>xalan</groupId>
+ <artifactId>xalan</artifactId>
+ <version>2.5.1</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jsch</artifactId>
+ <version>0.1.29</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>${resteasy.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jettison-provider</artifactId>
+ <version>${resteasy.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-links</artifactId>
+ <version>${resteasy.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.el</groupId>
+ <artifactId>jboss-el</artifactId>
+ <version>2.0.1.GA</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>2.3.18</version>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
<build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+
<plugins>
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <!-- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE
- -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine> -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <!-- Everything but the web service tests, this is the standard test execution -->
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <groups>${rhq.testng.includedGroups}</groups>
+ <systemPropertyVariables>
+ <embeddedDeployment>true</embeddedDeployment>
+ <deploymentDirectory>target/test-classes</deploymentDirectory>
+ <hibernate.dialect>${rhq.test.ds.hibernate-dialect}</hibernate.dialect>
+ <clean.db>${clean.db}</clean.db>
+ </systemPropertyVariables>
+ <argLine>-Djava.security.manager -Djava.security.policy==target/test-classes/security.policy</argLine>
+ <additionalClasspathElements>
+ <!-- The below is required for tests to run against Oracle. -->
+ <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc5/${ojdbc5.version}/ojdbc5-${ojdbc5.version}.jar</additionalClasspathElement>
+ </additionalClasspathElements>
</configuration>
- </plugin>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+
+ <!-- in order to get JMS to work properly in embedded test container, extract jms-rs.rar classes -->
+ <execution>
+ <id>Extract JMS classes from RAR needed for JMS tests</id>
+ <phase>process-classes</phase>
+ <configuration>
+ <tasks>
+ <unzip src="src/test/resources/jms-ra.rar" dest="target">
+ <patternset>
+ <include name="jms-ra.jar"/>
+ </patternset>
+ </unzip>
+ <unzip src="target/jms-ra.jar" dest="target/test-classes">
+ <patternset>
+ <include name="org/**"/>
+ </patternset>
+ </unzip>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
new file mode 100644
index 0000000..9c9d1bb
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
@@ -0,0 +1,175 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.client.security.test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.SerializablePermission;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.PermissionCollection;
+import java.util.Collections;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.bindings.SandboxedScriptEngine;
+import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.StandardScriptPermissions;
+import org.rhq.bindings.util.PackageFinder;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.client.LocalClient;
+import org.rhq.enterprise.server.security.AllowEjbAccessPermission;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class EjbAccessTest extends AbstractEJB3Test {
+
+ public void testEjbsAccessibleThroughPrivilegedCode() {
+ LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ public void testEjbsAccessibleThroughLocalClient() throws ScriptException, IOException {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ engine.eval("SubjectManager.getSubjectByName('rhqadmin');");
+ }
+
+ public void testLocalEjbsInaccessibleThroughJndiLookup() throws ScriptException, IOException {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "context = new javax.naming.InitialContext();\n"
+ + "subjectManager = context.lookup('SubjectManagerBean/local');\n"
+ + "subjectManager.getOverlord();");
+
+ Assert.fail("The script shouldn't have been able to call local SLSB method.");
+ } catch (ScriptException e) {
+ assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ }
+ }
+
+ public void testRemoteEjbsInaccessibleThroughJndiLookup() throws ScriptException, IOException {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "context = new javax.naming.InitialContext();\n"
+ + "subjectManager = context.lookup('SubjectManagerBean/remote');\n"
+ + "subjectManager.getSubjectByName('rhqadmin');");
+
+ Assert.fail("The script shouldn't have been able to call remote SLSB method directly.");
+ } catch (ScriptException e) {
+ //TODO java.io.IOException: access denied (java.io.SerializablePermission enableSubclassImplementation)
+ assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ }
+ }
+
+ public void testScriptCantUseSessionManager() throws ScriptException, IOException {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval("org.rhq.enterprise.server.auth.SessionManager.getInstance();");
+
+ Assert.fail("The script shouldn't have been able to get instance of SessionManager.");
+ } catch (ScriptException e) {
+ assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public void testScriptCantUseSessionManagerMethods() throws Exception {
+
+ //The code below cannot work in Rhino because as of now, Rhino modifies
+ //the return value of Class.getDeclaredField() to be null when there
+ //is a security manager installed.
+ //This has been filed as a bug at Oracle (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7119959)
+
+ if (true) {
+ return;
+ }
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ final ScriptEngine engine = getEngine(overlord);
+
+ class G {
+ private String obtainSessionManagerUsingReflection = ""
+ + "var sessionManagerClass = java.lang.Class.forName(\"org.rhq.enterprise.server.auth.SessionManager\");\n"
+ + "println(sessionManagerClass);\n"
+ + "var managerField = sessionManagerClass.getDeclaredField(\"_manager\");\n"
+ + "println(managerField);\n"
+ + "managerField.setAccessible(true);\n"
+ + "var manager = managerField.get(null);\n"
+ + "println(manager);\n"
+ + "manager.";
+
+ public void testInvoke(String methodCall) throws ScriptException {
+ String code = obtainSessionManagerUsingReflection + methodCall;
+
+ try {
+ engine.eval(code);
+ Assert.fail("The script shouldn't have been able to a method on a SessionManager.");
+ } catch (ScriptException e) {
+ assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ }
+ }
+ };
+ G manager = new G();
+
+ manager.testInvoke("getLastAccess(0);");
+ manager.testInvoke("getOverlord()");
+ manager.testInvoke("getSubject(2);");
+ manager.testInvoke("invalidate(0);");
+ manager.testInvoke("invalidate(\"\");");
+ manager.testInvoke("put(new org.rhq.core.domain.auth.Subject());");
+ manager.testInvoke("put(new org.rhq.core.domain.auth.Subject(), 0);");
+ }
+
+ private ScriptEngine getEngine(Subject subject) throws ScriptException, IOException {
+ StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new LocalClient(subject));
+ ScriptEngine engine = ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), bindings);
+
+ PermissionCollection perms = new StandardScriptPermissions();
+ perms.add(new SerializablePermission("enableSubclassImplementation"));
+
+ return new SandboxedScriptEngine(engine, perms);
+ }
+}
diff --git a/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml b/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml
new file mode 100644
index 0000000..caa7513
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
+ version="3.0">
+
+ <description>RHQ</description>
+ <display-name>RHQ</display-name>
+
+ <assembly-descriptor>
+
+ <!-- This interceptor checks that the alert CLI scripts don't try to circumvent our access objects by accessing the local SLSB beans directly. -->
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.security.AllowEjbAccessInterceptor</interceptor-class>
+ </interceptor-binding>
+
+ <!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.authz.RequiredPermissionsInterceptor</interceptor-class>
+ </interceptor-binding>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.common.TransactionInterruptInterceptor</interceptor-class>
+ </interceptor-binding>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.common.PerformanceMonitorInterceptor</interceptor-class>
+ </interceptor-binding>
+
+ </assembly-descriptor>
+
+</ejb-jar>
diff --git a/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml b/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml
new file mode 100644
index 0000000..b7c5c66
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<jboss xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
+ version="3.0">
+
+ <enterprise-beans>
+
+ <!--
+ The AlertConditionLogManagerBean, AlertConditionManagerBean, AlertDampeningManagerBean,
+ AlertDefinitionManagerBean, AlertManagerBean, AuthorizationManagerBean, CachedConditionManagerBean, and
+ SubjectManager SLSB's are all invoked, either directly or indirectly, by the AlertConditionConsumerBean MDB.
+ Since MDB invocations are always done in new threads, using the default SLSB pool impl (ThreadlocalPool) would
+ cause a new instance of these SLSB's to be created every time they were invoked by AlertConditionConsumerBean.
+ This would be bad if only because existing instances would
+ not be reused, but it is really bad because the instances would also never get destroyed, causing heap space to
+ gradually leak until the Server eventually ran out of memory. Hence, we must use a StrictMaxPool, which
+ will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool. Because lots of alert
+ definitions could result in many concurrent calls to AlertConditionConsumerBean, and because most of these
+ SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's), we set the max pool size to 100 to
+ minimize the chances of AlertConditionConsumerBean invocations, which are the most critical, from having to
+ block and potentially getting backed up in the queue. We set the pool timeout extremely high to essentially
+ prevent queued callers from timing out. Note, MDB's are configured in ejb3-interceptors-aop.xml to use a strict
+ max pool with a max of 15 and a timeout of 10000, so AlertConditionConsumerBean might become a bottleneck for
+ systems with a lot of alerts defined. (ips, 05/10/11)
+
+ For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
+ -->
+
+ <session>
+ <ejb-name>AlertConditionLogManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertConditionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertDampeningManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertDefinitionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AlertManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>AuthorizationManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>CachedConditionManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>SubjectManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>100</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+
+ <!--
+ The CacheConsistencyManagerBean, CloudManagerBean, ServerManagerBean, StatusManagerBean, and SystemManagerBean
+ SLSB's are all invoked, either directly or indirectly, by EJB timers. Since EJB timer invocations are always
+ done in new threads, using the default SLSB pool impl (ThreadlocalPool) would cause a new instance of this
+ SLSB to be created every time it was invoked by an EJB timer. This would be bad if only because an existing
+ instance would not be reused, but it is really bad because the instance would also never get destroyed, causing
+ heap space to gradually leak until the Server eventually ran out of memory. Hence, we must use a
+ StrictMaxPool, which will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool.
+ The timer invocations will only require one or two instances at any given time, but because most of these
+ SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's, we set the max pool size to 30, to
+ minimize the chances of EJB timer invocations, which are the most critical, from having to block and
+ potentially getting backed up in the queue. We set the pool timeout extremely high to essentially prevent
+ queued callers from timing out. (ips, 05/10/11)
+
+ For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
+ -->
+
+ <session>
+ <ejb-name>CacheConsistencyManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>CloudManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>ServerManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>StatusManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ <session>
+ <ejb-name>SystemManagerBean</ejb-name>
+ <pool-config>
+ <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
+ <pool-max-size>30</pool-max-size>
+ <pool-timeout>1000000000</pool-timeout>
+ </pool-config>
+ </session>
+
+ </enterprise-beans>
+
+</jboss>
diff --git a/modules/enterprise/server/client-api/src/test/resources/hibernate.properties b/modules/enterprise/server/client-api/src/test/resources/hibernate.properties
new file mode 100644
index 0000000..1951b84
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/test/resources/hibernate.properties
@@ -0,0 +1,26 @@
+# FOR SOME STRANGE REASON, THIS FILE NEEDS TO BE HERE FOR THE HIBERNATE TO CORRECTLY
+# INITIALIZE. I DON'T KNOW WHY THE STANDARD default.persistence.properties FILE DOESN'T
+# WORK IN THIS MODULE.
+
+hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
+#hibernate.connection.release_mode=after_statement
+#hibernate.transaction.flush_before_completion=false
+#hibernate.transaction.auto_close_session=false
+#hibernate.query.factory_class=org.hibernate.hql.ast.ASTQueryTranslatorFactory
+#hibernate.hbm2ddl.auto=create-drop
+#hibernate.hbm2ddl.auto=create
+hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
+# Clustered cache with TreeCache
+#hibernate.cache.provider_class=org.jboss.ejb3.entity.TreeCacheProviderHook
+#hibernate.treecache.mbean.object_name=jboss.cache:service=EJB3EntityTreeCache
+#hibernate.dialect=org.hibernate.dialect.HSQLDialect
+hibernate.jndi.java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+hibernate.jndi.java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
+hibernate.bytecode.use_reflection_optimizer=false
+# I don't think this is honored, but EJB3Deployer uses it
+hibernate.bytecode.provider=javassist
+hibernate.jdbc.use_streams_for_binary=true
+hibernate.show_sql=false
+hibernate.format_sql=true
+hibernate.default_batch_fetch_size=16
+hibernate.jdbc.batch_size=20
diff --git a/modules/enterprise/server/client-api/src/test/resources/jms-ra.rar b/modules/enterprise/server/client-api/src/test/resources/jms-ra.rar
new file mode 100644
index 0000000..c4807c6
Binary files /dev/null and b/modules/enterprise/server/client-api/src/test/resources/jms-ra.rar differ
diff --git a/modules/enterprise/server/client-api/src/test/resources/security.policy b/modules/enterprise/server/client-api/src/test/resources/security.policy
new file mode 100644
index 0000000..8860b47
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/test/resources/security.policy
@@ -0,0 +1,10 @@
+// We need the SecurityManager installed to enable sandboxing of CLI scripts
+// but we don't define any other security measures on the RHQ server itself.
+//
+// Granting all permissions allows us to run the RHQ server as if no security
+// manager was in place (which is assumed by default by JBoss AS) but be able
+// to use it when we need it for our own purposes.
+
+grant {
+ permission java.security.AllPermission;
+};
commit ef5673fb4482fd08cdec672740afc2f12a3d2b0b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Sat Dec 10 01:17:50 2011 +0100
Making SessionManager behave the same as EJBs wrt the AccessEjbPermission.
It is very security-sensitive so we shouldn't allow scripts to just access
it and cause havoc in user sessions.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
index 39b6076..b4a19b7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
@@ -25,30 +25,42 @@ import java.util.Map;
import java.util.Random;
import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.server.security.AllowEjbAccessPermission;
import org.rhq.enterprise.server.util.LookupUtil;
/**
* This is the JON Server's own session ID generator. It is outside any container-provided session mechanism. Its sole
* purpose is to provide session IDs to logged in {@link Subject}s. It will timeout those sessions regardless of any
* container-provided session-timeout mechanism.
- *
+ * <p>
+ * Because this is a very security-sensitive class, any public method requires the caller to
+ * have the {@link AllowEjbAccessPermission} as any other calls to the EJB layer. This is so that the
+ * malicious users can't trick the EJB layer into thinking that some users are logged in or log out other
+ * users.
+ * <p>
+ * Also, for security reasons, this class is final so that malicious code can't subclass it and modify its
+ * behavior.
+ *
* <p>This object is a {@link #getInstance() singleton}.</p>
*/
-public class SessionManager {
+public final class SessionManager {
+
+ private static final AllowEjbAccessPermission ACCESS_PERMISSION = new AllowEjbAccessPermission();
+
/**
* Our source for random session IDs.
*/
- private static Random _random = new Random();
+ private static final Random _random = new Random();
/**
* Our session cache that is keyed on the session ID.
*/
- private static Map<Integer, AuthSession> _cache = new HashMap<Integer, AuthSession>();
+ private static final Map<Integer, AuthSession> _cache = new HashMap<Integer, AuthSession>();
/**
* The singleton instance
*/
- private static SessionManager _manager = new SessionManager();
+ private static final SessionManager _manager = new SessionManager();
/**
* The timeout for all user sessions.
@@ -78,7 +90,7 @@ public class SessionManager {
/**
* Return the singleton object.
- *
+ *
* @return the {@link SessionManager}
*/
public static SessionManager getInstance() {
@@ -95,6 +107,7 @@ public class SessionManager {
* sessionId will be assigned.
*/
public Subject put(Subject subject) {
+ checkPermission();
return put(subject, DEFAULT_TIMEOUT);
}
@@ -108,6 +121,7 @@ public class SessionManager {
* that Subject is overlord). The sessionId will be assigned.
*/
public synchronized Subject put(Subject subject, long timeout) {
+ checkPermission();
Integer key;
do {
@@ -141,6 +155,7 @@ public class SessionManager {
* @throws SessionTimeoutException
*/
public synchronized Subject getSubject(int sessionId) throws SessionNotFoundException, SessionTimeoutException {
+ checkPermission();
Integer id = new Integer(sessionId);
AuthSession session = _cache.get(id);
@@ -162,6 +177,7 @@ public class SessionManager {
* @param sessionId session id to invalidate
*/
public synchronized void invalidate(int sessionId) {
+ checkPermission();
_cache.remove(new Integer(sessionId));
// while we are here, let's go through the entire session cache and remove expired sessions
@@ -187,6 +203,7 @@ public class SessionManager {
* @param username username for the sessions to be invalidated
*/
public synchronized void invalidate(String username) {
+ checkPermission();
List<Integer> doomedSessionIds = new ArrayList<Integer>(_cache.size());
for (AuthSession s : _cache.values()) {
if (username.equals(s.getSubject(false).getName())) {
@@ -201,6 +218,7 @@ public class SessionManager {
}
public long getlastAccess(int sessionId) {
+ checkPermission();
AuthSession session = _cache.get(sessionId);
if (session == null) {
return -1;
@@ -209,6 +227,7 @@ public class SessionManager {
}
public Subject getOverlord() {
+ checkPermission();
if (overlordSubject == null) {
overlordSubject = LookupUtil.getSubjectManager().getSubjectById(OVERLORD_SUBJECT_ID);
@@ -256,4 +275,9 @@ public class SessionManager {
return copy;
}
+
+ private static void checkPermission() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
+ }
}
\ No newline at end of file
commit 0b0632e5641e91f3549e5addbc2c18bb27132c5a
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Sat Dec 10 01:16:26 2011 +0100
moving the EJB access permission and the interceptor back to the server
jar.
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessInterceptor.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessInterceptor.java
deleted file mode 100644
index d3dcdb2..0000000
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessInterceptor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.enterprise.client.security;
-
-import java.security.AccessController;
-import java.security.Permission;
-
-import javax.interceptor.AroundInvoke;
-import javax.interceptor.InvocationContext;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class AllowEjbAccessInterceptor {
-
- private static final Permission PERM = new AllowEjbAccessPermission();
-
- @AroundInvoke
- public Object intercept(InvocationContext invocationContext) throws Exception {
- //check that the caller has permissions to access the EJBs.
- //normal code does, only alert CLI scripts that try to circumvent our
- //manager proxies don't.
- AccessController.checkPermission(PERM);
- return invocationContext.proceed();
- }
-}
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessPermission.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessPermission.java
deleted file mode 100644
index 19ee165..0000000
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessPermission.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-package org.rhq.enterprise.client.security;
-
-import java.security.BasicPermission;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class AllowEjbAccessPermission extends BasicPermission {
-
- private static final long serialVersionUID = 1L;
-
- public AllowEjbAccessPermission() {
- super("rhq.allow.ejb.access");
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java
new file mode 100644
index 0000000..350453fb
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java
@@ -0,0 +1,46 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.server.security;
+
+import java.security.Permission;
+
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.InvocationContext;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AllowEjbAccessInterceptor {
+
+ private static final Permission PERM = new AllowEjbAccessPermission();
+
+ @AroundInvoke
+ public Object intercept(InvocationContext invocationContext) throws Exception {
+ //check that the caller has permissions to access the EJBs.
+ //normal code does, only alert CLI scripts that try to circumvent our
+ //manager proxies don't.
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) sm.checkPermission(PERM);
+
+ return invocationContext.proceed();
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java
new file mode 100644
index 0000000..67f418d
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java
@@ -0,0 +1,36 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.server.security;
+
+import java.security.BasicPermission;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AllowEjbAccessPermission extends BasicPermission {
+
+ private static final long serialVersionUID = 1L;
+
+ public AllowEjbAccessPermission() {
+ super("rhq.allow.ejb.access");
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
index 2700ae3..caa7513 100644
--- a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
+++ b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
@@ -12,7 +12,7 @@
<!-- This interceptor checks that the alert CLI scripts don't try to circumvent our access objects by accessing the local SLSB beans directly. -->
<interceptor-binding>
<ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.client.security.AllowEjbAccessInterceptor</interceptor-class>
+ <interceptor-class>org.rhq.enterprise.server.security.AllowEjbAccessInterceptor</interceptor-class>
</interceptor-binding>
<!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
commit 248f6d5a2e08b7367490a47b892ccf8080fa1545
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Dec 7 17:50:25 2011 +0100
be paranoid even in the comments ;)
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
index 7fcdac3..e9f1e4d 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
@@ -62,7 +62,9 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
//run this through the privileged block to elevate the privs of the script
//the scripts don't have the AllowEjbAccessPermission but this code has
- //all perms.
+ //all perms (or at least all perms assigned to it by the current context,
+ //which at the time of writing is defined by the rhq-server.policy file
+ //which gives all code all permissions).
return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
commit 84f032252328434e01ac68d40bec34d102533d81
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Dec 7 13:54:34 2011 +0100
Use a custom java permission and an EJB interceptor to disallow server-side CLI scripts from accessing the EJBs directly.
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index e777e21..b125b3b 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -26,6 +26,7 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
+
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
@@ -40,6 +41,14 @@
section. -->
<scope>provided</scope>
</dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-ejb3x</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
</dependencies>
<build>
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
index 5f3ff90..7fcdac3 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
@@ -20,6 +20,8 @@
package org.rhq.enterprise.client;
import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import org.apache.commons.logging.Log;
@@ -54,11 +56,19 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
}
}
- protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, Object[] args) throws Throwable {
+ protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, final Object[] args) throws Throwable {
try {
- Method realMethod = localSLSB.getClass().getMethod(originalMethod.getName(), argTypes);
-
- return realMethod.invoke(localSLSB, args);
+ final Method realMethod = localSLSB.getClass().getMethod(originalMethod.getName(), argTypes);
+
+ //run this through the privileged block to elevate the privs of the script
+ //the scripts don't have the AllowEjbAccessPermission but this code has
+ //all perms.
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ return realMethod.invoke(localSLSB, args);
+ }
+ });
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Method [" + originalMethod + "] does not have a desimplified counterpart with arguments " + Arrays.asList(argTypes) + ".", e);
}
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessInterceptor.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessInterceptor.java
new file mode 100644
index 0000000..d3dcdb2
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessInterceptor.java
@@ -0,0 +1,45 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.client.security;
+
+import java.security.AccessController;
+import java.security.Permission;
+
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.InvocationContext;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AllowEjbAccessInterceptor {
+
+ private static final Permission PERM = new AllowEjbAccessPermission();
+
+ @AroundInvoke
+ public Object intercept(InvocationContext invocationContext) throws Exception {
+ //check that the caller has permissions to access the EJBs.
+ //normal code does, only alert CLI scripts that try to circumvent our
+ //manager proxies don't.
+ AccessController.checkPermission(PERM);
+ return invocationContext.proceed();
+ }
+}
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessPermission.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessPermission.java
new file mode 100644
index 0000000..19ee165
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/security/AllowEjbAccessPermission.java
@@ -0,0 +1,36 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.client.security;
+
+import java.security.BasicPermission;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AllowEjbAccessPermission extends BasicPermission {
+
+ private static final long serialVersionUID = 1L;
+
+ public AllowEjbAccessPermission() {
+ super("rhq.allow.ejb.access");
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
index 8222948..2700ae3 100644
--- a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
+++ b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
@@ -9,6 +9,12 @@
<assembly-descriptor>
+ <!-- This interceptor checks that the alert CLI scripts don't try to circumvent our access objects by accessing the local SLSB beans directly. -->
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.client.security.AllowEjbAccessInterceptor</interceptor-class>
+ </interceptor-binding>
+
<!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
<interceptor-binding>
<ejb-name>*</ejb-name>
12 years, 5 months
[rhq] Branch 'lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs' - modules/enterprise
by lkrejci
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java | 21 +++++-----
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java | 4 -
2 files changed, 12 insertions(+), 13 deletions(-)
New commits:
commit eb92c16f4ac8151e1984406af677f950f9984af4
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jan 3 15:07:13 2012 +0100
updating the javadocs to correctly explain the purpose of the URLPreferringContext
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
index b291c3e..c6456a2 100644
--- a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
@@ -35,17 +35,18 @@ import javax.naming.spi.NamingManager;
* <p>
* This is important because RHQ server has its own initial context factory
* builder that creates factories that in turn create contexts. If the default
- * {@link InitialContext} implementation was used, we'd end up with a stack overflow
- * error caused by the callchain loop when the {@link InitialContext} would ask
- * the builder for a factory that would create another context that would ask the
- * builder for the factory, etc. ad infinitum.
+ * {@link InitialContext} implementation was used, we'd never be able to lookup
+ * scheme-based names because the default implementation of the {@link InitialContext}
+ * always uses the default context of the builder if one is installed no matter
+ * the scheme in the name.
* <p>
- * This class prevents that by acting exactly like the InitialContext would if
- * the initial context factory builder wasn't installed. This enables the callers
- * to still use the standard InitialContext when doing lookups etc. This standard
- * initial context will ask our initial context factory builder which will then
- * in chain create this {@link URLPreferringContext} that behaves like the original
- * InitialContext would if the builder wasn't there.
+ * The {@link AccessCheckingInitialContextFactoryBuilder} wraps the context returned
+ * by the factory in an instance of this class and thus is restoring the original
+ * intended behavior of the {@link InitialContext}. It looks at the name being looked
+ * up (bound or whatever) and prefers to use the URL context factories if the name
+ * contains the scheme (as does the {@link InitialContext} if no builder is installed).
+ * If the name doesn't contain a scheme, the provided default context factory is used to
+ * look up the name.
*
* @author Lukas Krejci
*/
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
index 6c311c7..609e98c 100644
--- a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
@@ -22,7 +22,6 @@ package org.rhq.jndi;
import java.util.Hashtable;
import javax.naming.Context;
-import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
@@ -31,8 +30,7 @@ import javax.naming.spi.InitialContextFactory;
* backed by the wrapped initial context factory.
* <p>
* This is to support contexts that don't need to be secured, yet we need to make sure to
- * break the call-chain loop caused by the {@link InitialContext} asking the RHQ's {@link AccessCheckingInitialContextFactoryBuilder} for
- * default contexts.
+ * re-enable lookup of scheme-based names.
*
* @author Lukas Krejci
*/
12 years, 5 months