Adding Global Password to Jenkins with init.groovy - jenkins

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")
);

Related

Jenkins add Git Behaviors using groovy scripts

I'm creating my Jenkins instance using groovy scripts because I'm automating the Jenkins creation process. I create this script:
/* Adds a multibranch pipeline job to Jenkins */
import hudson.model.*
import hudson.util.PersistedList
import jenkins.*
import jenkins.branch.*
import jenkins.model.*
import jenkins.model.Jenkins
import jenkins.plugins.git.*
import com.cloudbees.hudson.plugins.folder.computed.PeriodicFolderTrigger
import org.jenkinsci.plugins.workflow.multibranch.*
// Create job
def env = System.getenv()
Jenkins jenkins = Jenkins.instance
String jobName = "Job"
String jobScript = "Jenkinsfile"
def job = jenkins.getItem(jobName)
// Create the folder if it doesn't exist
if (job == null) {
job = jenkins.createProject(WorkflowMultiBranchProject.class, jobName)
}
job.getProjectFactory().setScriptPath(jobScript)
// Add git repo
String id = null
String remote = env.CODE_COMMIT_URL
String includes = "*"
String excludes = ""
boolean ignoreOnPushNotifications = false
GitSCMSource gitSCMSource = new GitSCMSource(id, remote, null, includes, excludes, ignoreOnPushNotifications)
BranchSource branchSource = new BranchSource(gitSCMSource)
// Remove and replace?
PersistedList sources = job.getSourcesList()
sources.clear()
sources.add(branchSource)
job.addTrigger(new PeriodicFolderTrigger("1m"))
and paste it at $JENKINS_HOME/ref/init.groovy.d/. When I start Jenkins, by job was already created. Besides that, I need to add some Git Behaviors to my job and I'd like to know if is there a way to add Git Behaviors using groovy script?
My Git after created:
Git behaviors I'd like to add at initialization (Discover tags, Check out to matching local branch, Custom user name/e-mail address)
Thank you!
I think what you want is managed through traits (I haven't actually tried this):
import jenkins.plugins.git.traits.*
def traits = []
// Add your traits...
traits.add(new TagDiscoveryTrait())
traits.add(new LocalBranchTrait())
gitSCMSource.setTraits(traits)

Configure matrix authorization plugin using Groovy script

I am learning to write the groovy script to configure matrix authorization plugin. I have written this script where only authenticated users can access Jenkins:
import jenkins.model.*
import hudson.security.*
import com.cloudbees.hudson.plugins.folder.properties.AuthorizationMatrixProperty
try {
def instance = Jenkins.getInstance()
def realm = new HudsonPrivateSecurityRealm(false)
instance.setSecurityRealm(realm)
def strategy = new hudson.security.GlobalMatrixAuthorizationStrategy()
strategy.add(Jenkins.ADMINISTER, 'authenticated')
instance.setAuthorizationStrategy(strategy)
instance.save()
}
catch(Throwable exc) {
println '!!! Error configuring jenkins'
org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception(exc)).printStackTrace()
println '!!! Shutting down Jenkins to prevent possible mis-configuration from going live'
jenkins.cleanUp()
System.exit(1)
}
Now, I want to configure this matrix plugin in a way that nobody can access the Jenkins settings area(even authenticated users can not access the Jenkins settings). I have done lot of research on that and not able to move forward with this. Any help/pointer will be appreciated. Thanks!
I found an answer to that. Below is the complete code for the above requirement where I was missing Jenkins.READ.
import jenkins.model.*
import hudson.security.*
import com.cloudbees.hudson.plugins.folder.properties.AuthorizationMatrixProperty
try {
def instance = Jenkins.getInstance()
def realm = new HudsonPrivateSecurityRealm(false)
instance.setSecurityRealm(realm)
def strategy = new hudson.security.GlobalMatrixAuthorizationStrategy()
strategy.add(Jenkins.READ, 'authenticated')
instance.setAuthorizationStrategy(strategy)
instance.save()
}
catch(Throwable exc) {
println '!!! Error configuring jenkins'
org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new
Exception(exc)).printStackTrace()
println '!!! Shutting down Jenkins to prevent possible mis-configuration from going live'
jenkins.cleanUp()
System.exit(1)
}

Jenkins: Configure ActiveDirectorySecurityRealm Plugin using Groovy

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()

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.

In Jenkins, how do builds know who requested them?

I need to pass the username of the requester of a build down to the script that is actually doing the work. Looking at the console output for a particular build, the first line is always "Started by user foo," so Jenkins is clearly keeping track of who triggered the build. So it should be possible to pass that information down to the job. The question is, how?
user30997
Please check out Jenkins Build User Vars plugin, it does what you need:
It is used to set following user build variables:
BUILD_USER – full name of user started build,
BUILD_USER_FIRST_NAME – first name of user started build,
BUILD_USER_LAST_NAME – last name of user started build,
BUILD_USER_ID – id of user started build.
The username isn't put in an easy-to-fetch environment variable, but you can get it using the xml (or json or python) api - as soon as you start a build, http://[jenkins-server]/job/[job-name]/[build-number]/api/xml is populated with details:
<freeStyleBuild>
<action>
<cause>
<shortDescription>Started by user foobar</shortDescription>
<userName>foobar</userName>
</cause>
</action>
<building>true</building>
[...]
I tried to use Jenkins Build User Vars plugin and notify a HipChat room that a build was started by a certain user, but BUILD_USER variable was not available to HipChat plugin, possibly because HipChat action happened before Build User Vars plugin injects the variable.
So I installed pre-scm-buildstep plugin and added:
]
// Inject environment variables using Groovy
import hudson.model.*
def build = Thread.currentThread().executable
def userCause = build.getCause(hudson.model.Cause$UserIdCause)
def userName = userCause?.userId ?: 'Jenkins'
def envVars = ['BUILD_USER': userName]
for (item in envVars) {
build.addAction(new ParametersAction([
new StringParameterValue(item.key, item.value)
]))
}
In your Job add "Execute system Groovy script":
def yourUserName = build.causes[0].userId
I managed to get it (on Jenkins 2.58):
currentBuild.getRawBuild().getCauses()[0].getUserId()
Of course you need to set permissions in Jenkins to be able to call these methods.
It's not always the 0th Cause object you are looking for, e.g. it may be another one if you replay another user's build (did not test this).
import os
import jenkinsapi.build
import jenkinsapi.jenkins
#Required Environment variables example:
#JENKINS_URL=http://jenkinsserver/
#JOB_NAME=TEST_GT
#BUILD_NUMBER=8
jenkins_inst = None
def get_jenkins_inst():
if jenkins_inst == None:
jenkins_url = os.environ['JENKINS_URL']
print("Connect to jenkins " + jenkins_url)
jenkins_inst = jenkinsapi.jenkins.Jenkins(jenkins_url)
return jenkins_inst
def get_jenkins_job():
jenkins_inst = get_jenkins_inst()
jenkins_job_name = os.environ['JOB_NAME']
print("Get jenkins job " + jenkins_job_name)
return jenkins_inst.get_job(jenkins_job_name)
def get_jenkins_user():
jenkins_job = get_jenkins_job()
jenkins_buildno = int(os.environ['BUILD_NUMBER'])
print("Get jenkins job build " + str(jenkins_buildno))
cur_build = jenkins_job.get_build(jenkins_buildno)
return cur_build.get_actions()['causes'][0]['userId']

Resources