How to check if user is already created in Jenkins on Groovy?
I am using this script for automatic creation of admin user https://github.com/foxylion/docker-jenkins/blob/master/docker-images/master/default-user.groovy but unfortunately it launches each time when docker container (with it) restarts. Consequently I lose my other manually created users in Jenkins GUI.
It looks like getSecurityRealm() will return an impl that will include HudsonPrivateSecurityRealm ... is so this looks like it will work:
import jenkins.model.*
import hudson.security.*
import org.acegisecurity.userdetails.UsernameNotFoundException
import org.springframework.dao.DataAccessException
def env = System.getenv()
def jenkins = Jenkins.getInstance()
jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(false))
jenkins.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy())
def user = null;
try {
jenkins.getSecurityRealm().loadUserByUsername(env.JENKINS_USER);
} catch (UsernameNotFoundExceoption n) {
user = jenkins.getSecurityRealm().createAccount(env.JENKINS_USER, env.JENKINS_PASS)
user.save()
jenkins.getAuthorizationStrategy().add(Jenkins.ADMINISTER, env.JENKINS_USER)
jenkins.save()
} catch (org.springframework.dao.DataAccessException d) {
/// log
}
Related
I'm writing a shared library that will get used in Pipelines.
class Deployer implements Serializable {
def steps
Deployer(steps) {
this.steps = steps
}
def deploy(env) {
// convert environment from steps to list
def process = "ls -l".execute(envlist, null)
process.consumeProcessOutput(output, error)
process.waitFor()
println output
println error
}
}
In the Jenkinsfile, I import the library, call the class and execute the deploy function inside a script section:
stage('mystep') {
steps {
script {
def deployer = com.mypackage.HelmDeployer("test")
deployer.deploy()
}
}
}
However, no output or errors are printed on the Console log.
Is it possible to execute stuff inside a shared library class? If so, how, and what am I doing wrong?
Yes, it is possible but not really an obvious solution. Every call that is usually done in the Jenkinsfile but was moved to the shared-library needs to reference the steps object you passed.
You can also reference the Jenkins environment by calling steps.env.
I will give you a short example:
class Deployer implements Serializable {
def steps
Deployer(steps) {
this.steps = steps
}
def callMe() {
// Always call the steps object
steps.echo("Test")
steps.echo("${steps.env.BRANCH_NAME}")
steps.sh("ls -al")
// Your command could look something like this:
// def process = steps.sh(script: "ls -l", returnStdout: true).execute(steps.env, null)
...
}
}
You also have to import the object of the shared library and create an instance of it. Define the following outside of your Pipeline.
import com.mypackage.Deployer // path is relative to your src/ folder of the shared library
def deployer = new Deployer(this) // 'this' references to the step object of the Jenkins
Then you can call it in your pipeline as the following:
... script { deployer.test() } ...
I am able to add a specific Permission to a User using the following common script:
import hudson.model.*
import Jenkins.*
import hudson.security.Permission
import hudson.security.GlobalMatrixAuthorizationStrategy
String userId = "my_user"
List<String> userPermissionList = [hudson.model.Item.CONFIGURE]
Hudson instance = Jenkins.get()
GlobalMatrixAuthorizationStrategy authStrategy = Jenkins.instance.getAuthorizationStrategy()
// Adding each permission from list
userPermissionList.each { permission ->
authStrategy.add(permission, userId)
instance.setAuthorizationStrategy(authStrategy)
}
instance.save()
However, I looked everywhere to find how to remove a specific permission from a user. Looking at GlobalMatrixAuthorizationStrategy, there is a add() method, however no remove() of any sort.
Is this even possible??? (it has to be)
Or do I have add the difference to the user? As in, clear the user of all permissions and add back all but the ones I want to remove.
Solution
The Permission class has an attribute called enabled with associated getters and setters. You can add a permission by setting permission.enabled = true and to remove the permission you should explicitly set permission.enabled = false
The default value for permission.enabled may be different depending on what version of Jenkins you are running. It is best to explicitly set this value either way
import hudson.model.*
import Jenkins.*
import hudson.security.Permission
import hudson.security.GlobalMatrixAuthorizationStrategy
def userId = "gfarkas"
def userPermissionList = [hudson.model.Item.CONFIGURE]
Hudson instance = Jenkins.get()
GlobalMatrixAuthorizationStrategy authStrategy = Jenkins.instance.getAuthorizationStrategy()
// Removing each permission from list
userPermissionList.each { permission ->
permission.enabled = false
authStrategy.add(permission, userId)
instance.setAuthorizationStrategy(authStrategy)
}
instance.save()
This intended to be ran in the Jenkin's Script Console
Before running the above script the user had the following permission
And after running this script the user had the following permission
If I rerun the script with permission.enabled = true the user has the following permission
According to the document.
https://javadoc.jenkins.io/hudson/security/Permission.html#enabled
enabled : Whether this permission is available for use
So Enable=false will remove the role from setting, means the whole column will disappear.
and this document works for me,
getGrantedPermissionEntries():
Returns a live modifiable map of permissions.
Since:3.0
https://javadoc.jenkins.io/plugin/matrix-auth/org/jenkinsci/plugins/matrixauth/AuthorizationContainer.html#getGrantedPermissionEntries--
import hudson.security.*
import org.jenkinsci.plugins.matrixauth.PermissionEntry
import org.jenkinsci.plugins.matrixauth.AuthorizationType
def user = new PermissionEntry(AuthorizationType.USER, 'woody.wei')
println user
def strategy = Jenkins.instance.authorizationStrategy
entryMap = strategy.getGrantedPermissionEntries()
entryMap.keySet().each{
entryMap[it] -= user
}
getGrantedPermissionEntries returns a map, each permission holds it's permission entries, looks like this.
{Permission[class hudson.model.View,Delete]=[PermissionEntry{type=GROUP, sid='authenticated'}], Permission[class hudson.model.Computer,Connect]=[PermissionEntry{type=GROUP, sid='authenticated'}], Permission[class hudson.model.Run,Delete]=[PermissionEntry{type=GROUP, sid='authenticated'}], Permission[class hudson.model.Computer,Create]=[PermissionEntry{type=GROUP, sid='authenticated'}], Permission[class com.cloudbees.plugins.credentials.CredentialsProvider,ManageDomains]=[PermissionEntry{type=USER, sid='woody.wei'}, PermissionEntry{type=GROUP, sid='authenticated'}]}
To move a specific permission, construct a permission like this, then remove the entry in it.
Permission.fromId('hudson.model.Item.Cancel')
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)
}
For the already available multi-job in jenkins, need to add new phase jobs using Groovy Scripting. I have written the following groovy code which adds up an already existing job p25_deploy-1.
This code is working to create the multi-job but the phase job is not showing as mapped in the Jenkins UI. Where as if I see it config.xml, its created properly as expected except a tag <killPhaseOnJobResultCondition>. Not sure why the phase job is not mapped properly?
import jenkins.model.*
import hudson.model.*
import com.tikal.jenkins.plugins.multijob.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.KillPhaseOnJobResultCondition.*
import java.lang.String.*
import hudson.model.Descriptor;
import hudson.tasks.Builder;
def jenkinsInstance = jenkins.model.Jenkins.instance
def templateJobName = 'profile_p25'
def templateJob = jenkinsInstance.getJob(templateJobName)
// get MultiJob BuildPhases and clone each PhaseJob
builders = templateJob.getBuilders();
builders.each { b ->
if (b instanceof MultiJobBuilder){
def pj = b.getPhaseJobs()
hudson.model.Describable p1 = new PhaseJobsConfig("p25_deploy-1",null,
true,PhaseJobsConfig.KillPhaseOnJobResultCondition NEVER,null,false,false,null,0,false,true,null,false,false)
pj.add(p1)
}
}
templateJob.save()
// update dependencies
jenkinsInstance.rebuildDependencyGraph()
Any help will be really appreciated. Have tried many ways but was not able to figure out the problem with the script.
We can use DSL to create but I wanted it to be done in Groovy Scripting and moreover modify the existing job.
Blockquote
Yay! I am back with the answer for my question. Have tried this since very long time. Finally am able to make it though. I was aware that solution would be really simple but not able to figure out the hack of it.
import jenkins.model.*
import hudson.model.*
import com.tikal.jenkins.plugins.multijob.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.KillPhaseOnJobResultCondition.*
import java.lang.String.*
import hudson.model.Descriptor
import hudson.tasks.Builder
def jenkinsInstance = jenkins.model.Jenkins.instance
def templateJobName = 'profile_p25'
def templateJob = jenkinsInstance.getJob(templateJobName)
// get MultiJob BuildPhases and clone each PhaseJob
builders = templateJob.getBuilders();
builders.each { b -> if (b instanceof MultiJobBuilder)
{ def pj =
b.getPhaseJobs()
hudson.model.Describable newphase = new
PhaseJobsConfig(deploys[i],null,
true,null,null,false,false,null,0,false,false,"",false,false)
newphase.killPhaseOnJobResultCondition = 'NEVER'
pj.add(newphase)
}
}
templateJob.save()
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")
);