Using
Add a user to the sudoers file. e.g. allow user mchyzer to restart tomcats (that are allowed in Grouper). Note, you pass in the user's name in the first command line arg so the command knows who is running it (since it is run as appadmin by sudo)
mchyzer ALL=(appadmin) /opt/appserv/binMgmt/clusterTomcatHelper mchyzer *
sdf
One-time setup
Create a permission definition:
Add action inheritance so "all" implies the others
Create a role for an environment
Add permission names for each application, in this case prefix the real app name with "app_"
Assign permissions to a user in the role
Change log consumer:
/** * @author mchyzer * $Id: PcdChangeLogConsumer.java,v 1.1 2011/11/15 06:00:00 mchyzer Exp $ */ package edu.upenn.isc.clusterLinuxClc; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import edu.internet2.middleware.grouper.app.loader.GrouperLoaderConfig; import edu.internet2.middleware.grouper.changeLog.ChangeLogConsumerBase; import edu.internet2.middleware.grouper.changeLog.ChangeLogEntry; import edu.internet2.middleware.grouper.changeLog.ChangeLogLabels; import edu.internet2.middleware.grouper.changeLog.ChangeLogProcessorMetadata; import edu.internet2.middleware.grouper.changeLog.ChangeLogTypeBuiltin; import edu.internet2.middleware.grouper.util.GrouperUtil; import edu.internet2.middleware.grouper.xmpp.XmppConnectionBean; /** * */ public class ClusterLinuxChangeLogConsumer extends ChangeLogConsumerBase { /** */ private static final Log LOG = GrouperUtil.getLog(ClusterLinuxChangeLogConsumer.class); /** * @see edu.internet2.middleware.grouper.changeLog.ChangeLogConsumerBase#processChangeLogEntries(java.util.List, edu.internet2.middleware.grouper.changeLog.ChangeLogProcessorMetadata) */ @Override public long processChangeLogEntries(List<ChangeLogEntry> changeLogEntryList, ChangeLogProcessorMetadata changeLogProcessorMetadata) { long currentId = -1; XmppConnectionBean xmppConnectionBean = null; String recipient = null; //identifies which config is running, multiple could be running String consumerName = changeLogProcessorMetadata.getConsumerName(); String grouperFolderBase = null; { String grouperFolderBaseConfigName = "changeLog.consumer." + consumerName + ".clusterLinux.grouperFolderBase"; grouperFolderBase = GrouperLoaderConfig.getPropertyString(grouperFolderBaseConfigName, true); } for (ChangeLogEntry changeLogEntry : changeLogEntryList) { //try catch so we can track that we made some progress try { currentId = changeLogEntry.getSequenceNumber(); boolean sendMessage = false; //this might be a little aggressive, but basically if a permission or member changes in the clusterLinux folder of //grouper then send a refresh message if (changeLogEntry.equalsCategoryAndAction(ChangeLogTypeBuiltin.PERMISSION_ADD) || changeLogEntry.equalsCategoryAndAction(ChangeLogTypeBuiltin.PERMISSION_DELETE)) { String permissionName = changeLogEntry.retrieveValueForLabel(ChangeLogLabels.PERMISSION_ADD.attributeDefNameName); if (permissionName != null && permissionName.startsWith(grouperFolderBase)) { sendMessage = true; } LOG.debug("Processing changeLog #" + currentId + ", permissionName: " + permissionName + ", grouperFolderBase: " + grouperFolderBase + ", message: " + changeLogEntry.getChangeLogType().getChangeLogCategory() + "." + changeLogEntry.getChangeLogType().getActionName() + ", sendMessage: " + sendMessage ); } else if (changeLogEntry.equalsCategoryAndAction(ChangeLogTypeBuiltin.MEMBERSHIP_ADD) || changeLogEntry.equalsCategoryAndAction(ChangeLogTypeBuiltin.MEMBERSHIP_DELETE) || changeLogEntry.equalsCategoryAndAction(ChangeLogTypeBuiltin.MEMBERSHIP_UPDATE)) { String roleName = changeLogEntry.retrieveValueForLabel(ChangeLogLabels.MEMBERSHIP_ADD.groupName); if (roleName != null && roleName.startsWith(grouperFolderBase)) { sendMessage = true; } LOG.debug("Processing changeLog #" + currentId + ", roleName: " + roleName + ", grouperFolderBase: " + grouperFolderBase + ", message: " + changeLogEntry.getChangeLogType().getChangeLogCategory() + "." + changeLogEntry.getChangeLogType().getActionName() + ", sendMessage: " + sendMessage ); } else if (StringUtils.equals("permission", changeLogEntry.getChangeLogType().getChangeLogCategory()) && StringUtils.equals("permissionChangeOnRole", changeLogEntry.getChangeLogType().getActionName())) { //note, this is 2.1+ String roleName = changeLogEntry.retrieveValueForLabel("roleName"); if (roleName != null && roleName.startsWith(grouperFolderBase)) { sendMessage = true; } LOG.debug("Processing changeLog #" + currentId + ", roleName: " + roleName + ", grouperFolderBase: " + grouperFolderBase + ", message: " + changeLogEntry.getChangeLogType().getChangeLogCategory() + "." + changeLogEntry.getChangeLogType().getActionName() + ", sendMessage: " + sendMessage ); } else { LOG.debug("Processing changeLog #" + currentId + ", " + changeLogEntry.getChangeLogType().getChangeLogCategory() + "." + changeLogEntry.getChangeLogType().getActionName() + ", sendMessage: " + sendMessage ); } //is there something to send? if (sendMessage) { String message = "Update permissions"; if (xmppConnectionBean == null) { recipient = GrouperLoaderConfig.getPropertyString("changeLog.consumer." + consumerName + ".publisher.recipient", ""); String xmppServer = GrouperLoaderConfig.getPropertyString("xmpp.server.host"); int port = GrouperLoaderConfig.getPropertyInt("xmpp.server.port", -1); String username = GrouperLoaderConfig.getPropertyString("xmpp.user", ""); String password = GrouperLoaderConfig.getPropertyString("xmpp.pass", ""); String resource = GrouperLoaderConfig.getPropertyString("xmpp.resource", ""); xmppConnectionBean = new XmppConnectionBean(xmppServer, port, username, resource, password); } xmppConnectionBean.sendMessage(recipient, message); } } catch (Exception e) { //we unsuccessfully processed this record... decide whether to wait, throw, ignore, log, etc... LOG.error("problem with id: " + currentId, e); changeLogProcessorMetadata.setHadProblem(true); changeLogProcessorMetadata.setRecordException(e); changeLogProcessorMetadata.setRecordExceptionSequence(currentId); //stop here return currentId; //continue } } return currentId; } }
Build that consumer into a jar:
<project name="clusterLinux" default="build" basedir="."> <!-- declare the ant-contrib tasks --> <taskdef resource="net/sf/antcontrib/antlib.xml" /> <!-- copy build.properties if not there already --> <if><not><available file="build.properties" /></not> <then><copy file="build.example.properties" tofile="build.properties" /></then> </if> <!-- Grouper Global Build Properties --> <property file="${basedir}/build.properties"/> <target name="build" description="full build" depends="init,clean,compile,jarPrepare,jar"> </target> <target name="init"> <tstamp /> <property name="main.sourceChangeLogDir" value="../sourceChangeLogConsumer" /> <property name="main.lib" value="../lib" /> <property name="main.binChangeLogDir" value="../dist/binChangeLog" /> <property name="main.outputDir" value="../dist" /> <property name="main.appName" value="clusterLinux" /> <property name="main.jarFileChangeLog" value="${main.outputDir}/${main.appName}ChangeLog.jar" /> <path id="main.changeLogClasspath"> <fileset dir="${main.lib}"> <include name="**/*.jar" /> </fileset> <fileset file="${grouper.jar.location}" /> </path> </target> <target name="clean" depends="init"> <mkdir dir="${main.binChangeLogDir}" /> <delete dir="${main.binChangeLogDir}" /> <mkdir dir="${main.binChangeLogDir}" /> </target> <target name="compile"> <mkdir dir="${main.outputDir}" /> <mkdir dir="${main.binChangeLogDir}" /> <javac target="1.6" srcdir="${main.sourceChangeLogDir}" destdir="${main.binChangeLogDir}" debug="true" > <classpath refid="main.changeLogClasspath" /> </javac> </target> <target name="jarPrepare"> <mkdir dir="${main.binChangeLogDir}" /> <copy todir="${main.binChangeLogDir}"> <fileset dir="${main.sourceChangeLogDir}"> <include name="**/*.java"/> <!-- source --> </fileset> </copy> <mkdir dir="${main.binChangeLogDir}/clusterLinux" /> <copy todir="${main.binChangeLogDir}/clusterLinux" file="build.xml" /> </target> <target name="jar"> <tstamp> <format property="the.timestamp" pattern="yyyy/MM/dd HH:mm:ss" /> </tstamp> <jar jarfile="${main.jarFileChangeLog}" duplicate="fail"> <fileset dir="${main.binChangeLogDir}" /> <manifest> <attribute name="Built-By" value="${user.name}"/> <attribute name="Implementation-Vendor" value="Penn"/> <attribute name="Implementation-Title" value="clusterLinuxChangeLog"/> <attribute name="Build-Timestamp" value="${the.timestamp}"/> </manifest> </jar> <echo message="Output is: ${main.jarFileChangeLog}" /> </target> </project>
If you want to log the change log, add this to the log4j.properties:
log4j.logger.edu.upenn.isc.clusterLinuxClc.ClusterLinuxChangeLogConsumer = DEBUG
sdf