Jenkins: Configure ActiveDirectorySecurityRealm Plugin using Groovy - jenkins

I'm currently spending some time setting up a generic configuration using Jenkins AD-SecurityRealm (ActiveDirectorySecurityRealm) Plugin (v2.6) and stuck over a nasty issue: It seems that my approach to (auto) set up a valid AD-connection (following the corresponding documentation) is not working at all. Every time I'll re-init my Jenkins instance an incomplete config.xml will provide - the "bindName" property (XML-node) is always missing. This property is required by the ad-server I'll use and so I've to override the config manually to solve this issue.
I haven't the vaguest idea why this still happens.
my groovy code (excerpt)
String _domain = 'my-primary-ad-server-running.acme.org'
String _site = 'jenkins.acme.org'
String _bindName = 'ad-bind-user'
String _bindPassword = 'ad-bind-password-super-secret-123'
String _server = 'my-primary-ad-server-running.acme.org'
def hudsonActiveDirectoryRealm = new ActiveDirectorySecurityRealm(_domain, _site, _bindName, _bindPassword, _server)
def instance = Jenkins.getInstance()
instance.setSecurityRealm(hudsonActiveDirectoryRealm)
instance.save()
my config.xml result (excerpt)
<securityRealm class="hudson.plugins.active_directory.ActiveDirectorySecurityRealm" plugin="active-directory#2.6">
<domains>
<hudson.plugins.active__directory.ActiveDirectoryDomain>
<name>my-primary-ad-server-running.acme.org</name>
<servers>my-primary-ad-server-running.acme.org:3268</servers>
<bindPassword>{###-fancy-crypted-super-password-nobody-can-decrypt-anymore-###}</bindPassword>
</hudson.plugins.active__directory.ActiveDirectoryDomain>
</domains>
<startTls>true</startTls>
<groupLookupStrategy>AUTO</groupLookupStrategy>
<removeIrrelevantGroups>false</removeIrrelevantGroups>
<tlsConfiguration>TRUST_ALL_CERTIFICATES</tlsConfiguration>
</securityRealm>
my config.xml required (excerpt)
<securityRealm class="hudson.plugins.active_directory.ActiveDirectorySecurityRealm" plugin="active-directory#2.6">
<domains>
<hudson.plugins.active__directory.ActiveDirectoryDomain>
<name>my-primary-ad-server-running.acme.org</name>
<servers>my-primary-ad-server-running.acme.org:3268</servers>
<bindName>ad-bind-user</bindName>
<bindPassword>{###-fancy-crypted-super-password-nobody-can-decrypt-anymore-###}</bindPassword>
</hudson.plugins.active__directory.ActiveDirectoryDomain>
</domains>
<startTls>true</startTls>
<groupLookupStrategy>AUTO</groupLookupStrategy>
<removeIrrelevantGroups>false</removeIrrelevantGroups>
<tlsConfiguration>TRUST_ALL_CERTIFICATES</tlsConfiguration>
</securityRealm>

Thanks #kosta.
Following script also works using active-directory 2.10 and jenkins 2.150.1
This also include site information.
import hudson.plugins.active_directory.ActiveDirectoryDomain
import hudson.plugins.active_directory.ActiveDirectorySecurityRealm
import hudson.plugins.active_directory.GroupLookupStrategy
String _domain = 'dev.test.com'
String _site = 'HQ'
String _bindName = 'dev\jenkins'
String _bindPassword = 'test'
String _server = 'dev.test.com:2328'
def hudsonActiveDirectoryRealm = new ActiveDirectorySecurityRealm(_domain, _site, _bindName, _bindPassword, _server)
hudsonActiveDirectoryRealm.getDomains().each({
it.bindName = hudsonActiveDirectoryRealm.bindName
it.bindPassword = hudsonActiveDirectoryRealm.bindPassword
it.site = hudsonActiveDirectoryRealm.site
})
def instance = Jenkins.getInstance()
instance.setSecurityRealm(hudsonActiveDirectoryRealm)
instance.save()
Check this screenshot: Configure Global Security

If you look at the source code for ActiveDirectorySecurityRealm you will see that the bindName is marked as transient, thus it won't be persisted as part of the config XML.
The only solution to get the desired config.xml is to force the config.xml by providing a custom static one and not use the init script.

I was able to solve this issue by adding the following code at the end (Tested on 2.6 and 2.8). You also need to make sure that your credentials are valid because the plugin is doing an initial connectivity check https://issues.jenkins-ci.org/browse/JENKINS-48513
hudsonActiveDirectoryRealm.getDomains().each({
it.bindName = hudsonActiveDirectoryRealm.bindName
it.bindPassword = hudsonActiveDirectoryRealm.bindPassword
})
instance.setSecurityRealm(hudsonActiveDirectoryRealm)
instance.save()

Related

How to Reference A Jenkins Global Shared Library

After reviewing the docs, a number of questions here on SO, and trying a dozen or so different script configurations, I cannot figure out how to reference a shared Groovy library. I've added the library like so:
This appears to be working. I'm referencing the script like so:
You can see the error message therein:
Script1: 1: unable to resolve class Library , unable to find class
for annotation # line 1, column 1. #Library('sonarQubeAPI')_
The script code, not I think it matters, looks like this:
import groovy.json.JsonSlurper
class SonarQubeAPI{
static string getVersion(){
return "1.0";
}
static void getSonarStatus(projectKey){
def sonarQubeUserToken = "USERTOKEN";
def projectStatusUrl = "pathtosonarqube/api/qualitygates/project_status?projectKey=" + projectKey;
println("Retrieving project status for " + projectKey);
def json = getJson(sonarQubeUserToken, projectStatusUrl);
def jsonSlurper = new JsonSlurper();
def object = jsonSlurper.parseText(json);
println(object.projectStatus.status);
}
static string getJson(userToken, url){
def authString = "${userToken}:".getBytes().encodeBase64().toString();
def conn = url.toURL().openConnection();
conn.setRequestProperty( "Authorization", "Basic ${authString}" );
return conn.content.text;
}
}
I'm probably just a magic character off, but I can't seem to lock it down.
Shared libraries are a feature of Jenkins Pipelines, not of Jenkins (core) itself. You can use them only in Pipeline jobs (and child types like Multibranch Pipeline).

Groovy Missing Property Exception

I have a jenkins build that needs to get the filenames for all files checked in within a changeset.
I have installed groovy on the slave computer and configured Jenkins to use it. I am running the below script that should return the names (or so I assume as this may be wrong as well) and print to the console screen however I am getting this error:
groovy.lang.MissingPropertyException: No such property: paths for class: hudson.plugins.tfs.model.ChangeSet
Here is the Groovy System Script:
import hudson.plugins.tfs.model.ChangeSet
// work with current build
def build = Thread.currentThread()?.executable
// get ChangesSets with all changed items
def changeSet= build.getChangeSet()
def items = changeSet.getItems()
def affectedFiles = items.collect { it.paths }
// get file names
def fileNames = affectedFiles.flatten().findResults
fileNames.each {
println "Item: $it" // `it` is an implicit parameter corresponding to the current element
}
I am very new to Groovy and Jenkins so if its syntax issue or if I'm missing a step please let me know.
I don't know the version of jenkins you are using but according to the sourcecode of ChangeSet that you can find here I suggest you to replace line 9 with:
def affectedFiles = items.collect { it.getAffectedPaths() }
// or with the equivalent more groovy-idiomatic version
def affectedFiles = items.collect { it.affectedPaths }
Feel free to comment the answer if there will be more issues.

Set StashNotifier with Groovy

I am trying to add the StashNotifier configuration to Jenkins via Groovy
import jenkins.model.*;
import org.jenkinsci.plugins.stashNotifier.*
def instance = Jenkins.getInstance()
def bitbucket = instance.getDescriptor(StashNotifier)
println "--> configure Stash Notifier..."
def bitBucketNotifier = new StashNotifier (
"https://servername:8443", //stashServerBaseUrl
"user", //credentialsId
false, //ignoreUnverifiedSSLPeer
"", //commitSha1
false, //includeBuildNumberInKey
"", //projectKey
false, //prependParentProjectKey
false //disableInprogressNotification
)
bitbucket.save()
println "--> configure Stash Notifier... done"
The xml configuration I am trying to implement is
<?xml version='1.0' encoding='UTF-8'?>
<org.jenkinsci.plugins.stashNotifier.StashNotifier_-DescriptorImpl plugin="stashNotifier#1.11.6">
<credentialsId>user</credentialsId>
<stashRootUrl>https://servername:8443/</stashRootUrl>
<ignoreUnverifiedSsl>false</ignoreUnverifiedSsl>
<includeBuildNumberInKey>false</includeBuildNumberInKey>
<prependParentProjectKey>false</prependParentProjectKey>
<disableInprogressNotification>false</disableInprogressNotification>
</org.jenkinsci.plugins.stashNotifier.StashNotifier_-DescriptorImpl>
I am new to Java and groovy, but I cannot get this to work. I feel I am close, probably missing one or two little bits.
I am trying to get Jenkins to configure upon start-up and then reconfigure itself if any changes are made to core integrations. In this case, the BitBucket server won't change but if users do make the change to point at something else, Jenkins is reconfigured to point at the correct thing
#flue42 has a great answer, though going through the JSON and FormData is a bit tough to follow. Instead you can simply write the values to their respective properties on the object and save it.
If you happened to have multiple Stash servers you wanted to notify (not suppported at the global configuration level), you'll need to override the global setting on a per job basis, see my other answer with the skeleton of doing it using the Job DSL plugin.
Perhaps the most annoying part of looking at this to implement myself was in the code it references stashServerBaseUrl (as you noted in your comment) but then the required name in the Groovy/form is stashRootUrl. The place to find the right names is right around here
#!groovy
import jenkins.model.*;
import org.jenkinsci.plugins.stashNotifier.*;
String url = 'https://stashblablablabla';
String credentials = '01111111-e222-3333-eeff-4f4444e44bc4';
def j = Jenkins.getInstance();
def stash = instance.getDescriptor(StashNotifier)
stash.stashRootUrl = url //stashServerBaseUrl
stash.credentialsId = credentials //credentialsId
stash.ignoreUnverifiedSsl = false //ignoreUnverifiedSSLPeer
stash.includeBuildNumberInKey = false //includeBuildNumberInKey
stash.projectKey = "" //projectKey
stash.prependParentProjectKey = false //prependParentProjectKey
stash.disableInprogressNotification = false //disableInprogressNotification
stash.save()
I've done something like that :
#!groovy
import jenkins.model.*;
import org.jenkinsci.plugins.*;
import net.sf.json.JSONObject;
String url = 'https://stashblablablabla';
String credentials = '01111111-e222-3333-eeff-4f4444e44bc4';
def j = Jenkins.getInstance();
def stash = j.getExtensionList(
stashNotifier.StashNotifier.DescriptorImpl.class)[0];
def formData = [
stashRootUrl: url,
credentialsId: credentials,
ignoreUnverifiedSsl: false,
includeBuildNumberInKey: false,
prependParentProjectKey: false,
disableInprogressNotification: false,
considerUnstableAsSuccess: false
] as JSONObject;
stash.configure(null, formData);
j.save();
I've figured that solution out reading that:
https://github.com/jenkinsci/stashnotifier-plugin/blob/release/1.x/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java
https://github.com/samrocketman/jenkins-bootstrap-slack/blob/master/scripts/configure-slack.groovy
It appears to be working in my test platform.
If you are looking to do it via Job DSL you can use this example from the Job DSL repo.
// notify Stash using the global Jenkins settings
job('example-1') {
publishers {
stashNotifier()
}
}
// notify Stash using the global Jenkins settings and sets keepRepeatedBuilds to true
job('example-2') {
publishers {
stashNotifier {
keepRepeatedBuilds()
}
}
}
https://github.com/jenkinsci/job-dsl-plugin/blob/master/job-dsl-core/src/main/docs/examples/javaposse/jobdsl/dsl/helpers/publisher/PublisherContext/stashNotifier.groovy

Adding Global Password to Jenkins with init.groovy

How can I add a global passwords to Jenkins through the init.groovy that runs at startup?
To be clear, in the Manage Jenkins -> Configure Jenkins page, there is a section titled "Global Passwords". I would like to add entries in that section via Groovy code during the startup of Jenkins.
I am trying to provision my jenkins environment through groovy code by using the init.groovy. I need to add global passwords through the EnvInject plugin. I can successfully add path to a file for the same plugin using this code:
def instance = Jenkins.getInstance()
DescribableList<NodeProperty<?>, NodePropertyDescriptor> globalNodeProperties =
instance.getGlobalNodeProperties();
globalNodeProperties.add(
new EnvInjectNodeProperty(false, "/var/lib/jenkins/secret.properties")
);
However, I am failing to understand the mechanics needed to programmatically add global passwords.
Here is the code example that should work. It seems that save() method also adds it to GlobalNodeProperties, so you don't have to add to that collection manually.
import jenkins.model.*
import hudson.util.*
import hudson.slaves.NodeProperty
import hudson.slaves.NodePropertyDescriptor
import org.jenkinsci.plugins.envinject.*
def instance = Jenkins.getInstance()
DescribableList<NodeProperty<?>, NodePropertyDescriptor> globalNodeProperties
= instance.getGlobalNodeProperties();
envInjectNodeProperty= new EnvInjectNodeProperty(false, "/var/lib/jenkins/secret.properties"
propDescriptor = envInjectNodeProperty.getDescriptor()
//password entry
def passEntry = new EnvInjectGlobalPasswordEntry("some_username", "password")
//password entries list, add you global password here
List<EnvInjectGlobalPasswordEntry> envInjectGlobalPasswordEntriesList= [passEntry];
propDescriptor.envInjectGlobalPasswordEntries =
envInjectGlobalPasswordEntriesList.toArray(
new EnvInjectGlobalPasswordEntry[envInjectGlobalPasswordEntriesList.size()]
);
propDescriptor.save();
https://github.com/jenkinsci/envinject-plugin/tree/master/src/main/java/org/jenkinsci/plugins/envinject
I did not try this plugin, but there is a class : EnvInjectGlobalPasswordEntry
i guess it could be like this:
globalNodeProperties.add(
new EnvInjectGlobalPasswordEntry("pass-name", "the-password")
);

Way to change Jenkins' project variable value with script

Is there a way to change project variable values in Jenkins automatically when build is done?
In my case i got a variable VERSION, default value is 1. And i need to increment this default value every build done. Assuming build stars by cron in this case. Any plugins can help me?
Now i have something like this: My build steps.
It is a single working way to get project variable in my groovy script that i found. Now how can i set new value for variable?
I read some similar question on SO, but didn't found a working way for me.
P.S. I can't use $BUILD_NUMBER var, because i need a possibility to set VERSION manually when i start build.
First, of all, install the plugins Global Variable String Parameter Plugin and Groovy Postbuild Plugin. Under Manage Jenkins -> Configure System you should now have a part, called Global Properties. There you add a new variable. In my tests, I called it SOME_VER.
At your job, you now add a Groovy postbuild part with this code adjusted to your variable:
import jenkins.*;
import jenkins.model.*;
import hudson.*;
import hudson.model.*;
import java.lang.*;
instance = Jenkins.getInstance();
globalNodeProperties = instance.getGlobalNodeProperties();
envVarsNodePropertyList = globalNodeProperties.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class);
envVars = null
if (envVarsNodePropertyList != null && envVarsNodePropertyList.size() > 0)
{
envVars = envVarsNodePropertyList.get(0).getEnvVars()
String value = envVars.get("SOME_VER", "0")
int NEW_VER = Integer.parseInt(value)
NEW_VER = NEW_VER + 1
envVars.override("SOME_VER", NEW_VER.toString());
}
instance.save()
Parts of this code are taken from here. This code does nothing else than retrieving the value of the global variable, change it and save the new value of the variable.

Resources