Building a Jenkins Security Realm


Last week I spent a good while on writing a new security realm for KDE’s Jenkins setups. The result of my tireless java brewing is that the Jenkins installation of KDE neon now uses KDE’s Phabricator setup to authenticate users and manage permissions via OAuth.

We should hopefully see this roll out to the KDE CI Jenkins as well in the near future.

Since the documentation seems a bit scarce I am going to throw together some thoughts on how to implement OAuth security realms. For a primer on general plugin development I suggest having a look at the Jenkins Plugin Tutorial.

jenkins-securityJenkins security is split into two parts. The SecruityRealm controlling authentication of users and the AuthorizationStrategy controlling permissions of the users. These two are plugin description points for the respective functionality in Jenkins’ security.

The important thing to remember is that you can implement one without the other. For example the KDE OAuth plugin only implements a SecurityRealm as we currently have no need for our own AuthorizationStrategy. The Role Strategy plugin on the other hand implements only an AuthorizationStrategy.

To successfully implement a SecurityRealm you will need your realm class which is going to extend SecurityRealm and implement a UserDetailsService (this will actually only be used internally to, among other things, log in a user for API transactions). The SecurityRealm will use an AuthenticationToken to actually manage a session and a UserDetails instance to represent a user entity.

You can find some boilerplate code to outline a primitive realm we could use for OAuth2 in this git repository. Which would get a call-sequence similar to this one upon login request:

  • getLoginUrl (redirects to commenceLogin)
  • doCommenceLogin (redirects to request URI on oauth host)
  • doFinishLogin (gets redirected to by oauth host once authorized; requests access token)

After doFinishLogin the user should be authenticated and logged in. As you will probably notice there is talk of MyAuthToken and MyUser. Sample code for those is also available in the git repository.

They are both not terribly complicated, for the most part they are simply plain old data objects representing a session and a user. It is probably worth mentioning that a GrantedAuthority is approximately equal to the concept of a group membership, so much so that if you add more GrantedAuthorityImpls Jenkins will handle them as groups listed on the user profile and for use in AuthorizationStrategies.

MyAuthToken auth = new MyAuthToken(accessToken);

And that’s all you need for your SecurityRealm. For the most part your realm will simply create a token “somehow” and then set it as active on the SecurityContextHolder. Once that is done you have an authenticated session at your hand.

For some more inspiration hop on over to my actual plugin’s git repository.

A Very Aptly Ruby API


At Blue Systems we are running a whole slew of different deb repositories all over the place. Primarily of course for the various CI systems we are working on for Plasma Mobile, Debian, and KDE neon.

A while ago Rohan Garg suggested we should use Aptly, a relatively new repository management system written in Go featuring advanced features such as repository mirroring, publishing to Amazon S3 and a REST API. Since I do like me some REST APIs I was quickly sold on the idea of adopting it as our primary repository system.

Alas, most of our CI rigging is written in Ruby and there was no usable API gem in sight.

Low and behold: I wrote a Ruby gem for Aptly’s REST API. It’s called aptly-api.

It covers all the common repository usage from creating repositories and adding files, to publishing repositories to a publishing location. Let’s look at some code.

For example here we create a repository and publish it as public-name.

require 'aptly'

Aptly.configure do |config| = 'localhost'
  config.port = 8080

repo = Aptly::Repository.create('kewl-new-repo')
repo.publish('public-name', Distribution: 'wily', Architectures: %w(amd64 i386))

Aptly has two notions of a repository. There is a repository and then there is a published repository. A published repository essentially is an on-disk representation of a repository, namely what you would actually find on any deb repository like These published repositories have one (or more!) repositories associated with it. All packages in that repository will be part of the published repository. This allows you to have neat repository sets where internally you have packages separate in multiple repositories but publicly they show up in the same published repository tree. For instance you could have a repository for qt and a repository for kde-frameworks, but publicly your deb repository would contain both qt’s and kde-frameworks’ packages.

Let’s add a deb to our repository…

repo = Aptly::Repository.get('kewl-new-repo')

At this point kitteh will not actually show up in the published directory, we first have to update it. In fact, let’s update all published repositories our repository is part of, chances are we want all to refresh anyway.


For more useful information on aptly-api have a look at the gem documentation. If you find aptly-api useful, drop me a comment. Pull requests and bug reports are of course appreciated as well.

Bonus: Secure Remote

Aptly presently doesn’t support API authentication, so you’d rightfully wonder how exactly we secure the beast. Surely we aren’t publicly binding the API server for all the world to abuse.

The solution, as so often in life, is of course SSH. Namely if you want to use the API on a remote you could simply tunnel the relevant port to your localhost.

require 'aptly'
require 'net/ssh/gateway'

gateway ='hostname', 'username')
port ='localhost', 8080, 8080)

Aptly.configure do |config| = 'localhost'
  config.port = port