Skip to content

Instantly share code, notes, and snippets.

@mllrjb
Last active April 10, 2024 17:30
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save mllrjb/ccfd3315b7546ae8e8382ff693b34d7f to your computer and use it in GitHub Desktop.
Save mllrjb/ccfd3315b7546ae8e8382ff693b34d7f to your computer and use it in GitHub Desktop.
Jenkins init.groovy.d role-based authorization strategy

Usage

Set a system environment variable AUTHZ_JSON_URL that points to a JSON file with the following structure:

{
  "admins": [
    "groupA", 
    "userA"
  ],
  "builders": [
    "groupB",
    "userB"
  ],
  "readers": ["anonymous"]
}

If you don't specify a URL, it will just grant admin access to anonymous.

import hudson.*
import hudson.security.*
import jenkins.model.*
import java.util.*
import com.michelin.cio.hudson.plugins.rolestrategy.*
import com.synopsys.arc.jenkins.plugins.rolestrategy.*
import java.lang.reflect.*
import java.util.logging.*
import groovy.json.*
def env = System.getenv()
/**
* ===================================
*
* Roles
*
* ===================================
*/
def globalRoleRead = "read"
def globalBuildRole = "build"
def globalRoleAdmin = "admin"
/**
* ===================================
*
* Users and Groups
*
* ===================================
*/
def access = [
admins: ["anonymous"],
builders: [],
readers: []
]
if (env.AUTHZ_JSON_FILE) {
println "Get role authorizations from file ${env.AUTHZ_JSON_FILE}"
File f = new File(env.AUTHZ_JSON_FILE)
def jsonSlurper = new JsonSlurper()
def jsonText = f.getText()
access = jsonSlurper.parseText( jsonText )
}
else if (env.AUTH_JSON_URL) {
println "Get role authorizations from URL ${env.AUTHZ_JSON_URL}"
URL jsonUrl = new URL(env.AUTHZ_JSON_URL);
access = new JsonSlurper().parse(jsonUrl);
}
else {
println "Warning! Neither env.AUTHZ_JSON_FILE nor env.AUTHZ_JSON_URL specified!"
println "Granting anonymous admin access"
}
/**
* ===================================
*
* Permissions
*
* ===================================
*/
// TODO: drive these from a config file
def adminPermissions = [
"hudson.model.Hudson.Administer",
"hudson.model.Hudson.Read"
]
def readPermissions = [
"hudson.model.Hudson.Read",
"hudson.model.Item.Discover",
"hudson.model.Item.Read"
]
def buildPermissions = [
"hudson.model.Hudson.Read",
"hudson.model.Item.Build",
"hudson.model.Item.Cancel",
"hudson.model.Item.Read",
"hudson.model.Run.Replay"
]
def roleBasedAuthenticationStrategy = new RoleBasedAuthorizationStrategy()
Jenkins.instance.setAuthorizationStrategy(roleBasedAuthenticationStrategy)
/**
* ===================================
*
* HACK
* Inspired by https://issues.jenkins-ci.org/browse/JENKINS-23709
* Deprecated by on https://github.com/jenkinsci/role-strategy-plugin/pull/12
*
* ===================================
*/
Constructor[] constrs = Role.class.getConstructors();
for (Constructor<?> c : constrs) {
c.setAccessible(true);
}
// Make the method assignRole accessible
Method assignRoleMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod("assignRole", RoleType.class, Role.class, String.class);
assignRoleMethod.setAccessible(true);
println("HACK! changing visibility of RoleBasedAuthorizationStrategy.assignRole")
/**
* ===================================
*
* Permissions
*
* ===================================
*/
Set<Permission> adminPermissionSet = new HashSet<Permission>();
adminPermissions.each { p ->
def permission = Permission.fromId(p);
if (permission != null) {
adminPermissionSet.add(permission);
} else {
println("${p} is not a valid permission ID (ignoring)")
}
}
Set<Permission> buildPermissionSet = new HashSet<Permission>();
buildPermissions.each { p ->
def permission = Permission.fromId(p);
if (permission != null) {
buildPermissionSet.add(permission);
} else {
println("${p} is not a valid permission ID (ignoring)")
}
}
Set<Permission> readPermissionSet = new HashSet<Permission>();
readPermissions.each { p ->
def permission = Permission.fromId(p);
if (permission != null) {
readPermissionSet.add(permission);
} else {
println("${p} is not a valid permission ID (ignoring)")
}
}
/**
* ===================================
*
* Permissions -> Roles
*
* ===================================
*/
// admins
Role adminRole = new Role(globalRoleAdmin, adminPermissionSet);
roleBasedAuthenticationStrategy.addRole(RoleType.Global, adminRole);
// builders
Role buildersRole = new Role(globalBuildRole, buildPermissionSet);
roleBasedAuthenticationStrategy.addRole(RoleType.Global, buildersRole);
// anonymous read
Role readRole = new Role(globalRoleRead, readPermissionSet);
roleBasedAuthenticationStrategy.addRole(RoleType.Global, readRole);
/**
* ===================================
*
* Roles -> Groups/Users
*
* ===================================
*/
access.admins.each { l ->
println("Granting admin to ${l}")
roleBasedAuthenticationStrategy.assignRole(RoleType.Global, adminRole, l);
}
access.builders.each { l ->
println("Granting builder to ${l}")
roleBasedAuthenticationStrategy.assignRole(RoleType.Global, buildersRole, l);
}
access.readers.each { l ->
println("Granting read to ${l}")
roleBasedAuthenticationStrategy.assignRole(RoleType.Global, readRole, l);
}
Jenkins.instance.save()
{
"admins": [
"groupA",
"userA"
],
"builders": [
"groupB",
"userB"
],
"readers": ["anonymous"]
}
@Gold-Cobra
Copy link

