Search This Blog

Thursday, August 5, 2010

Atlassian Stack: FishEye (auto start)

Today's ticket is to rig up FishEye so that it starts at boot time.  I scoured the FishEye docs and googled but came up empty.  There is a Mac OS X solution and one for an older version of FishEye and CentOS.  Nothing for Karmic Koala.  My solution?  Emulate what was done for Jira.  I copied /etc/init/jira.conf and created /etc/init/fisheye.conf.  My resulting file looks like this:
# fisheye

description     "Atlassian FishEye - Source control viewer"

start on runlevel [2345]
stop on runlevel [!2345]

kill timeout 30

env RUN_AS_USER=fisheye
env BASEDIR=/opt/fisheye

    LOGFILE=$BASEDIR/fisheye.out.`date +%Y-%m-%d`.log
    exec su - $RUN_AS_USER -c "$BASEDIR/bin/" >> $LOGFILE 2>&1
end script

The solution does not appear to be perfect, however.  If I issue sudo service jira stop, I get this: jira stop/waiting.  If I issue sudo service fisheye stop, I get this:  stop: Unknown instance.  Not good. I don't want to just kill the process when I shutdown the box.  Who knows what type of data corruption will occur?  I need to figure out what is wrong with my script and fix it.  One difference is that the other Atlassian pieces bundle their own copy of Tomcat and that is what we invoke in the start scripts.  FishEye uses something else. 

I googled about Upstart and decided that I won't ever fully understand how it works.  So, I've decide to make two upstart scripts.  One that controls starting up FishEye and boot time (fisheye-start.conf) and one that controls shutting down FishEye during shutdown (fisheye-stop.conf).  Perhaps not the most elegant solution but it appears to work.  All I'm doing is calling in one and in the other.  Nothing fancy.

How Do I Use Spring Security To Secure Spring MVC and Spring BlazeDS In The Same Application?

Context: I have a single web application that is based on Spring 3.  It serves up RESTful resources using the new Spring MVC annotations and it works fine.  After some head scratching and research, I finally figured out the configuration required to lock down the Spring MVC calls with Digest Authentication via Spring Security 3.  I then wanted the ability to provide access to the same set of services to our Flex clients using AMF so I added Spring BlazeDS Integration to the mix.  Remoting a service via Spring is almost trivial.  Add an annotation or two and you are good to go.  Adding security to the mix is almost as easy.  If you follow the directions on how to lock down your AMF channels, it'll work fine.  The problem I ran into is that set of security filters set up by the Spring BlazeDS Integration directions interfere with the set of filters needed by Spring MVC.  The solution?  Watch things in the debugger in a working environment, reverse engineer the required filters for Spring BlazeDS and then specify them by hand in your Spring Security set up.  Spring Security uses a chain of filters to apply authentication logic to servlets.  Spring MVC and Spring BlazeDS get their own instance of DispatcherServlet in the application.  You then apply the required filters to the appropriate servlet.  My solution was to break up the Spring Security beans into three files:

  • common-security-context.xml - holds beans that are common to both Spring MVC and Flex authentication
  • mvc-security-context.xml - holds the beans specific to authentication of the RESTful API
  • flex-security-context.xml - holds the beans specific to authentication of the BlazeDS calls
What you should end up with is the ability to invoke the service in two ways: one as a RESTful resource and one as a Flex Remote Object.  In each case, providing the same set of credentials should authenticate you.  In summary, relying on the Spring Security namespace to set up your security environment does not work if you are combining Flex and Digest authentication: you need to set things up by hand.

Here are my versions of the files in question.  I hope that it saves you some time and effort.


Monday, August 2, 2010

Atlassian Stack: FishEye

Today's mission: install FishEye, the source control repository analysis tool. Quoting the online docs: "FishEye unlocks Subversion, Git, Perforce, Clearcase, CVS, and Mercurial with real-time notifications of code changes plus web-based reporting, visualisation, search and code sharing." I'll be installing 2.3.5 Standalone edition.

  1. create a new user account and group named fisheye
  2. add the fisheye account to the subversion group -- it needs read only access to the Subversion repository 
  3. extract the fisheye zip into /opt
  4. make a softlink from the new installation directory to /opt/fisheye
  5. change ownership of the installation directory over to fisheye:fisheye.
  6. mkdir /opt/fisheye-home
  7. change ownership over to the fisheye account
  8. export FISHEYE_INST in /etc/environment so that it points to /opt/fisheye-home
  9. copy /opt/fisheye/config.xml to /opt/fisheye-home
  10. logged out and then back into the account to make sure that the environment variable was set correctly
  11. as the fisheye account, start fisheye: sudo -u fisheye /opt/fisheye/bin/
  12. connect to http://localhost:8060/ and run through the wizard
  13. had to do something odd, in order to get the server id I had to start with the "obtain evaluation license" option and then back out and do the "enter existing license option"
  14. Added the Subversion repository by specifying svn://localhost/opt/svn
The initial installation is done.  Next step, integrate it with the rest of the stack.

Friday, July 30, 2010

Spring Security 3 and Digest Authentication

