You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

Draft, not quite implemented

ActiveMQ is an open source application messaging middleware service where applications can send messages to other applications (or groups of consumers) in real-time without polling.

Grouper can be used to manage ActiveMQ authorizations. University of Pennsylvania and Penn State are interested in this component.

ActiveMQ users can send/receive messages to topics/queues, and also can dynamically create topics/queues. Grouper permissions can be exported and kept in sync (cron'ed and real-time) with a local permissions store. An ActiveMQ plugin reads the local permissions and enforces the rules.

The Grouper-ActiveMQ component is a jar that you can add to the ActiveMQ system (along with a few other jars), and some configuration that allows authorization managed from Grouper.

Architecture

grouperActivemqArchitecture

Authentication

If you want to authenticate to ActiveMQ with kerberos service principal user/pass, there is a plugin in this Grouper-ActiveMQ component.  Configure in the activemq.xml

    <plugins>
       <!-- ATTENTION! AUTHN MUST BE BELOW AUTHZ!!! -->
       <bean xmlns="http://www.springframework.org/schema/beans" 
          id="kerberosPlugin" 
          class="edu.internet2.middleware.grouperActivemq.GrouperBrokerPlugin" />
      
    </plugins>

Configure kerberos authentication in grouper.activemq.properties:

########################################
## KERBEROS settings, only needed if doing kerberos auth
########################################

# number of minute to cache successful logins
kerberos.login.cache.success.minutes = 5

# number of minute to cache failed logins
kerberos.login.cache.failed.minutes = 1

Configure the krb5.conf (in classpath)

[libdefaults]
    default_realm = UPENN.EDU
    default_tkt_enctypes = des3-hmac-sha1 des-cbc-crc
    default_tgs_enctypes = des3-hmac-sha1 des-cbc-crc

[realms]
    UPENN.EDU = {
        kdc = kerberos1.upenn.edu
        kdc = kerberos2.upenn.edu
        kdc = kerberos3.upenn.edu
        admin_server = kerberos1.upenn.edu
    }

Getting started

  • This is developeed with Grouper 2.1, and ActiveMQ 5.7
  • Check out the Grouper ActiveMQ component: http://anonsvn.internet2.edu/viewvc/viewvc.py/i2mi/branches/GROUPER_2_1_BRANCH/grouper-misc/grouperActivemq/
  • Build into a jar
  • Copy to the ActiveMQ library path: grouperActivemq.jar, grouperClient.jar, smack.jar, quartz.jar, commons-logging.jar, ezmorph.jar, json-lib.jar, jta.jar, 
  • Copy to the ActiveMQ classpath: grouper.activemq.base.properties, goruper.activemq.properties, grouper.client.example.properties, grouper.client.properties, krb5.conf (if applicable), morphString.example.properties (if applicable), morphString.properties (if applicable), jass.conf (if applicable)
  • Configure the Grouper-ActiveMQ connector in the activemq.xml
    <plugins>
       <bean xmlns="http://www.springframework.org/schema/beans" 
          id="grouperPlugin" 
          class="edu.internet2.middleware.grouperActivemq.GrouperBrokerPlugin" />
    </plugins>

Configuration

Create a role (or some roles) in Grouper which are used for ActiveMQ users.

Create a permission definition (or definitions if you are delegating) that are used for ActiveMQ permissions.

Make sure all ActiveMQ permission definitions have these actions:  

/** send a message */
  sendMessage,
  
  /** send a message on this destination or sub destinations */
  sendMessageInherit,
  
  /** receive a message */
  receiveMessage,
  
  /** receive a message on this destination or sub destinations */
  receiveMessageInherit,
  
  /** create a queue/topic in this destination or somewhere under this destination */
  createDestination,
  
  /** delete a queue/topic in this destinate or somewhere under this destination */
  deleteDestination;

Note: you can specify a root folder in Grouper where permissions must be in, and the root folder can be prefix which is removed from the destination name.

Configure the grouper.activemq.properties

#
# Grouper activemq configuration
#

# The grouper activemq plugin uses Grouper Configuration Overlays (documented on wiki)
# By default the configuration is read from grouper.activemq.base.properties
# (which should not be edited), and the grouper.activemq.properties overlays
# the base settings.  See the grouper.activemq.base.properties for the possible
# settings that can be applied to the grouper.activemq.properties

########################################
## Config chaining hierarchy
########################################

# comma separated config files that override each other (files on the right override the left)
# each should start with file: or classpath:
# e.g. classpath:grouper.client.example.properties, file:c:/something/myconfig.properties
grouperActivemq.config.hierarchy = classpath:grouper.activemq.base.properties, classpath:grouper.activemq.properties

# seconds between checking to see if the config files are updated
grouperActivemq.config.secondsBetweenUpdateChecks = 60

########################################
## KERBEROS settings, only needed if doing kerberos auth
########################################

# number of minute to cache successful logins
kerberos.login.cache.success.minutes = 5

# number of minute to cache failed logins
kerberos.login.cache.failed.minutes = 1


#########################################
## Permissions settings
#########################################

# prefix for permissions which will be stripped when translating to destination
# if there is nothing specified, then the queue's/topic's are fully qualified in PennGroups
# Note: if you put something in here, you cant easily remove it later...
grouperActivemq.folderPrefix = 

# all permissions for activemq must be in this folder
grouperActivemq.requireBaseFolder = 

# list all the permission definitions (comma separated) in Grouper where the destinations are specified
# this is a required field.  Note, the actions must exactly match up with GrouperActivemqPermissionAction
grouperActivemq.permissionDefinitions = 

# directory on activemq machine which has two cached file for the activemq permissions files:
# activemqGrouperPermissions.1.properties, and activemqGrouperPermissions.2.properties
grouperActivemq.permissionsCacheDirectory = 

# the roles that users of activemq must have permissions in, comma separated
grouperActivemq.roleNames = 

# subject sources that should be pulled for permissions.  i.e. which subjects can have permissions in 
# activemq, and what subject attribute is their login id for activemq.  Increment the number for more entries
# they must be sequential
grouperActivemq.subjectSource.0.sourceId = 
grouperActivemq.subjectSource.0.subjectAttributeForLogin = 

# grouperActivemq.subjectSource.1.sourceId = 
# grouperActivemq.subjectSource.1.subjectAttributeForLogin = 

# generally run this every night since real time will run every day
grouperActivemq.fullRefreshQuartzCron = 0 0 7 * * ?


 

Broker plugin example

If you have an implementation of Broker:

/**
 * @author mchyzer $Id$
 */
package edu.upenn.isc.activemq;

import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerFilter;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.broker.ProducerBrokerExchange;
import org.apache.activemq.broker.region.Destination;
import org.apache.activemq.broker.region.Subscription;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ConsumerInfo;
import org.apache.activemq.command.DestinationInfo;
import org.apache.activemq.command.Message;
import org.apache.activemq.command.ProducerInfo;

/**
 * my broker
 */
public class MyBroker extends BrokerFilter {

  /**
   * @param next1
   */
  public MyBroker(Broker next1) {
    super(next1);

  }
  
  /**
   * @see org.apache.activemq.broker.BrokerFilter#addDestinationInfo(org.apache.activemq.broker.ConnectionContext, org.apache.activemq.command.DestinationInfo)
   */
  @Override
  public void addDestinationInfo(ConnectionContext context, DestinationInfo info)
      throws Exception {
    System.out.println("addDestinationInfo: ");
    super.addDestinationInfo(context, info);
  }

  /**
   * @see org.apache.activemq.broker.BrokerFilter#addDestination(org.apache.activemq.broker.ConnectionContext, org.apache.activemq.command.ActiveMQDestination, boolean)
   */
  @Override
  public Destination addDestination(ConnectionContext context,
      ActiveMQDestination destination, boolean create) throws Exception {
    System.out.println("addDestination: ");
    return super.addDestination(context, destination, create);
  }

  /**
   * @see org.apache.activemq.broker.BrokerFilter#removeDestination(org.apache.activemq.broker.ConnectionContext, org.apache.activemq.command.ActiveMQDestination, long)
   */
  @Override
  public void removeDestination(ConnectionContext context,
      ActiveMQDestination destination, long timeout) throws Exception {

    System.out.println("removeDestination: ");
    super.removeDestination(context, destination, timeout);
  }

  /**
   * @see org.apache.activemq.broker.BrokerFilter#addConsumer(org.apache.activemq.broker.ConnectionContext, org.apache.activemq.command.ConsumerInfo)
   */
  @Override
  public Subscription addConsumer(ConnectionContext context, ConsumerInfo info)
      throws Exception {

    System.out.println("addConsumer: ");
    return super.addConsumer(context, info);
  }
  
  /**
   * @see org.apache.activemq.broker.BrokerFilter#addProducer(org.apache.activemq.broker.ConnectionContext, org.apache.activemq.command.ProducerInfo)
   */
  @Override
  public void addProducer(ConnectionContext context, ProducerInfo info) throws Exception {

    System.out.println("addProducer: ");
    super.addProducer(context, info);
  }

  /**
   * 
   * @see org.apache.activemq.broker.BrokerFilter#send(org.apache.activemq.broker.ProducerBrokerExchange, org.apache.activemq.command.Message)
   */
  @Override
  public void send(ProducerBrokerExchange producerExchange, Message messageSend)
      throws Exception {
    System.out.println("send: ");
    super.send(producerExchange, messageSend);
  }

}

And you have an implementation for BrokerPlugin:

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.upenn.isc.activemq;

import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerPlugin;

/**
 * An authorization plugin where each operation on a destination is checked
 * against an authorizationMap
 * 
 * @org.apache.xbean.XBean
 * 
 * 
 */
public class MyBrokerPlugin implements BrokerPlugin {

    public MyBrokerPlugin() {
    }

    public Broker installPlugin(Broker broker) {
        return new MyBroker(broker);
    }

}

Then you can register the broker in the activemq.xml (add above <transportConnectors>

    <plugins>
       <bean xmlns="http://www.springframework.org/schema/beans" 
          id="myBrokerPlugin" 
          />
      
    </plugins>

sdf

  • No labels