Hi,
in your script you have a typo. See the link.
Wrong variable name
You need to use the variable globalBuildRole .

Greetings

@mllrjb
Copy link
Author

mllrjb commented Nov 8, 2017

Good catch @Gold-Cobra!

@jvenkat255
Copy link

Hi,

I'm working on role-strategy in Jenkins through groovy script. I didn't get the JSON url, I don't know how to give JSON url. Can you please give me suggestion.
Thanks in adavance

@couturiehe01
Copy link

Here is an update on the role-authz.groovy script to use either a local file or a URL as json :

if (!env.AUTHZ_JSON_FILE && !env.AUTHZ_JSON_URL) {
  println "Warning! Neither env.AUTHZ_JSON_FILE nor env.AUTHZ_JSON_URL specified!"
  println "Granting anonymous admin access"
} else {
  if (env.AUTHZ_JSON_FILE)  {
    println "Get role authorizations from file ${env.AUTHZ_JSON_FILE}"
    File f = new File(env.AUTHZ_JSON_FILE)
    def jsonSlurper = new JsonSlurper()
    def jsonText = f.getText()
    access = jsonSlurper.parseText( jsonText )
  } else {
    println "Get role authorizations from URL ${env.AUTHZ_JSON_URL}"
    URL jsonUrl = new URL(env.AUTHZ_JSON_URL);
    access = new JsonSlurper().parse(jsonUrl);
  }
}

You just need to set either AUTHZ_JSON_FILE or AUTHZ_JSON_URL variable

@mllrjb
Copy link
Author

mllrjb commented Jun 20, 2019

Thanks @couturiehe01! Incorporated your changes.

@mllrjb
Copy link
Author

mllrjb commented Jun 20, 2019

@jvenkat255 - sorry, didn't see your question. You'll need to set an environment variable on your system so that Jenkins can pick it up, e.g. export AUTHZ_JSON_URL=http://company.com/auth.json. Depending on how you're executing Jenkins, the way you set your environment variable is going to vary. If you're still having trouble, feel free to drop me a message, my email is in my profile.

@couturiehe01
Copy link

couturiehe01 commented Jun 21, 2019

Here is a way to manage everything from a json file : roles, permissions and groups/users.
You can define as many roles as you want in the json file, without updating the groovy script.
File or URL values can be set either in the script itself or from environment variables.

