Author Archives: Matt Vincent

4 Ways to Launch Docker Containers

Introduction

Amazon just announced general availability of their Elastic Container Service providing a platform for launching Docker images in the cloud.  Let’s say your team is developing software on Windows and Mac OSX, but Docker requires the Linux kernel’s virtualization features to work. By now, you have likely discovered that Vagrant and/or boot2docker provide nice ways to run Linux on your local PC or Mac and provide a docker deployment platform.

But with so many different options available to configure how your Docker containers talk to each other, how do you get started?  In this article, we will take a look at a basic set of containers needed to stand up your own Docker registry (a must if you want to share your images in a place other than the public docker.io or paid private quay.io) and look at four different ways to launch your containers: 

Continue reading

Aggregate MyBatis.NET SqlMaps from Multiple C# Projects

Summary

This blog post describes an approach for integrating Spring.NET and MyBatis.NET in a way that lets iBATIS aggregate SqlMap config files from multiple assemblies (a.k.a. assembly scanning) prior to handing out ISqlMapper instances. Teams setting up new MyBatis.NET/Spring.NET tech stacks might find this useful.

Continue reading

The Easiest Way to Organize Zimbra Email

If you’re like me, receiving 30-40 emails is par for the day. Because Source Allies provides consulting services for companies wishing to implement or better take advantage of Zimbra, it is also the mail server we use at our company. Zimbra has incredible search capabilities, but my OCD tendencies still require that my email is nicely filed away in it’s designated folder. However, if statisticians say we spend an average of 3 years of our lives waiting at red stop lights, I certainly don’t want to spent that much time or more, dragging emails from my inbox into my IMAP folders.

This blog post lets you manage all of your email in OCD detail, with just (2) keyboard shortcuts: u and s. Continue reading

Spring Roo Sample App Tutorial – Part 1

In this blog, I will start creating a web application used to organize bookmarks. Because only certain bookmarks are of interest to specific groups of people, I will use groups in our LDAP server to control which users see which groups of bookmarks.

The entire blog will be released in posts staggered over time. Part 1 will focus on initial setup of Roo, the core web application and authentication with a directory server. Subsequent posts will refine the Spring Roo application.

What is Roo?

It’s a great rapid prototyping tool because prototypes don’t need to be scrapped to proceed with fleshing out the application if a prototype proves itself.

Roo gives you Spring best practices, Rails-like scaffolding, an interactive shell, no additional run-time dependencies, and a big productivity boost while not locking you into yet another framework. You can re-use your existing Spring/JPA/Hibernate knowledge, while getting the productivity gains from Roo.

Setting up Roo

  • wget http://s3.amazonaws.com/dist.springframework.org/milestone/ROO/spring-roo-1.0.0.RC3.zip
  • unzip spring-roo-1.0.0.RC3.zip
  • sudo ln -s ~/Frameworks/spring-roo-1.0.0.RC3/bin/roo.sh /usr/bin/roo
  • mkdir ~/Workspaces/intranetlinks; cd ~/Workspaces/intranetlinks

Starting our Project

Once in your new project directory, type ‘roo’. Then once in the Roo shell, execute these commands. See this guide for an explanation of what these commands do:

project --topLevelPackage com.sourceallies.links
persistence setup --provider HIBERNATE --database MYSQL
database properties set --key database.password --value password
database properties set --key database.username --value username
database properties set --key database.url --value jdbc:mysql://localhost:3306/intranetlinks
 
entity --name ~.domain.LinkCategory
field string name --notNull --sizeMin 1 --sizeMax 255
 
entity --name ~.domain.Link
field string name --notNull --sizeMin 1 --sizeMax 60
field string url --notNull --sizeMin 1 --sizeMax 255
field string ldapSecurityGroup --notNull --sizeMin 1 --sizeMax 60
field reference --class ~.domain.Link --fieldName category --type ~.domain.LinkCategory
 
logging setup --level DEBUG
 
controller scaffold --name ~.web.LinkCategoryController --entity ~.domain.LinkCategory
controller scaffold --name ~.web.LinkController --entity ~.domain.Link
 
finder list --class com.sourceallies.links.domain.Link
finder add --finderName findLinksByCategory --class ~.domain.Link
 
security setup
test integration
perform test
perform eclipse

Then of course, create your local database inside the MySQL shell:

