security & authorization
security
[!NOTE|label:references:]
import hudson.security.*
import jenkins.security.*
import jenkins.model.Jenkins
def jenkins = jenkins.model.Jenkins.instance
println jenkins.securityRealm
println jenkins.authorizationStrategy
// -- result --
// hudson.security.LDAPSecurityRealm@7d090e41
// hudson.security.ProjectMatrixAuthorizationStrategy@6d51bb9d
authorization strategy
reference:
decrypt credentials.xml
[!NOTE|label:references:]
hudson.util.Secret.fromString('{..string..}').getPlainText()
// or
hudson.util.Secret.fromString('{..string..}').getEncryptedValue()
example
hudson.util.Secret.fromString('{AQAAABAAAAAQszhBK4LXdjzjqP/7w8yQWbD4+Kf1ql4XnYEnPUyvP2o=}').getPlainText() // 123456
hudson.security.Permission.getAll().each { p ->
println "${p.name} :" +
"\n\t${p.id} : ${p.description}"
}
import hudson.security.GlobalMatrixAuthorizationStrategy import hudson.security.Permission import hudson.security.ProjectMatrixAuthorizationStrategy import jenkins.model.Jenkins String shortName( Permission p ) { Map<String, String> replacement = [ 'Hudson' : 'Overall' , 'Computer' : 'Agent' , 'Item' : 'Job' , 'CredentialsProvider' : 'Credentials' ] p.id .tokenize('.')[-2..-1] .collect { replacement.get(it) ?: it } .join(' ') } Map<String, Permission> permissionIds = Permission.all.findAll { permission -> List<String> nonConfigurablePerms = ['RunScripts', 'UploadPlugins', 'ConfigureUpdateCenter'] permission.enabled && ! permission.id.startsWith('hudson.security.Permission') && ! nonConfigurablePerms.any { permission.id.endsWith(it) } }.collect { permission -> [ (shortName(permission)): permission ] }.sum() // show result println permissionIds.collect { it.key + ' : ' + it.value.id }.join ('\n') 'DONE'
get current authorization strategy class
import hudson.model.*
import hudson.security.*
Hudson instance = jenkins.model.Jenkins.instance
def strategy = instance.getAuthorizationStrategy()
println strategy.getClass()
// result
// class hudson.security.ProjectMatrixAuthorizationStrategy
get raw authorization and permissions info
jenkins.model.Jenkins.instance
.authorizationStrategy
.grantedPermissions
.collect{ p, u -> [ (p.id), u ] }
or
jenkins.model.Jenkins.instance .authorizationStrategy .grantedPermissions .each { p, u -> println "\n${p} :\n\t${u}" }
ProjectMatrixAuthorizationStrategy
grant permission to user
import hudson.security.GlobalMatrixAuthorizationStrategy
import hudson.security.Permission
import hudson.security.ProjectMatrixAuthorizationStrategy
import jenkins.model.Jenkins
ProjectMatrixAuthorizationStrategy authorizationStrategy = new ProjectMatrixAuthorizationStrategy()
String id = 'hudson.model.Hudson.Administer'
String user = 'marslo'
authorizationStrategy.add( Permission.fromId(id), user )
// save strategy
jenkins.model.Jenkins.instance.authorizationStrategy = authorizationStrategy
jenkins.model.Jenkins.instance.save()
create new instance
new
import hudson.security.* ProjectMatrixAuthorizationStrategy authorizationStrategy = new ProjectMatrixAuthorizationStrategy()
import hudson.model.* import hudson.security.* def strategy = jenkins.model.Jenkins.instance.getAuthorizationStrategy() def authorizationStrategy = strategy.class.newInstance()
String instanceName = 'hudson.security.ProjectMatrixAuthorizationStrategy' def strategy = Class.forName(instanceName).newInstance() println strategy.class // -- result -- // class hudson.security.ProjectMatrixAuthorizationStrategy
get groups list
import hudson.model.* import hudson.security.* ProjectMatrixAuthorizationStrategy authorizationStrategy = new ProjectMatrixAuthorizationStrategy() println authorizationStrategy.getGroups()
RoleBasedAuthorizationStrategy
add 'admin' user to all permissions
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.*
import jenkins.*
import com.michelin.cio.hudson.plugins.rolestrategy.*
String admin = 'admin'
// turn security on
RoleBasedAuthorizationStrategy authorizationStrategy = new RoleBasedAuthorizationStrategy()
// ProjectMatrixAuthorizationStrategy authorizationStrategy = new ProjectMatrixAuthorizationStrategy()
jenkins.model.Jenkins.instance.setAuthorizationStrategy(authorizationStrategy)
Constructor[] constrs = Role.class.getConstructors()
constrs.each { Constructor c -> c.setAccessible(true) }
Method assignRoleMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod( "assignRole", String.class, Role.class, String.class )
assignRoleMethod.setAccessible( true )
Set<Permission> adminPermissions = new HashSet<Permission>()
hudson.security.Permission.getAll(){ adminPermissions.add(Permission.fromId(it) }
Role adminRole = new Role( admin, adminPermissions )
authorizationStrategy.addRole( RoleBasedAuthorizationStrategy.GLOBAL, adminRole )
crumb issuer
[!NOTE|label:references:]
get crumb issuer
import hudson.security.csrf.DefaultCrumbIssuer
DefaultCrumbIssuer issuer = jenkins.model.Jenkins.instance.crumbIssuer
String jenkinsCrumb = "${issuer.crumbRequestField}:${issuer.crumb}"
println jenkinsCrumb
// Jenkins-Crumb:b8a9cd5***********
set crumb issuer
import jenkins.model.Jenkins
Jenkins jenkins = jenkins.model.Jenkins.instance
jenkins.setCrumbIssuer(new DefaultCrumbIssuer(true))
jenkins.save()
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.Stapler
AsyncResourceDisposer disposer = AsyncResourceDisposer.get()
backlog = disposer.getBacklog()
stap = Stapler
resp = stap.getCurrentResponse()
disposer.backlog.each { item ->
disposer.doStopTracking( item.id, resp )
}
or via curl
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer import org.jenkinsci.plugins.strictcrumbissuer.StrictCrumbIssuer AsyncResourceDisposer disposer = AsyncResourceDisposer.get() StrictCrumbIssuer issuer = jenkins.model.Jenkins.instance.crumbIssuer String jenkinsCrumb = "${issuer.crumbRequestField}:${issuer.crumb}" String url = jenkins.model.Jenkins.instance.rootUrl + disposer.url disposer.getBacklog().each { item -> println "\n${item.id} : \t${url}/stopTracking/?id=${item.id} : \t${item.class.simpleName} : \n" + "\t${item.getLastState().getDisplayName()} : \n" + "\t${item.getDisposable().node} : ${item.getDisposable().path}\n" + "\t${item.toString()}" println "removeing ${item.id} : " [ 'bash', '-c', 'curl -v -s ' + '-u <user>:<token> ' + '-X POST ' + "-H \"Content-Type: application/json\" " + "-H \"Accept: application/json\" " + "-H \"${jenkinsCrumb}\" " + "${url}/stopTracking/?id=${item.id} " ].execute().with{ def stdout = new StringBuffer() def stderr = new StringBuffer() it.waitForProcessOutput( stdout, stderr ) println "EXIT CODE: ${it.exitValue()}" println "ERROR: ${stderr}" println "OUTPUT: ${stdout}" } }
get crumb via cmd
[!TIP|local:references:]
curl
# after 2.176.2 $ SERVER="https://localhost:8080" $ COOKIEJAR="$(mktemp)" $ CRUMB=$(curl -u "admin:admin" -s --cookie-jar "$COOKIEJAR" "$SERVER/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)") # verify $ echo $CRUMB Jenkins-Crumb:786**********************************************************932 # trigger a build $ curl -X POST \ -u "admin:admin" \ --cookie "$COOKIEJAR" \ -H "$CRUMB" \ https://${SERVER}/job/sandbox/build # to run script $ curl -d "script=System.getProperties()" \ -u "admin:admin" \ --cookie "$COOKIEJAR" \ -H "$CRUMB" \ https://${SERVER}/scriptText
via wget
# after 2.176.2 $ SERVER="https://localhost:8080" $ COOKIEJAR="$(mktemp)" $ CRUMB="$(wget --quiet --user=admin --password=admin --auth-no-challenge --save-cookies "$COOKIEJAR" --keep-session-cookies -q --output-document - "$SERVER/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)")" $ wget --user=admin --password=admin \ --auth-no-challenge \ --load-cookies "$COOKIEJAR" \ --header="$CRUMB" \ --post-data="" \ --quiet \ "$SERVER"/job/someJob/build
credential
references:
[!TIP|label:something else :]
api :
list all credentials
import com.cloudbees.plugins.credentials.common.StandardCredentials
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey;
import com.cloudbees.plugins.credentials.SystemCredentialsProvider
CredentialsProvider.lookupCredentials( StandardCredentials.class, jenkins.model.Jenkins.instance)
.sort{ it.id }
.each{
switch( it.class.simpleName ) {
case 'BasicSSHUserPrivateKey' :
println """
type : ${it.class.simpleName}
id : ${it.id}
scope : ${it.scope}
username : ${it.username}
description : ${it.description}
privateKeysLastModified : ${it.privateKeysLastModified}
usernameSecret : ${it.usernameSecret ?: 'false'}
privateKeys : ${it.privateKeys.join('\n')}
"""
break;
case 'CertificateCredentialsImpl' :
println """
type : ${it.class.simpleName}
id : ${it.id}
scope : ${it.scope}
password : ${it.password}
description : ${it.description}
keyStore.type : ${it.keyStore.type}
keyStoreSource.keyStoreBytes : ${it.keyStoreSource.keyStoreBytes}
keyStoreSource.uploadedKeystoreBytes : ${it.keyStoreSource.uploadedKeystoreBytes}
properties : ${it.properties}
properties.password : ${it.properties.password}
properties.passwordEmpty : ${it.properties.passwordEmpty}
properties.keyStore.type : ${it.properties.keyStore.type}
"""
break;
case 'StringCredentialsImpl' :
println """
type : ${it.class.simpleName}
id : ${it.id}
secret : ${it.secret}
description : ${it.description}
scope : ${it.scope}
"""
break;
case 'UsernamePasswordCredentialsImpl' :
println """
type : ${it.class.simpleName}
id : ${it.id}
username : ${it.username}
password : ${it.password}
description : ${it.description}
usernameSecret : ${it.usernameSecret ?: 'false'}
"""
break;
}
}
with vault
import com.cloudbees.plugins.credentials.common.StandardCredentials import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials import com.cloudbees.plugins.credentials.CredentialsProvider import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey; import com.cloudbees.plugins.credentials.SystemCredentialsProvider import com.datapipe.jenkins.vault.credentials.common.VaultUsernamePasswordCredential import com.datapipe.jenkins.vault.credentials.VaultAppRoleCredential import com.datapipe.jenkins.vault.credentials.common.VaultSSHUserPrivateKeyImpl import com.datapipe.jenkins.vault.credentials.common.VaultStringCredentialImpl CredentialsProvider.lookupCredentials( StandardCredentials.class, jenkins.model.Jenkins.instance) .sort{ it.id } .each{ switch( it.class.simpleName ) { case 'BasicSSHUserPrivateKey' : println """ type : ${it.class.simpleName} id : ${it.id} scope : ${it.scope} username : ${it.username} description : ${it.description} privateKeysLastModified : ${it.privateKeysLastModified} usernameSecret : ${it.usernameSecret ?: 'false'} privateKeys : ${it.privateKeys.join('\n')} """ break; case 'CertificateCredentialsImpl' : println """ type : ${it.class.simpleName} id : ${it.id} scope : ${it.scope} password : ${it.password} description : ${it.description} keyStore.type : ${it.keyStore.type} keyStoreSource.keyStoreBytes : ${it.keyStoreSource.keyStoreBytes} keyStoreSource.uploadedKeystoreBytes : ${it.keyStoreSource.uploadedKeystoreBytes} properties : ${it.properties} properties.password : ${it.properties.password} properties.passwordEmpty : ${it.properties.passwordEmpty} properties.keyStore.type : ${it.properties.keyStore.type} """ break; case 'StringCredentialsImpl' : println """ type : ${it.class.simpleName} id : ${it.id} secret : ${it.secret} description : ${it.description} scope : ${it.scope} """ break; case 'UsernamePasswordCredentialsImpl' : println """ type : ${it.class.simpleName} id : ${it.id} username : ${it.username} password : ${it.password} description : ${it.description} usernameSecret : ${it.usernameSecret ?: 'false'} """ break; case 'VaultUsernamePasswordCredentialImpl' : println """ type : ${it.class.simpleName} engineVersion : ${it.engineVersion} id : ${it.id} scope : ${it.scope} description : ${it.description} displayName : ${it.displayName} path : ${it.path} usernameKey : ${it.usernameKey} username : ${it.username} passwordKey : ${it.passwordKey} password : ${it.password} usernameSecret : ${it.usernameSecret ?: 'false'} """ break; case 'VaultAppRoleCredential': println """ type : ${it.class.simpleName} id : ${it.id} roleId : ${it.roleId} secretId : ${it.secretId} path : ${it.path} namespace : ${it.namespace} scope : ${it.scope} description : ${it.description} """ break; case 'VaultSSHUserPrivateKeyImpl': println """ type : ${it.class.simpleName} engineVersion : ${it.engineVersion} id : ${it.id} scope : ${it.scope} description : ${it.description} displayName : ${it.displayName} usernameSecret : ${it.usernameSecret ?: 'false'} usernameKey : ${it.usernameKey} username : ${it.username} privateKeyKey : ${it.privateKeyKey} privateKeys : ${it.privateKeys.join('\n')} passphraseKey : ${it.passphraseKey} passphrase : ${ it.passphrase} """ break; case 'VaultStringCredentialImpl': println """ type : ${it.class.simpleName} engineVersion : ${it.engineVersion} id : ${it.id} displayName : ${it.displayName} description : ${it.description} prefixPath : ${it.prefixPath} path : ${it.path} secret : ${it.secret} valutKey : ${it.vaultKey} """ break; } }
import com.cloudbees.plugins.credentials.CredentialsProvider import com.cloudbees.plugins.credentials.Credentials import com.cloudbees.plugins.credentials.domains.Domain import jenkins.model.Jenkins Closure indent = { String text, int indentationCount -> text.replaceAll( "(?m)^", "\t" * indentationCount ) } Jenkins.get().allItems().collectMany{ CredentialsProvider.lookupStores(it).toList() }.unique().forEach { store -> Map<Domain, List<Credentials>> domainCreds = [:] store.domains.each { domainCreds.put(it, store.getCredentials(it))} if ( domainCreds.collectMany{it.value}.empty ) { return } def shortenedClassName = store.getClass().name.substring(store.getClass().name.lastIndexOf(".") + 1) println "Credentials for store context: ${store.contextDisplayName}, of type $shortenedClassName" domainCreds.forEach { domain , creds -> println indent( "Domain: ${domain.name}", 1 ) creds.each { cred -> cred.properties.each { prop, val -> println indent( "$prop = \"$val\"", 2 ) } println indent( '-----------------------', 2 ) } } }
StandardUsernamePasswordCredentials
import com.cloudbees.plugins.credentials.common.StandardCredentials
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials
import com.cloudbees.plugins.credentials.CredentialsProvider
List<StandardUsernamePasswordCredentials> creds = CredentialsProvider.lookupCredentials(
StandardUsernamePasswordCredentials.class,
jenkins.model.Jenkins.instance
)
creds.sort{it.id}.each {
println """
id : ${it.id}
username : ${it.username}
password : ${it.password}
description : ${it.description}
usernameSecret : ${it.usernameSecret ?: 'false'}
"""
}
'DONE'
BasicSSHUserPrivateKey
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey
import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey;
List<BasicSSHUserPrivateKey> creds = CredentialsProvider.lookupCredentials(
SSHUserPrivateKey.class , // or BasicSSHUserPrivateKey.class
jenkins.model.Jenkins.instance
).sort{ it.id }
.each {
println """
id : ${it.id}
scope : ${it.scope}
username : ${it.username}
description : ${it.description}
privateKeysLastModified : ${it.privateKeysLastModified}
usernameSecret : ${it.usernameSecret ?: 'false'}
privateKeys : ${it.privateKeys.join('\n')}
"""
}
CertificateCredentials
import com.cloudbees.plugins.credentials.common.StandardCredentials
import com.cloudbees.plugins.credentials.common.CertificateCredentials
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.cloudbees.plugins.credentials.SecretBytes
import com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl
CredentialsProvider.lookupCredentials(
CertificateCredentials.class,
jenkins.model.Jenkins.instance
).sort{ it.id }
.each {
SecretBytes secretKey = it.properties.keyStoreSource.uploadedKeystoreBytes
println """
id : ${it.id}
password : ${it.password}
description : ${it.description}
scope : ${it.scope}
keyStore.type : ${it.properties.keyStore.type}
SecretBytes.decrypt : ${SecretBytes.decrypt(it.keyStoreSource.keyStoreBytes)}
encryptedValue : ${hudson.util.Secret.fromString(secretKey.toString()).encryptedValue}
plainData : ${new String(SecretBytes.fromString(secretKey.toString()).getPlainData(), "ASCII")}
"""
}
'DONE'
SystemCredentialsProvider
import com.cloudbees.plugins.credentials.SystemCredentialsProvider
SystemCredentialsProvider systemCredentialsProvider = jenkins.model.Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
).first()
systemCredentialsProvider.credentials.each {
println """
id : ${it.id}
description : ${it.description}
scope : ${it.scope}
secret : ${it.secret}
"""
}
'DONE'
vault
[!NOTE|label:references:]
scripts:
[!NOTE|label:references:]
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.datapipe.jenkins.vault.credentials.VaultAppRoleCredential
List<VaultAppRoleCredential> creds = CredentialsProvider.lookupCredentials(
VaultAppRoleCredential.class ,
jenkins.model.Jenkins.instance
).sort{ it.id }
creds.each {
println """
type : ${it.class.simpleName}
scope : ${it.scope}
engineVersion : ${it.engineVersion}
id : ${it.id}
description : ${it.description}
namespace : ${it.namespace}
path : ${it.path}
secretId : ${it.secretId}
roleId : ${it.roleId}
"""
}
'DONE'
VaultUsernamePasswordCredential
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.datapipe.jenkins.vault.credentials.common.VaultUsernamePasswordCredential
List<VaultUsernamePasswordCredential> creds = CredentialsProvider.lookupCredentials(
VaultUsernamePasswordCredential.class ,
jenkins.model.Jenkins.instance
).sort{ it.id }
creds.each {
println """
type : ${it.class.simpleName}
scope : ${it.scope}
engineVersion : ${it.engineVersion}
id : ${it.id}
description : ${it.description}
path : ${it.path}
usernameKey : ${it.usernameKey}
username : ${it.username}
passwordKey : ${it.passwordKey}
password : ${it.password}
usernameSecret : ${it.usernameSecret ?: 'false'}
"""
}
'DONE'
VaultUsernamePasswordCredentialImpl
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.datapipe.jenkins.vault.credentials.common.VaultUsernamePasswordCredentialImpl
List<VaultUsernamePasswordCredentialImpl> creds = CredentialsProvider.lookupCredentials(
VaultUsernamePasswordCredentialImpl.class ,
jenkins.model.Jenkins.instance
).sort{ it.id }
creds.each {
println """
type : ${it.class.simpleName}
engineVersion : ${it.engineVersion}
id : ${it.id}
scope : ${it.scope}
description : ${it.description}
displayName : ${it.displayName}
path : ${it.path}
usernameKey : ${it.usernameKey}
username : ${it.username}
passwordKey : ${it.passwordKey}
password : ${it.password}
usernameSecret : ${it.usernameSecret ?: 'false'}
"""
}
'DONE'
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.datapipe.jenkins.vault.credentials.common.VaultSSHUserPrivateKeyImpl
List<VaultSSHUserPrivateKeyImpl> creds = CredentialsProvider.lookupCredentials(
VaultSSHUserPrivateKeyImpl.class,
jenkins.model.Jenkins.instance
).sort{ it.id }
creds.each {
println """
type : ${it.class.simpleName}
scope : ${it.scope}
engineVersion : ${it.engineVersion}
id : ${it.id}
description : ${it.description}
displayName : ${it.displayName}
usernameSecret : ${it.usernameSecret ?: 'false'}
usernameKey : ${it.usernameKey}
username : ${it.username}
privateKeyKey : ${it.privateKeyKey}
privateKeys : ${it.privateKeys.collect{ it.trim() }}
privateKey : ${it.privateKey}
passphraseKey : ${it.passphraseKey}
passphrase : ${ it.passphrase}
"""
}
'DONE'
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.datapipe.jenkins.vault.credentials.common.VaultStringCredentialImpl
List<VaultStringCredentialImpl> creds = CredentialsProvider.lookupCredentials(
VaultStringCredentialImpl.class ,
jenkins.model.Jenkins.instance
).sort{ it.id }
creds.each {
println """
type : ${it.class.simpleName}
engineVersion : ${it.engineVersion}
scope : ${it.scope}
id : ${it.id}
description : ${it.description}
displayName : ${it.displayName}
prefixPath : ${it.prefixPath}
path : ${it.path}
valutKey : ${it.vaultKey}
secret : ${it.secret}
"""
}
'DONE'
encrypt/decrypt password
import hudson.util.Secret
String original = 'marslo'
Secret secret = Secret.fromString( original )
String encrypted = secret.getEncryptedValue()
Secret decrypted = Secret.decrypt( encrypted )
println """
original : ${original}
encrypted : ${encrypted}
decrypted : ${decrypted}
"""
// original : marslo
// encrypted : {AQAAABAAAAAQyF78QAdq9bWCAeUi1VdYO7cB0CfG29KrvwZUU506zig=}
// decrypted : marslo
or
println hudson.util.Secret.fromString('marslo').getEncryptedValue() println hudson.util.Secret.decrypt( hudson.util.Secret.fromString('marslo').getEncryptedValue() // {AQAAABAAAAAQfwTdrtsFbS2MyOOA3kuO01p21CsVsSIpZg9FE1TMlMQ=} // marslo
tricky
This permission can be enabled by setting the system property jenkins.security.SystemReadPermission to true or installing the Extended Read Permission plugin.
This permission can be enabled by setting the system property jenkins.security.ManagePermission to true or installing the Overall/Manage permission enabler plugin.
Last updated