json file:
{ "role": [ { "name": "admin", "users": [ "groupA", "groupA" ], "permissions": [ "hudson.model.Hudson.Administer", "hudson.model.Hudson.Read" ] }, { "name": "build", "users": [ "groupB", "userB" ], "permissions": [ "hudson.model.Hudson.Read", "hudson.model.Item.Build", "hudson.model.Item.Cancel", "hudson.model.Item.Read", "hudson.model.Run.Replay" ] }, { "name": "read", "users": [ "anonymous" ], "permissions": [ "hudson.model.Hudson.Read", "hudson.model.Item.Discover", "hudson.model.Item.Read" ] } ] }

grooy script:

import hudson.*
import hudson.security.*
import jenkins.model.*
import java.util.*
import com.michelin.cio.hudson.plugins.rolestrategy.*
import java.lang.reflect.*
import java.util.logging.*
import groovy.json.*

def env = System.getenv()

/**
 * ==========================================
 * Default roles / permissions / groups-users
 * ==========================================
 */
def access = [
    role: [[ name:"Admin", 
             users:["anonymous"], 
             permissions:["hudson.model.Hudson.Administer", "hudson.model.Hudson.Read"]
          ]]
]

def AUTHZ_JSON_FILE = "" // you can set the default value here
def AUTHZ_JSON_URL  = "" // you can set the default value here

try { 
  if ( "${AUTHZ_JSON_FILE}" == "" && env.AUTHZ_JSON_FILE != null )
    // If default value is empty and env variable defined, use this env variable
    AUTHZ_JSON_FILE = "${env.AUTHZ_JSON_FILE}" 
} catch(ex) { }
try { 
  if ( "${AUTHZ_JSON_URL}" == "" && env.AUTHZ_JSON_URL != null )
    // If default value is empty and env variable defined, use this env variable
    AUTHZ_JSON_URL  = "${env.AUTHZ_JSON_URL}"  
} catch(ex) { }

if ( "${AUTHZ_JSON_FILE}" != "")  {
  /**
   * =================================================
   * Get roles, permissions and groups/users from file
   * =================================================
   */   
  println "Get role authorizations from file ${AUTHZ_JSON_FILE}"
  File f = new File(AUTHZ_JSON_FILE)
  def jsonSlurper = new JsonSlurper()
  def jsonText = f.getText()
  access = jsonSlurper.parseText( jsonText )
}
else if ( "${AUTHZ_JSON_URL}" != "") {
  /**
   * ================================================
   * Get roles, permissions and groups/users from URL
   * =================================================
   */   
  // Get roles and permissions from URL
  println "Get role authorizations from URL ${AUTHZ_JSON_URL}"
  URL jsonUrl = new URL(AUTHZ_JSON_URL);
  access = new JsonSlurper().parse(jsonUrl);
}
else {
  // Use default role, permissions and groups/users
  println "Warning! Neither AUTHZ_JSON_FILE nor AUTHZ_JSON_URL specified!"
  println "Granting anonymous admin access"
}

def roleBasedAuthenticationStrategy = new RoleBasedAuthorizationStrategy()
 Jenkins.instance.setAuthorizationStrategy(roleBasedAuthenticationStrategy)

/**
 * ===================================
 *         
 *               HACK
 * Inspired by https://issues.jenkins-ci.org/browse/JENKINS-23709
 * Deprecated by on https://github.com/jenkinsci/role-strategy-plugin/pull/12
 *
 * ===================================
 */

Constructor[] constrs = Role.class.getConstructors();
for (Constructor<?> c : constrs) {
  c.setAccessible(true);
}

// Make the method assignRole accessible
Method assignRoleMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod("assignRole", String.class, Role.class, String.class);
assignRoleMethod.setAccessible(true);
println("HACK! changing visibility of RoleBasedAuthorizationStrategy.assignRole")

/**
 * =============================================
 *       Set roles, permissions and groups/users
 * =============================================
 */

access.role.each { r ->
  // Set this role
  Set<Permission> thisPermissionSet = new HashSet<Permission>();
  println("\nGet ${r.name} role definition")
  
  // Get permissions for this role
  r.permissions.each { p ->
    def permission = Permission.fromId(p);
    if (permission != null) {
      println("Adding ${p} permission to ${r.name} role")
      thisPermissionSet.add(permission);
    } else {
      println("${p} is not a valid permission ID (ignoring)")
    }
  }
  // Permissions -> Role
  Role thisRole = new Role(r.name, thisPermissionSet);
  roleBasedAuthenticationStrategy.addRole(RoleBasedAuthorizationStrategy.GLOBAL, thisRole);

  //  Role -> Groups/Users
  r.users.each { l ->
    println("Granting ${r.name} to ${l}")
    roleBasedAuthenticationStrategy.assignRole(RoleBasedAuthorizationStrategy.GLOBAL, thisRole, l);  
  }
}