This was a tough one so I thought I'd take a few moments and share what I found.  Context: I'm using Spring 3 as the basis for a set of RESTful services.  The new MVC enhancements makes supporting a RESTful API pretty simple.  What I wanted to do what to lock down the API a bit and turned to Spring Security 3 to make that happen.  Not wanting to enable HTTPS, at least not yet, I turned to Digest Authentication which provides a reasonable authentication mechanism without having to hassle with digital certificates.  Getting Spring Security enabled and, at least initially, authenticating with Basic Authentication was a breeze.  Once I tried to enable Digests Authentication, things got weird.

 Luckily, I was able to locate two resources that steered me down the correct path.  One is the book, Spring Security 3 and another was an article on DZone titled "Using Spring Security to Enforce Authentication and Authorization on Spring Remoting Services Invoked From a Java SE Client".   The upshot is that you cannot rely on the simple namespace configuration that is almost always talked about in the Spring Security 3 literature.  It assumes a JSP type of environment with form login screens et al.  In my case, I'm using just enough of the web stack to allow for HTTP based manipulation of the server-side resource -- no gui.  This means you have to configure things by hand so it'll suit your needs.   Here is the Spring context file I used to enable Digest Authentication for my RESTful services.

Since this was a prototype, I'm relying on the in-memory credential store but you should be able to wire up some more suitable for a production environment.  What I wanted to do was to authenticate at the web layer but authorize at the services layer.  The authentication is handled by the Digest Authentication pieces and the authorization is handled by annotations in service interfaces.  For example:
public interface EchoPort
    @PreAuthorize( "hasRole( 'ROLE_ADMIN' )" )
    EchoResponse echoMessage( final EchoRequest request ) throws EchoError;

I used Apache HttpClient 4.0.1 for testing and was pleasantly surprised to find that it handled both Basic and Digest authentication for me.  All I had to do was to provide the credentials prior to making the call the HttpClient handled the rest.

theClient.getCredentialsProvider().setCredentials( AuthScope.ANY, new UsernamePasswordCredentials( defaultUserName, defaultPassword ) );

I hope this saves you a bit of time.

Thursday, July 29, 2010

Atlassian Stack: Confluence (integration)

Today's goal is to integrate Confluence with Jira and Crowd.  In the Jira admin doc I found a section on integrating Jira and Confluence.  I'll run through that.

  • configured quick search to point back to the Jira URL
  • configured track back, had to also go into Jira
  • user Confluence gadgets in Jira (I those to use trusted applications instead of oauth). I had to configure trusted application on both the Jira and Confluence sides.  After reading the instructions, it became clear that adding gadgets would be a pain -- you have to add them individually.  I've decided to add gadgets only when/if I decide they might be useful.  Enabled the atlassian-gadgest-shared plugin in Confluence
  • enable Jira linker plugin by entering the download URL of the plugin into the Confluence plugin manager screen
  • after a bit of searching I found the Confluence section that describes how to integrate Confluence into Crowd. I did not build a new directory.  I just reused the one I made for Jira instead.  I made the required confluence groups and made one of the users a member of both groups.  copied the jar files and edited the configuration files as instructed. restarted confluence.  Logged in with a crowd user and enabled External user management so that you have to manage users via Crowd.
  • add the "userful extendsions" described in the instructions.  Of the 3 suggested, I could only install the Jira Confluence portlet because the other two wanted me to authenticate for access to accounts I don't have.  Oh, we..
Not as a clean integration as I would've liked. Much of it appears to be plugin driven, which have to install yourself.

Wednesday, July 28, 2010

Atlassian Stack: Confluence (auto-start)

I had to search on "confluence auto start" to find the page that describes how to auto start Confluence under Linux.  Like the other products, the note from Daniel Harvey describing how to configure things for Karmic are the steps you want to follow.  Make sure to make adjustments based on the link so that Crowd starts before Jira or Confluence.  For me, that meant a trip back into the crowd.conf file.  I rebooted the machine and verified that Confluence had started for me.  Easy as pie.

Tuesday, July 27, 2010

Atlassian Stack: Confluence

GreenHopper says that I have to install Confluence so that is what I'll be doing today.  Dragging the Confluence card over from To DO to In Progress gets me started.  I'll be following the Confluence installation guide using the standalone directions.

  1. download and extract the standalone version into /opt
  2. make a soft link to the new directory so I can get to it via /opt/confluence
  3. the docs says that for Debian based Linux you might need to grab some X11 libraries.  Just to be safe, I'll follow their advice and install them: sudo apt-get install libice-dev libsm-dev libx11-dev libxext-dev libxp-dev libxt-dev libxtst-dev. Installation failed because I already have the libs installed (I'm running the desktop version of Ubuntu so the X11 stuff is already available).
  4. created a confluence user and group
  5. created a directory to hold the Confluence data: mkdir /opt/confluence-home
  6. changed the owner ship of that directory and the confluence installation directory to be owned by the confluence account
  7. edited the to point to /opt/confluence-home
  8. Jira is running on ports 8005 and 8080 which is Confluence's default port, so I have to edit the server.xml file to use a new port.  I'll go with 8000 and 8090.  
  9. next, I've got to wire up Confluence to our mysql instance
  10. I chose not to modify the MySQL instance to specify InnoDb for fear of corrupting the existing databases.
  11. using Webmin, I created an new MySQL user named confluenceuser and gave it full privs.
  12. using Webmin, created a new database named confluence making sure to select UTF-8 as the character set and utf8_bin as the collation order.
  13. start up Confluence, connect to http://localhost:8090/ and run through the wizards
  14. I elected to start with an example site instead of an empty one
Everything went off without a hitch.  I did realize, however, that a task needs to be added to have Confluence auto-start at boot time.  The question is, what is the best way to add that story in Greenhopper?  Specifically, how can I make the task dependent?  I decided to go into the "install Confluence" story and make a sub-task.  That new task ended up in my To Do list.  Easy.  I found a workflow issue: I was allowed to resolve the master task despite having two open sub-tasks.  There must be a setting somewhere that prevents that.