Menu

Posts tagged with ‘jenkins’

How does the Jenkins Credentials Plug-in store passwords?

kinow @ Sep 07, 2015 01:25:03

Jenkins Credentials Plug-in manages credentials stored in Jenkins. These credentials can be used in many jobs and by plug-ins for executing SSH commands, authenticating to systems, or running other commands that need some sort of authentication or authorisation.

I recently used its API for the first time in the BioUno figshare Plug-in to store OAuth 1.0 credentials (consumer key, consumer secret, token key, token secret). This blog post has more details about how we used the plug-in, but this post is specifically on how the passwords are stored by Jenkins.

Secret and ciphers

Jenkins stores its configuration on disk as XML using the XStream library. Plug-in developers using the Credentials Plug-in API must use the Secret class to encrypt sensitive information.

The Secret.fromString method is responsible for creating a cipher from a given String. As in the Secret Javadoc, “this is not meant as a protection against code running in the same VM, nor against an attacker who has local file system access on Jenkins master”. But at least makes things more complicated :-)

public static Secret fromString(String data) {
    data = Util.fixNull(data);
    Secret s = decrypt(data);
    if(s==null) s=new Secret(data);
    return s;
}

The first line simply replaces a null string by an empty “”, or keeps the current value of not null.

After that, the decrypt method is called.

public static Secret decrypt(String data) {
    if(data==null)      return null;
    try {
        byte[] in = Base64.decode(data.toCharArray());
        Secret s = tryDecrypt(KEY.decrypt(), in);
        if (s!=null)    return s;

        // try our historical key for backward compatibility
        Cipher cipher = getCipher("AES");
        cipher.init(Cipher.DECRYPT_MODE, getLegacyKey());
        return tryDecrypt(cipher, in);
    } catch (GeneralSecurityException e) {
        return null;
    } catch (UnsupportedEncodingException e) {
        throw new Error(e); // impossible
    } catch (IOException e) {
        return null;
    }
}

The KEY.decrypt() call will return a javax.crypto.Cipher. The Cipher class is handled in CryptoConfidentialKey in Jenkins API, where it defines the algorithm used to create the cipher: AES.

Jenkins has also a ConfidentialStore, that is required to create the cipher. This class must be initialized before someone tries to create or read a cipher. This extra step also increases security, though access to the JVM is still a problem.

It is a bit late, so it is all for today. In summary: the credentials plug-in gives you a central place to manage credentials, but it is up to plug-in developers to use it. Sensitive values can be encrypted with AES on disk. So it is important that your file permissions, ACL and system auditing processes are in place and well maintained and monitored.

Happy hacking!

<p class="postmetadata">

    <small>tags 
     [&nbsp;<a
        href="/tag/jenkins"
        rel="tag">jenkins</a>&nbsp;]&nbsp;

     [&nbsp;<a
        href="/tag/security"
        rel="tag">security</a>&nbsp;]&nbsp;

    </small>


    <br/>
    <small>posted in 
    [&nbsp;<a
        href="/blog"
        title="View all posts in blog"
        rel="category tag">blog</a>&nbsp;]&nbsp;
    category </small>

</p>

Groovy Hooks in Jenkins for increasing logging level

kinow @ Apr 12, 2015 11:30:03

Yesterday, while debugging a problem we had in the BioUno update center, I realized that after increasing the logging level in the WEB interface, the messages that I needed weren’t being displayed in the logs.

It happened because some of the logging happened during Jenkins initialization, and before I could adjust the log level.

The solution was to use a Groovy Hook Script. If you are familiar with Linux init scripts, the idea is quite similar.

A Groovy script in the $JENKINS_ROOT_DIR/init.groovy.d/ directory is executed during Jenkins initialization. This way you can increase the global logger level with a script as the following below.

import java.util.logging.ConsoleHandler
import java.util.logging.LogManager
import java.util.logging.Logger
import java.util.logging.Level

def logger = Logger.getLogger("")
logger.setLevel(Level.FINEST)
logger.addHandler (new ConsoleHandler())

Happy logging!

<p class="postmetadata">

    <small>tags 
     [&nbsp;<a
        href="/tag/jenkins"
        rel="tag">jenkins</a>&nbsp;]&nbsp;

     [&nbsp;<a
        href="/tag/groovy"
        rel="tag">groovy</a>&nbsp;]&nbsp;

    </small>


    <br/>
    <small>posted in 
    [&nbsp;<a
        href="/blog"
        title="View all posts in blog"
        rel="category tag">blog</a>&nbsp;]&nbsp;
    category </small>

</p>

Treemapping Jenkins Extension Points with R

kinow @ May 19, 2014 00:51:33

I have been playing with R and its packages for some time, and decided to study it a bit harder. Last week I started reading the Advanced R Programming by Hadley Wickham.