Jenkins.instance.save()

@njesper
Copy link

njesper commented Jul 11, 2019

I think this update have messed up your gist:
jenkinsci/role-strategy-plugin@8a8fb9a

  • The signature of assignRole seems to have changed

@mllrjb
Copy link
Author

mllrjb commented Jul 11, 2019

@njesper - you're right, looks like a couple changes might fix it:

roleBasedAuthenticationStrategy.assignRole(RoleBasedAuthorizationStrategy.GLOBAL...
// to
roleBasedAuthenticationStrategy.assignRole(RoleType.Global...
Method assignRoleMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod("assignRole", String.class, Role.class, String.class);
// to
Method assignRoleMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod("assignRole", RoleType.class, Role.class, String.class);

I'm not currently using the latest role-based auth plugin. Do you want to try this out and let me know if it works?

@njesper
Copy link

njesper commented Jul 12, 2019

Thanks for the quick reply! Very helpful code by the way! :-)

First attempt, modifying according to your lines above, @mllrjb, resulted in this log message:

WARNING: Failed to run script file:/var/lib/jenkins/init.groovy.d/role-auth.groovy
groovy.lang.MissingPropertyException: No such property: RoleType for class: role-auth
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
        at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:52)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:307)
        at role-auth.run(role-auth.groovy:76)
        at groovy.lang.GroovyShell.evaluate(GroovyShell.java:585)
        at jenkins.util.groovy.GroovyHookScript.execute(GroovyHookScript.java:136)
        at jenkins.util.groovy.GroovyHookScript.execute(GroovyHookScript.java:127)
        at jenkins.util.groovy.GroovyHookScript.run(GroovyHookScript.java:110)
        at hudson.init.impl.GroovyInitScript.init(GroovyInitScript.java:41)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at hudson.init.TaskMethodFinder.invoke(TaskMethodFinder.java:104)
        at hudson.init.TaskMethodFinder$TaskImpl.run(TaskMethodFinder.java:175)
        at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
        at jenkins.model.Jenkins$5.runTask(Jenkins.java:1091)
        at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
        at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

So I tried adding import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType, after having a look at RoleBasedAuthorizationStrategy.java and got this instead:

WARNING: Failed to run script file:/var/lib/jenkins/init.groovy.d/role-auth.groovy
groovy.lang.MissingMethodException: No signature of method: com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy.addRole() is applicable for argument types: (java.lang.String, com.michelin.cio.hudson.plugins.rolestrategy.Role) values: [globalRoles, com.michelin.cio.hudson.plugins.rolestrategy.Role@d27eae26]
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
        at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at role-auth.run(role-auth.groovy:124)
        at groovy.lang.GroovyShell.evaluate(GroovyShell.java:585)
        at jenkins.util.groovy.GroovyHookScript.execute(GroovyHookScript.java:136)
        at jenkins.util.groovy.GroovyHookScript.execute(GroovyHookScript.java:127)
        at jenkins.util.groovy.GroovyHookScript.run(GroovyHookScript.java:110)
        at hudson.init.impl.GroovyInitScript.init(GroovyInitScript.java:41)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at hudson.init.TaskMethodFinder.invoke(TaskMethodFinder.java:104)
        at hudson.init.TaskMethodFinder$TaskImpl.run(TaskMethodFinder.java:175)
        at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
        at jenkins.model.Jenkins$5.runTask(Jenkins.java:1091)
        at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
        at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

So not quite there yet...

@mllrjb
Copy link
Author

mllrjb commented Jul 15, 2019

@njesper - that's my bad, I added an else () block that was syntactically invalid. I've updated the snippet, see if that works for you now!

@couturiehe01
Copy link

couturiehe01 commented Jul 16, 2019

Updated code with RoleType