create database intranetlinks;
create user 'username'@'localhost' IDENTIFIED BY 'password';
grant all privileges on intranetlinks.* to 'username'@'localhost' with grant option;

Next, unless you’re using Roo 1.0.0.RC4 (not available at the time of this blog post), you’ll need to add the following config to near the bottom of your pom.xml (to fix this bug).

<profiles>
       <profile>
 <id>jaxb</id>
       <activation>
            <jdk>1.5</jdk>
        </activation>
        <dependencies>
               <dependency>
                    <groupId>javax.xml.bind</groupId>
                    <artifactId>jaxb-api</artifactId>
                    <version>2.1</version>
                </dependency>
               <dependency>
                    <groupId>com.sun.xml.bind</groupId>
                    <artifactId>jaxb-impl</artifactId>
                    <version>2.1.3</version>
                </dependency>
         </dependencies>
  </profile>
</profiles>

Then pull the JAXB JAR into your build by executing this maven command (outside of the Roo shell):

mvn package clean

Finally, per a prior blog, replace the body of your src/main/resources/META-INF/spring/applicationContext-security.xml with this:

    <http>
    	<form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
        <logout logout-url="/static/j_spring_security_logout"/>
        <intercept-url pattern="/admin/**" access="ROLE_ADMIN"/>
        <intercept-url pattern="/member/**" access="IS_AUTHENTICATED_REMEMBERED" />
        <intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/static/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/images/**" filters="none" />
        <intercept-url pattern="/styles/**" filters="none" />
	<intercept-url pattern="/link/form" access="ROLE_INTRANETLINKS-ADMINS" />
	<!-- We're doing REST, only allow GETs to normal users -->
    	<intercept-url pattern="/link/**" access="ROLE_INTRANETLINKS-ADMINS" method="DELETE"/>
    	<intercept-url pattern="/link/**" access="ROLE_INTRANETLINKS-ADMINS" method="POST"/>
    	<intercept-url pattern="/link/**" access="ROLE_INTRANETLINKS-ADMINS" method="PUT"/>
        <intercept-url pattern="/link/**" access="IS_AUTHENTICATED_REMEMBERED" />
        <intercept-url pattern="/login/**" filters="none" />
	<intercept-url pattern="/**" access="ROLE_USERS"  />
	 <anonymous /> 
    </http>
 
    <ldap-server id="ldapServer" url="ldap://yourdirectoryserver:338899/" />
 
   <authentication-manager>
    <ldap-authentication-provider server-ref="ldapServer"  
       user-search-base="ou=people,dc=sourceallies,dc=com" 
       user-search-filter="(uid={0})"
       group-role-attribute="cn"
       group-search-base="ou=groups,dc=sourceallies,dc=com"
       group-search-filter="(memberUid={1})"
       role-prefix="ROLE_" />
   </authentication-manager>

Note that in Spring Security 3.0, Authentication Providers must now be declared from within the authentication-manager element (more information here).

Then add a few more dependencies to your pom.xml

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>org.springframework.security.ldap</artifactId>
        <version>3.0.0.RC1</version>
    </dependency>
 
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-core</artifactId>
        <version>1.3.0.RELEASE</version>
    </dependency>
 
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-core-tiger</artifactId>
        <version>1.3.0.RELEASE</version>
    </dependency>

This will allow you to use Spring LDAP and also conditionally render pieces of your application like this:

<security:authorize ifAllGranted="ROLE_SUPERVISOR">
    <li id="finder_findlinksbycategory_menu_item">
        <c:url value="/link/find/ByCategory/form" var="finder_findlinksbycategory_menu_item_url"/>
        <a href="${finder_findlinksbycategory_menu_item_url}">
            <spring:message arguments="Category" code="global.menu.find"/>
        </a>
    </li>
</security:authorize>

Finally, run the following command to startup Tomcat and start refining your UI.

mvn tomcat:run

Stay tuned for Part 2 of this series!

Spring LDAP Group Authorization Tip

The folks at Spring have made it extremely easy to allow your application authenticate and authorize users with Spring LDAP. This blog entry explains how to check your directory structure and use some sparsely documented Spring LDAP parameters ({0} and {1}) to get everything working.

In your Spring Security configuration, pointing to your directory is straight forward:

 <ldap-server id="ldapServer" url="ldap://dir.yourdomain.com:389/" />

But in configuring the ldap-authentication-provider, you need to know a few things about your directory of course! We recommend using Apache Directory Studio to browse your directory – it’s a fantastic application.

If you’re more of a command-line person, just use ldapsearch (example below):

ldapsearch -H ldap://dir.yourdomain.com:389 -ZZ -x 
-D "cn=AdminUser,dc=yourdomain,dc=com" -W -b "cn=users,ou=groups,dc=yourdomain,dc=com" 
-s base -a always "(objectClass=*)" "*"

Once connected to your directory, you’ll need to figure out how your groups are configured. Specifically, you’ll want to know if your configuration looks like

Example A:

  • dc=yourdomain,dc=com
    • ou=groups
      • cn=users
        • memberUid=USERNAME

or Example B:

  • dc=yourdomain,dc=com
    • ou=groups
      • cn=users
        • memberUid=uid= USERNAME,ou=people,dc= yourdomain,dc=com

If it’s like Example A, you’ll want your config like this:

<ldap-authentication-provider server-ref="ldapServer"  
	user-search-base="ou=people,dc=yourdomain,dc=com" 
	user-search-filter="(uid={0})"
	group-role-attribute="cn"
	group-search-base="ou=groups,dc=yourdomain,dc=com"
	group-search-filter="(memberUid={1})"
	role-prefix="ROLE_" />

otherwise, you’ll want this config:

<ldap-authentication-provider server-ref="ldapServer"  
	user-search-base="ou=people,dc=yourdomain,dc=com" 
	user-search-filter="(uid={0})"
	group-role-attribute="cn"
	group-search-base="ou=groups,dc=yourdomain,dc=com"
	group-search-filter="(memberUid={0})"
	role-prefix="ROLE_" />

Note the difference in the group-search-filter:

  • {0} contains the username with the entire ldap base.
  • {1} only contains username.

Open Source Enterprise Search

Has locating information across a multitude of systems on your corporate network finally made you consider an enterprise search appliance?

Our company has a number of systems in place designed to capture corporate knowledge and subject matter expertise.  Once it became too time consuming to find information across these systems (and we struck out with demos of search appliances like SearchBlox), we purchased the entry level Google Mini.  We’ve been happy with the appliance, but wanted to search more information formats (beyond digest authenticated SSL web pages and SMB shares), authenticate to our central authentication system (not LDAP), and introduce additional security levels.  (Word stemming would be nice too!)  To avoid the costs of graduating to Google Search Appliances, (and creating an internal Source Allies project to front end the Google Mini XML responses with some custom XSLT), we looked to open source again.

The trend towards enterprise search consolidation (Autonomy acquiring Interwoven for $775M, Microsoft offering $1.2B for FAST) has been interrupted by strong open source Lucene-based products like Nutch and Solr.  They have broken the enterprise search market segment wide open again.  Nutch provides basic web & file system crawling search appliance functionality and Solr gives us the ability to infused structured data into the same underlying Lucene index.

Lucene Logo Apache SolrApache Nutch

We decided to implement these technologies into our company network.  In our environment, the Nutch and Solr indexes are updated on a regular basis.  We use Nutch to index unstructured data such as our intranet, wikis, blogs and subversion document repositories.  Solr indexes structured data such as our corporate CRM application – a SugarCRM instance.  (Incidentally, we use a separate product called OpenGROK to index our subversion source code repositories).  Because both Nutch and Solr are both open source, it was very simple tie them into our single-sign-on system (front-ending them with our CAS server).  — Stay tuned for a follow-up blog highlighting the technical details of our configuration.

Ultimately, Nutch and Solr are going to provide our company with a more flexible enterprise search solution, but the solution is not without its fair share of Lucene/Nutch/Solr expertise to make it all happen.  Now that we have commodity cloud computing, Hadoop Map/Reduce, structured and unstructured indexing tools on top of Lucene, I’m anxious to see what the open source community will do next in the enterprise search space.   It doesn’t seem to far off to have an appliance that will do the normal Nutch/Goole Mini web and SMB share crawling, but also actively update the index with corporate collaboration (shared email/group chat/social media/RSS/wave protocol/video transcribing/forums/KM systems/custom SQL queries).  Of course all of this is currently possible with Solr/Nutch and even Google Mini’s OneBox modules, but who will be the first to make it really easy to setup?