One of the first chapters talks about the basic data structures in R. In order to get my feet wet I thought about a simple example: treemapping Jenkins extension points.

Treemap graph

There is a Wiki page with the extension points in Jenkins (what parts of Jenkins can be customized) and its implementations. That page is generated by a Jenkins job.

That job outputs a JSON file that contains each available extension points, as well as an array with its implementations. The R code below will produce two vectors, one with the count of implementations of each extension point, and the other with the class name.

nExtensionPoints <- length(extensionPointsJson$extensionPoints)
numberOfImplementations <- vector(length = nExtensionPoints)
namesOfTheExtensionPoints <- vector(length = nExtensionPoints)
for (i in seq_along(extensionPoints)) {
  extensionName = extensionPoints[[i]]$className
  lastIndexOfDot = regexpr("\\.[^\\.]*$", extensionName)
  namesOfTheExtensionPoints[[i]] = substr(extensionName, lastIndexOfDot[1]+1, nchar(extensionName))
  numberOfImplementations[[i]] = length(extensionPoints[[i]]$implementations)
  print(paste(namesOfTheExtensionPoints[[i]], " -> ", numberOfImplementations[[i]]))
}

For creating the treemap I used the portfolio package, and the map.market function. The structures previously created and the next snippet of code are all that is needed to create the treemap of the Jenkins extension points.

map.market(id=seq_along(extensionPoints), area=numberOfImplementations, group=namesOfTheExtensionPoints, color=numberOfImplementations, main="Jenkins Extension Points")

You can also use the Jenkins R Plug-in to produce this graph, as in this sample job. You can get the complete script in this gist, or just copy it here.

library('rjson')
library('portfolio')

download.file(url="https://ci.jenkins-ci.org/view/Infrastructure/job/infra_extension-indexer/ws/extension-points.json", destfile="extension-points.json", method="wget")
extensionPointsJson <- fromJSON(paste(readLines("extension-points.json"), collapse=""))
extensionPoints <- extensionPointsJson$extensionPoints
nExtensionPoints <- length(extensionPointsJson$extensionPoints)
numberOfImplementations <- vector(length = nExtensionPoints)
namesOfTheExtensionPoints <- vector(length = nExtensionPoints)
for (i in seq_along(extensionPoints)) {
  extensionName = extensionPoints[[i]]$className
  lastIndexOfDot = regexpr("\\.[^\\.]*$", extensionName)
  namesOfTheExtensionPoints[[i]] = substr(extensionName, lastIndexOfDot[1]+1, nchar(extensionName))
  numberOfImplementations[[i]] = length(extensionPoints[[i]]$implementations)
  print(paste(namesOfTheExtensionPoints[[i]], " -> ", numberOfImplementations[[i]]))
}
png(filename="extension-points.png", width=2048, height=1536, units="px", bg="white")
map.market(id=seq_along(extensionPoints), area=numberOfImplementations, group=namesOfTheExtensionPoints, color=numberOfImplementations, main="Jenkins Extension Points")
dev.off()
<p class="postmetadata">

    <small>tags 
     [&nbsp;<a
        href="/tag/jenkins"
        rel="tag">jenkins</a>&nbsp;]&nbsp;

     [&nbsp;<a
        href="/tag/r"
        rel="tag">r</a>&nbsp;]&nbsp;

    </small>


    <br/>
    <small>posted in 
    [&nbsp;<a
        href="/blog"
        title="View all posts in blog"
        rel="category tag">blog</a>&nbsp;]&nbsp;
    category </small>

</p>

Running BDD tests from TestLink in Jenkins

kinow @ Nov 07, 2012 14:26:08

Last night and this morning I spent some time working on running BDD tests that were created in TestLink in Jenkins, using testlink-plugin.

Similar integration has already been proposed in JinFeng, by Olivier Renault. Basically, you write BDD stories in TestLink (a story goes into the Test Case summary), Jenkins retrieves these stories and executes them using a skeleton project.

TestLink BDD
TestLink BDD

There are many ways to use BDD. In some of them you write code like Java, Ruby or Perl, and in others you write a DSL. I started working with JBehave, but for this integration, I preferred to use a DSL - as TestLink doesn’t maintain source code, only test cases -, so I switched to easyb.

( Read more … )

A quick view on Wordpress, Mantis and Jenkins plug-in API

kinow @ Oct 25, 2012 08:49:36

I’m preparing a plug-in API proposal for TestLink, and thought that the best way to learn how to write a good plug-in API would be by looking at other application’s plug-in API’s.

This post contains information that I gathered for creating this new API, but that may also be useful for other programmers. I used Wordpress, Mantis and Jenkins in this study. Let me know if you find any mistakes or if you have any other suggestions.

( Read more … )