import hudson.*
import hudson.security.*
import jenkins.model.*
import java.util.*
import com.michelin.cio.hudson.plugins.rolestrategy.*
import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType;
import java.lang.reflect.*
import java.util.logging.*
import groovy.json.*

def env = System.getenv()

println("=== Configure roles / permissions / groups-users")

/**
 * ==========================================
 * Default roles / permissions / groups-users
 * ==========================================
 */
def access = [
    role: [[ name:"Admin", 
             users:["anonymous"], 
             permissions:["hudson.model.Hudson.Administer", "hudson.model.Hudson.Read"]
          ]]
]

def AUTHZ_JSON_FILE = "" // you can set the default value here
def AUTHZ_JSON_URL  = "" // you can set the default value here

try { 
  if ( "${AUTHZ_JSON_FILE}" == "" && env.AUTHZ_JSON_FILE != null )
    // If default value is empty and env variable defined, use this env variable
    AUTHZ_JSON_FILE = "${env.AUTHZ_JSON_FILE}" 
} catch(ex) { }
try { 
  if ( "${AUTHZ_JSON_URL}" == "" && env.AUTHZ_JSON_URL != null )
    // If default value is empty and env variable defined, use this env variable
    AUTHZ_JSON_URL  = "${env.AUTHZ_JSON_URL}"  
} catch(ex) { }

if ( "${AUTHZ_JSON_FILE}" != "")  {
  /**
   * =================================================
   * Get roles, permissions and groups/users from file
   * =================================================
   */   
  println "Get role authorizations from file ${AUTHZ_JSON_FILE}"
  File f = new File(AUTHZ_JSON_FILE)
  def jsonSlurper = new JsonSlurper()
  def jsonText = f.getText()
  access = jsonSlurper.parseText( jsonText )
}
else if ( "${AUTHZ_JSON_URL}" != "") {
  /**
   * ================================================
   * Get roles, permissions and groups/users from URL
   * =================================================
   */   
  // Get roles and permissions from URL
  println "Get role authorizations from URL ${AUTHZ_JSON_URL}"
  URL jsonUrl = new URL(AUTHZ_JSON_URL);
  access = new JsonSlurper().parse(jsonUrl);
}
else {
  // Use default role, permissions and groups/users
  println "Warning! Neither AUTHZ_JSON_FILE nor AUTHZ_JSON_URL specified!"
  println "Granting anonymous admin access"
}

def roleBasedAuthenticationStrategy = new RoleBasedAuthorizationStrategy()
 Jenkins.instance.setAuthorizationStrategy(roleBasedAuthenticationStrategy)

/**
 * ===================================
 *         
 *               HACK
 * Inspired by https://issues.jenkins-ci.org/browse/JENKINS-23709
 * Deprecated by on https://github.com/jenkinsci/role-strategy-plugin/pull/12
 *
 * ===================================
 */

Constructor[] constrs = Role.class.getConstructors();
for (Constructor<?> c : constrs) {
  c.setAccessible(true);
}

// Make the method assignRole accessible
//Method assignRoleMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod("assignRole", String.class, Role.class, String.class);
//assignRoleMethod.setAccessible(true);
//println("HACK! changing visibility of RoleBasedAuthorizationStrategy.assignRole")

/**
 * =============================================
 *       Set roles, permissions and groups/users
 * =============================================
 */

access.role.each { r ->
  // Set this role
  Set<Permission> thisPermissionSet = new HashSet<Permission>();
  println("\nGet ${r.name} role definition")
  
  // Get permissions for this role
  r.permissions.each { p ->
    def permission = Permission.fromId(p);
    if (permission != null) {
      println("Adding ${p} permission to ${r.name} role")
      thisPermissionSet.add(permission);
    } else {
      println("${p} is not a valid permission ID (ignoring)")
    }
  }
  // Permissions -> Role
  Role thisRole = new Role(r.name, thisPermissionSet);
  roleBasedAuthenticationStrategy.addRole(RoleType.fromString(RoleBasedAuthorizationStrategy.GLOBAL), thisRole);

  //  Role -> Groups/Users
  r.users.each { l ->
    println("Granting ${r.name} to ${l}")
    roleBasedAuthenticationStrategy.assignRole(RoleType.fromString(RoleBasedAuthorizationStrategy.GLOBAL), thisRole, l);  
  }
}

