com.sun.enterprise.security.ee.Audit Maven / Gradle / Ivy
Show all versions of payara-micro Show documentation
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.security.ee;
import java.util.*;
import java.util.logging.Logger;
import java.util.logging.Level;
//V3:Commented import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import com.sun.logging.LogDomains;
import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.EjbBundleDescriptor;
import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.MethodPermission;
import com.sun.enterprise.deployment.MethodDescriptor;
import com.sun.enterprise.deployment.RunAsIdentityDescriptor;
import com.sun.enterprise.deployment.EjbIORConfigurationDescriptor;
import com.sun.enterprise.deployment.WebBundleDescriptor;
import com.sun.enterprise.deployment.web.SecurityConstraint;
import com.sun.enterprise.deployment.web.AuthorizationConstraint;
import com.sun.enterprise.deployment.web.LoginConfiguration;
import com.sun.enterprise.deployment.web.UserDataConstraint;
import com.sun.enterprise.deployment.web.SecurityRole;
import com.sun.enterprise.deployment.web.WebResourceCollection;
import com.sun.enterprise.deployment.WebComponentDescriptor;
import org.glassfish.security.common.Role;
import org.glassfish.deployment.common.SecurityRoleMapper;
import javax.servlet.http.HttpServletRequest;
import com.sun.appserv.security.AuditModule;
/**
* Audit support class.
*
* This class provides convenience methods for producing audit output.
* Audit output is logged using the standard iAS logger SECURITYLOGGER.
* However, audit output is only produced if auditing is active. Auditing
* is configured in server.xml in the security-service element.
*
*
Audit output if logged with Level.WARNING.
*
*
Some diagnostic methods are also provided for debugging.
*
*/
public class Audit extends AuditModule
{
private static final String AUDIT_ON = "auditOn";
private static boolean auditFlag = false;
private static Logger logger =
LogDomains.getLogger(Audit.class, LogDomains.SECURITY_LOGGER);
/*
private static String strPrivateAudit = null;
private static String strDenied = null;
private static String strOK = null;
private static String strMethodName = null;
private static String strSession = null;
*/
/**
* Check auditing state.
*
* @returns True if auditing is active currently.
*
*/
public static boolean isActive()
{
return auditFlag;
}
public void init(Properties props) {
super.init(props);
String audit = props.getProperty(AUDIT_ON);
auditFlag = (audit == null)?false: Boolean.valueOf(audit).booleanValue();
}
/**
* Invoked post authentication request for a user in a given realm
* @param user username for whom the authentication request was made
* @param realm the realm name under which the user is authenticated.
* @param success the status of the authentication
*/
public void authentication(String user, String realm, boolean success) {
if (auditFlag) {
StringBuffer sbuf = new StringBuffer("Audit: Authentication for user = (");
sbuf.append(user);
sbuf.append(") under realm = (");
sbuf.append(realm).append(") returned = ").append(success);
logger.log(Level.INFO, sbuf.toString());
}
}
/**
* Invoked post web authorization request.
* @param user the username for whom the authorization was performed
* @param req the HttpRequest object for the web request
* @param type either hasResourcePermission, hasUserDataPermission or
* hasRoleRefPermission
* @param success the status of the web authorization request
*/
public void webInvocation(String user, HttpServletRequest req,
String type, boolean success)
{
if (auditFlag){
StringBuilder sbuf = new StringBuilder("Audit: [Web] Authorization for user = (");
sbuf.append(user).append(") and permission type = (").append(type).append(") for request ");
sbuf.append(req.getMethod()).append(" ").append(req.getRequestURI()).append(" returned =").append(success);
logger.log(Level.INFO, sbuf.toString());
}
}
/**
* Invoked post ejb authorization request.
* @param user the username for whom the authorization was performed
* @param ejb the ejb name for which this authorization was performed
* @param method the method name for which this authorization was performed
* @param success the status of the ejb authorization request
*/
public void ejbInvocation(String user, String ejb, String method, boolean success) {
if(auditFlag){
// Modified from StringBuffer to StringBuilder
StringBuilder sbuf = new StringBuilder("Audit: [EJB] Authorization for user =");
sbuf.append(user).append(" for ejb = (");
sbuf.append(ejb).append(") method = (").append(method).append(") returned =").append(success);
logger.log(Level.INFO, sbuf.toString());
}
}
/**
* Invoked post ejb authorization request.
* @param user the username for whom the authorization was performed
* @param ejb the ejb name for which this authorization was performed
* @param method the method name for which this authorization was performed
* @param success the status of the ejb authorization request
*/
/**
* Invoked during validation of the web service request
* @param uri The URL representation of the web service endpoint
* @param endpoint The name of the endpoint representation
* @param success the status of the web service request validation
*/
public void webServiceInvocation(String uri, String endpoint, boolean success) {
if(auditFlag){
StringBuilder sbuf = new StringBuilder("Audit: [WebService] ");
sbuf.append("uri: ").append(uri);
sbuf.append("endpoint: ").append(endpoint);
sbuf.append(", valid request =").append(success);
logger.log(Level.INFO, sbuf.toString());
}
}
/**
* Invoked during validation of the web service request
* @param endpoint The URL representation of the web service endpoint
* @param success the status of the web service request validation
*/
public void ejbAsWebServiceInvocation(String endpoint, boolean success) {
if(auditFlag){
StringBuilder sbuf = new StringBuilder("Audit: [EjbAsWebService] ");
sbuf.append("endpoint : ").append(endpoint).append(", valid request =").append(success);
logger.log(Level.INFO, sbuf.toString());
}
}
/**
* Invoked upon completion of the server startup
*/
public void serverStarted() {
if(auditFlag){
logger.log(Level.INFO, "Audit: Application server startup complete");
}
}
/**
* Invoked upon completion of the server shutdown
*/
public void serverShutdown() {
if(auditFlag){
logger.log(Level.INFO, "Audit: Application server shutdown complete");
}
}
/**
* Initialize auditing. This reads the server.xml configuration to
* determine whether audit is turned on or off.
*
*/
/*
public static void init()
{
try {
ConfigContext configContext =
ApplicationServer.getServerContext().getConfigContext();
assert(configContext != null);
Server configBean =
ServerBeansFactory.getServerBean(configContext);
assert(configBean != null);
SecurityService securityBean =
ServerBeansFactory.getSecurityServiceBean(configContext);
assert(securityBean != null);
auditFlag = securityBean.isAuditEnabled();
} catch (Exception e) {
logger.log(Level.WARNING, "audit.badinit", e);
}
if (auditFlag) {
logger.info("audit.enabled");
}
// load i18n message bits for audit entries
ResourceBundle resBundle = logger.getResourceBundle();
strPrivateAudit = resBundle.getString("audit.string_private_audit");
strDenied = " " + resBundle.getString("audit.denied");
strOK = " " + resBundle.getString("audit.ok");
strMethodName = " " + resBundle.getString("audit.methodname");
strSession = " " + resBundle.getString("audit.session");
}
*/
/**
* Log an EJB method invocation.
*
* @param user Effective user for the invocation.
* @param ejb EJB name.
* @param method Method name.
* @param success True if the invocation was allowed, false if denied.
*
*/
/*
public static void ejbMethodInvocation(SecurityContext secCtx,
EJBLocalRemoteObject ejbObj,
Method method,
boolean success)
{
if (!logger.isLoggable(Level.INFO)) {
return;
}
String user = "(null)";
if (secCtx != null) {
Principal p = secCtx.getCallerPrincipal();
if (p!=null) {
user = p.getName();
}
}
String ejb = "(N/A)";
if (ejbObj != null) {
ejb = ejbObj.toString();
}
String meth = "(N/A)";
if (method != null) {
meth = method.toString();
}
StringBuffer sb = new StringBuffer();
sb.append(strPrivateAudit); // "Audit: principal="
if(user != null) {
sb.append(user);
} else {
sb.append("(null)");
}
sb.append(" ejb=");
sb.append(ejb);
sb.append(strMethodName); // " method="
sb.append(method);
if (success) {
sb.append(strOK); // " OK"
} else {
sb.append(strDenied); // " DENIED"
}
logger.info(sb.toString());
}
*/
/**
* Log a servlet invocation.
*
* @param req The HttpRequest.
* @param success True if the invocation was allowed, false if denied.
*
*/
/*
public static void webInvocation(HttpRequest req, boolean success)
{
/// DO NOTHING FOR NOW.
//if (!logger.isLoggable(Level.INFO) || !auditFlag) {
// return;
//}
//if (req == null) {
// logger.fine("Audit: No HttpRequest available.");
// return;
//}
//if (!(req instanceof HttpRequestBase)) {
// logger.fine("Audit internal error, class: " + req.getClass());
// return;
//}
//HttpRequestBase reqs = (HttpRequestBase)req;
//StringBuffer sb = new StringBuffer();
//sb.append(strPrivateAudit); // "Audit: principal="
//String user = reqs.getRemoteUser();
//if (user != null) {
// sb.append(user);
//} else {
// sb.append("(null)");
//}
//sb.append(" ");
//sb.append(reqs.getMethod());
//sb.append(" ");
//sb.append(reqs.getRequestURI());
//sb.append(strSession); // " session="
//sb.append(reqs.getRequestedSessionId());
//if (success) {
// sb.append(strOK); // " OK"
//} else {
// sb.append(strDenied); // " DENIED"
//}
//logger.info(sb.toString());
}
*/
/**
* Diagnostic method. Read roles and ACLs from the given Application
* and dump a somewhat organized summary of what has been set.
* This can be used to diagnose deployment or runtime deployment errors
* as well as to help in configuring application descriptors.
*
*
Implementation is not particularly efficient but this is only
* called for debugging purposes at startup. All errors are ignored.
*
* @param app Application object to analyze.
*
*/
public static void showACL(Application app)
{
if (!isActive() || !logger.isLoggable(Level.FINEST)) {
return;
}
try {
dumpDiagnostics(app);
} catch (Throwable e) {
logger.fine("Error while showing ACL diagnostics: " +
e.toString());
}
}
/**
* Do the work for showACL().
*
*/
private static void dumpDiagnostics(Application app)
{
logger.finest("====[ Role and ACL Summary ]==========");
if (!app.isVirtual()) {
logger.finest("Summary for application: "+
app.getRegistrationName());
} else {
logger.finest("Standalone module.");
}
logger.finest("EJB components: "+
getEjbComponentCount(app));
logger.finest("Web components: " +
getWebComponentCount(app));
Iterator i;
StringBuffer sb;
// show all roles with associated group & user mappings
Set allRoles = app.getRoles();
if (allRoles == null) {
logger.finest("- No roles present.");
return;
}
SecurityRoleMapper rmap = app.getRoleMapper();
if (rmap == null) {
logger.finest("- No role mappings present.");
return;
}
i = allRoles.iterator();
logger.finest("--[ Configured roles and mappings ]--");
HashMap allRoleMap = new HashMap();
while (i.hasNext()) {
Role r = (Role)i.next();
logger.finest(" [" + r.getName() + "]");
allRoleMap.put(r.getName(), new HashSet());
sb = new StringBuffer();
sb.append(" is mapped to groups: ");
Enumeration grps = rmap.getGroupsAssignedTo(r);
while (grps.hasMoreElements()) {
sb.append(grps.nextElement());
sb.append(" ");
}
logger.finest(sb.toString());
sb = new StringBuffer();
sb.append(" is mapped to principals: ");
Enumeration users = rmap.getUsersAssignedTo(r);
while (users.hasMoreElements()) {
sb.append(users.nextElement());
sb.append(" ");
}
logger.finest(sb.toString());
}
// Process all EJB modules
Set ejbDescriptorSet = app.getBundleDescriptors(EjbBundleDescriptor.class) ;
i = ejbDescriptorSet.iterator();
while (i.hasNext()) {
EjbBundleDescriptor bundle = (EjbBundleDescriptor)i.next();
logger.finest("--[ EJB module: " + bundle.getName() + " ]--");
Set ejbs = bundle.getEjbs();
Iterator it = ejbs.iterator();
while (it.hasNext()) {
EjbDescriptor ejb = (EjbDescriptor)it.next();
logger.finest("EJB: "+ejb.getEjbClassName());
// check and show run-as if present
if (!ejb.getUsesCallerIdentity()) {
RunAsIdentityDescriptor runas = ejb.getRunAsIdentity();
if (runas == null) {
logger.finest(" (ejb does not use caller "+
"identity)");
} else {
String role = runas.getRoleName();
String user = runas.getPrincipal();
logger.finest(" Will run-as: Role: " + role +
" Principal: " + user);
if (role==null || "".equals(role) ||
user==null || "".equals(user)) {
if(logger.isLoggable(Level.FINEST)){
logger.finest("*** Configuration error!");
}
}
}
}
// iterate through available methods
logger.finest(" Method to Role restriction list:");
Set methods = ejb.getMethodDescriptors();
Iterator si = methods.iterator();
while (si.hasNext()) {
MethodDescriptor md = (MethodDescriptor)si.next();
logger.finest(" "+md.getFormattedString());
Set perms = ejb.getMethodPermissionsFor(md);
StringBuffer rbuf = new StringBuffer();
rbuf.append(" can only be invoked by: ");
Iterator sip = perms.iterator();
boolean unchecked=false,excluded=false,roleBased=false;
while (sip.hasNext()) {
MethodPermission p = (MethodPermission)sip.next();
if (p.isExcluded()) {
excluded=true;
logger.finest(" excluded - can not "+
"be invoked");
} else if (p.isUnchecked()) {
unchecked=true;
logger.finest(" unchecked - can be "+
"invoked by all");
} else if (p.isRoleBased()) {
roleBased = true;
Role r = p.getRole();
rbuf.append(r.getName());
rbuf.append(" ");
// add to role's accessible list
HashSet ram = (HashSet)allRoleMap.get(r.getName());
ram.add(bundle.getName() + ":" +
ejb.getEjbClassName() + "." +
md.getFormattedString());
}
}
if (roleBased) {
logger.finest(rbuf.toString());
if (excluded || unchecked) {
logger.finest("*** Configuration error!");
}
} else if (unchecked) {
if (excluded) {
logger.finest("*** Configuration error!");
}
Set rks = allRoleMap.keySet();
Iterator rksi = rks.iterator();
while (rksi.hasNext()) {
HashSet ram = (HashSet)allRoleMap.get(rksi.next());
ram.add(bundle.getName() + ":" +
ejb.getEjbClassName() + "." +
md.getFormattedString());
}
} else if (!excluded) {
logger.finest("*** Configuration error!");
}
}
// IOR config for this ejb
logger.finest(" IOR configuration:");
Set iors = ejb.getIORConfigurationDescriptors();
if (iors != null) {
Iterator iorsi = iors.iterator();
while (iorsi.hasNext()) {
EjbIORConfigurationDescriptor ior =
(EjbIORConfigurationDescriptor)iorsi.next();
StringBuffer iorsb = new StringBuffer();
iorsb.append("realm=");
iorsb.append(ior.getRealmName());
iorsb.append(", integrity=");
iorsb.append(ior.getIntegrity());
iorsb.append(", trust-in-target=");
iorsb.append(ior.getEstablishTrustInTarget());
iorsb.append(", trust-in-client=");
iorsb.append(ior.getEstablishTrustInClient());
iorsb.append(", propagation=");
iorsb.append(ior.getCallerPropagation());
iorsb.append(", auth-method=");
iorsb.append(ior.getAuthenticationMethod());
logger.finest(iorsb.toString());
}
}
}
}
// show role->accessible methods list
logger.finest("--[ EJB methods accessible by role ]--");
Set rks = allRoleMap.keySet();
Iterator rksi = rks.iterator();
while (rksi.hasNext()) {
String roleName = (String)rksi.next();
logger.finest(" [" + roleName + "]");
HashSet ram = (HashSet)allRoleMap.get(roleName);
Iterator rami = ram.iterator();
while (rami.hasNext()) {
String meth = (String)rami.next();
logger.finest(" "+meth);
}
}
// Process all Web modules
Set webDescriptorSet = app.getBundleDescriptors(WebBundleDescriptor.class) ;
i = webDescriptorSet.iterator();
while (i.hasNext()) {
WebBundleDescriptor wbd = (WebBundleDescriptor)i.next();
logger.finest("--[ Web module: " + wbd.getContextRoot() + " ]--");
// login config
LoginConfiguration lconf = wbd.getLoginConfiguration();
if (lconf != null) {
logger.finest(" Login config: realm="+
lconf.getRealmName() + ", method="+
lconf.getAuthenticationMethod() + ", form="+
lconf.getFormLoginPage() + ", error="+
lconf.getFormErrorPage());
}
// get WebComponentDescriptorsSet() info
logger.finest(" Contains components:");
Set webComps = wbd.getWebComponentDescriptors();
Iterator webCompsIt = webComps.iterator();
while (webCompsIt.hasNext()) {
WebComponentDescriptor wcd =
(WebComponentDescriptor)webCompsIt.next();
StringBuffer name = new StringBuffer();
name.append(" - "+wcd.getCanonicalName());
name.append(" [ ");
Enumeration urlPs = wcd.getUrlPatterns();
while (urlPs.hasMoreElements()) {
name.append(urlPs.nextElement().toString());
name.append(" ");
}
name.append("]");
logger.finest(name.toString());
RunAsIdentityDescriptor runas =
(RunAsIdentityDescriptor)wcd.getRunAsIdentity();
if (runas!=null) {
String role = runas.getRoleName();
String user = runas.getPrincipal();
logger.finest(" Will run-as: Role: " + role +
" Principal: " + user);
if (role==null || "".equals(role) ||
user==null || "".equals(user)) {
logger.finest("*** Configuration error!");
}
}
}
// security constraints
logger.finest(" Security constraints:");
Enumeration scEnum = wbd.getSecurityConstraints();
while (scEnum.hasMoreElements()) {
SecurityConstraint sc =
(SecurityConstraint)scEnum.nextElement();
for (WebResourceCollection wrc: sc.getWebResourceCollections()) {
// show list of methods for this collection
StringBuffer sbm = new StringBuffer();
for (String httpMethod: wrc.getHttpMethods()) {
sbm.append(httpMethod);
sbm.append(" ");
}
logger.finest(" Using method: "+sbm.toString());
// and then list of url patterns
for (String urlPattern: wrc.getUrlPatterns()) {
logger.finest(" "+ urlPattern);
}
} // end res.collection iterator
// show roles which apply to above set of collections
AuthorizationConstraint authCons =
sc.getAuthorizationConstraint();
Enumeration rolesEnum = authCons.getSecurityRoles();
StringBuffer rsb = new StringBuffer();
rsb.append(" Accessible by roles: ");
while (rolesEnum.hasMoreElements()) {
SecurityRole sr = (SecurityRole)rolesEnum.nextElement();
rsb.append(sr.getName());
rsb.append(" ");
}
logger.finest(rsb.toString());
// show transport guarantee
UserDataConstraint udc =sc.getUserDataConstraint();
if (udc != null) {
logger.finest(" Transport guarantee: "+
udc.getTransportGuarantee());
}
} // end sec.constraint
} // end webDescriptorSet.iterator
logger.finest("======================================");
}
/**
* The number of Web Components in this application.
* Current implementation only return the number of servlets
* inside the application, and not the JSPs since we cannot
* get that information from deployment descriptors.
*
* @return the number of Web Components
*/
private static int getWebComponentCount(Application app) {
int count = 0;
for (WebBundleDescriptor wbd : app.getBundleDescriptors(WebBundleDescriptor.class)) {
count = count + wbd.getWebComponentDescriptors().size();
}
return count;
}
/**
* The number of EJB JARs in this application.
*
* @return the number of EJB JARS
*/
private static int getEjbComponentCount(Application app) {
int count = 0;
for (EjbBundleDescriptor ejbd : app.getBundleDescriptors(EjbBundleDescriptor.class)) {
count = count + ejbd.getEjbs().size();
}
return count;
}
}