Jenkins.instance.save()

Unchanged json file format
{ "role": [ { "name": "admin", "users": [ "groupA", "groupA" ], "permissions": [ "hudson.model.Hudson.Administer", "hudson.model.Hudson.Read" ] }, { "name": "build", "users": [ "groupB", "userB" ], "permissions": [ "hudson.model.Hudson.Read", "hudson.model.Item.Build", "hudson.model.Item.Cancel", "hudson.model.Item.Read", "hudson.model.Run.Replay" ] }, { "name": "read", "users": [ "anonymous" ], "permissions": [ "hudson.model.Hudson.Read", "hudson.model.Item.Discover", "hudson.model.Item.Read" ] } ] }

@njesper
Copy link

njesper commented Jul 19, 2019

Thanks a lot! I got it working again :-)

I'm running a modified version of the script, so I had to have a look at the diffs to figure out how to update my version. I don't think I was affected by the if-error, but rather a mistake by me; I only changed RoleBasedAuthorizationStrategy.GLOBAL to RoleType.Global for assignRole, but not for addRole.

  • Looks like this patch is missing in the script in your previous comment ;-)

Big Kudos!

@john-fletcher
Copy link

john-fletcher commented Sep 16, 2019

@mllrjb appriciate your help here.

I tried this script and roles.json file . but this sets security realm / authorization in such a way that I no longer able to login to Jenkins.
"missing overall read permissions"
again i had to false , which again removes the entire security. :(

can you please post latest working script and json file ?

@couturiehe01
Copy link

John-Fletcher,
This script does not manage the authentication part, only the authorization one. Please double check if your issue comes from somewhere else.

@ipeacocks
Copy link

ipeacocks commented May 15, 2020

@couturiehe01 you example helped me a lot! It's more manual than yours but maybe it will be useful for somebody

import hudson.*
import hudson.model.*
import hudson.security.*
import jenkins.*
import jenkins.model.*
import java.util.*
import com.michelin.cio.hudson.plugins.rolestrategy.*
import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType;
import java.lang.reflect.*
import java.util.logging.*
import groovy.json.*

def env = System.getenv()

// Roles
// def globalRoleRead = "read"
def globalRoleAdmin = "admin"
def globalRoleRemoteAgent = "remote_agent"

def jenkinsInstance = Jenkins.getInstance()
def currentAuthenticationStrategy = Hudson.instance.getAuthorizationStrategy()

Thread.start {
    sleep 15000
    if (currentAuthenticationStrategy instanceof RoleBasedAuthorizationStrategy) {
      println "Role based authorisation already enabled."
      println "Exiting script..."
      return
    } else {
      println "Enabling role based authorisation strategy..."
    }

    // Set new authentication strategy
    RoleBasedAuthorizationStrategy roleBasedAuthenticationStrategy = new RoleBasedAuthorizationStrategy()
    jenkinsInstance.setAuthorizationStrategy(roleBasedAuthenticationStrategy)

    Constructor[] constrs = Role.class.getConstructors();
    for (Constructor<?> c : constrs) {
      c.setAccessible(true);
    }

    // Create admin set of permissions
    Set<Permission> adminPermissions = new HashSet<Permission>();
    adminPermissions.add(Permission.fromId("hudson.model.View.Delete"));
    adminPermissions.add(Permission.fromId("hudson.model.Computer.Connect"));
    adminPermissions.add(Permission.fromId("hudson.model.Run.Delete"));
    adminPermissions.add(Permission.fromId("hudson.model.Hudson.UploadPlugins"));
    adminPermissions.add(Permission.fromId("com.cloudbees.plugins.credentials.CredentialsProvider.ManageDomains"));
    adminPermissions.add(Permission.fromId("hudson.model.Computer.Create"));
    adminPermissions.add(Permission.fromId("hudson.model.View.Configure"));
    adminPermissions.add(Permission.fromId("hudson.model.Hudson.ConfigureUpdateCenter"));
    adminPermissions.add(Permission.fromId("hudson.model.Computer.Build"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Configure"));
    adminPermissions.add(Permission.fromId("hudson.model.Hudson.Administer"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Cancel"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Read"));
    adminPermissions.add(Permission.fromId("com.cloudbees.plugins.credentials.CredentialsProvider.View"));
    adminPermissions.add(Permission.fromId("hudson.model.Computer.Delete"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Build"));
    adminPermissions.add(Permission.fromId("hudson.scm.SCM.Tag"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Discover"));
    adminPermissions.add(Permission.fromId("hudson.model.Hudson.Read"));
    adminPermissions.add(Permission.fromId("com.cloudbees.plugins.credentials.CredentialsProvider.Update"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Create"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Move"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Workspace"));
    adminPermissions.add(Permission.fromId("com.cloudbees.plugins.credentials.CredentialsProvider.Delete"));
    adminPermissions.add(Permission.fromId("hudson.model.View.Read"));
    adminPermissions.add(Permission.fromId("hudson.model.Hudson.RunScripts"));
    adminPermissions.add(Permission.fromId("hudson.model.View.Create"));
    adminPermissions.add(Permission.fromId("hudson.model.Item.Delete"));
    adminPermissions.add(Permission.fromId("hudson.model.Computer.Configure"));
    adminPermissions.add(Permission.fromId("com.cloudbees.plugins.credentials.CredentialsProvider.Create"));
    adminPermissions.add(Permission.fromId("hudson.model.Computer.Disconnect"));
    adminPermissions.add(Permission.fromId("hudson.model.Run.Update"));

    // Create the admin Role
    Role adminRole = new Role(globalRoleAdmin, adminPermissions);
    roleBasedAuthenticationStrategy.addRole(RoleType.fromString(RoleBasedAuthorizationStrategy.GLOBAL), adminRole);

    //------------------------------------------------------------------------------------------

    // Create set of permissions for remote_agent
    Set<Permission> remoteAgentPermissions = new HashSet<Permission>();
    remoteAgentPermissions.add(Permission.fromId("hudson.model.Hudson.Read"));
    remoteAgentPermissions.add(Permission.fromId("hudson.model.Computer.Connect"));
    remoteAgentPermissions.add(Permission.fromId("hudson.model.Computer.Create"));
    remoteAgentPermissions.add(Permission.fromId("hudson.model.Computer.Build"));
    remoteAgentPermissions.add(Permission.fromId("hudson.model.Computer.Delete"));
    remoteAgentPermissions.add(Permission.fromId("hudson.model.Computer.Configure"));
    remoteAgentPermissions.add(Permission.fromId("hudson.model.Computer.Disconnect"));

    // Create the Role for remote_agent
    Role remoteAgentRole = new Role(globalRoleRemoteAgent, remoteAgentPermissions);
    roleBasedAuthenticationStrategy.addRole(RoleType.fromString(RoleBasedAuthorizationStrategy.GLOBAL), remoteAgentRole);

    // --------------------------------------------------------------------------------------------------------

    // Creating admin user
    def hudsonRealm = new HudsonPrivateSecurityRealm(false)
    hudsonRealm.createAccount(env.JENKINS_USER, env.JENKINS_PASS)
    jenkinsInstance.setSecurityRealm(hudsonRealm)

    // Assign the role
    roleBasedAuthenticationStrategy.assignRole(RoleType.fromString(RoleBasedAuthorizationStrategy.GLOBAL), adminRole, env.JENKINS_USER);
    println "Admin role created...OK"

    // --------------------------------------------------------------------------------------------------------

    // Creating remote_agent user
    def hudsonRealm_2 = new HudsonPrivateSecurityRealm(false)
    hudsonRealm_2.createAccount(env.JENKINS_RA_USER, env.JENKINS_RA_PASS)
    jenkinsInstance.setSecurityRealm(hudsonRealm_2)

    // Assign the role
    roleBasedAuthenticationStrategy.assignRole(RoleType.fromString(RoleBasedAuthorizationStrategy.GLOBAL), remoteAgentRole, env.JENKINS_RA_USER);
    println "Remote Agent role created...OK"


    // Save the state
    println "Saving changes."
    jenkinsInstance.save()
}

JENKINS_USER is for admin, JENKINS_RA_USER is for remote_agent user (for jenkins agents connecting). Users and pass' are taken from env vars.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment