Automate Jenkins Keycloak plugin with groovy script - jenkins

i try to 100% automating the deployment of Jenkins with Keycloak plugin with Docker-compose. The objectiv is that we do not want to do anything but run a single command.
To automate Jenkins, I tried to use the Jenkins API but the Groovy script seems to be the best and easiest solution. The problem is that I am not a developper ...
I try something like this, but it's failed at Keycloak conf :
Failed to run script file:/var/jenkins_home/init.groovy.d/init.groovy groovy.lang.GroovyRuntimeException: Could not find matching constructor for: org.jenkinsci.plugins.KeycloakSecurityRealm(java.lang.Boolean)
import jenkins.model.*
import hudson.security.*
import org.jenkinsci.plugins.*
def instance = Jenkins.getInstance()
def env = System.getenv()
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
String password = env.JENKINS_PASSWORD
hudsonRealm.createAccount("admin", password)
instance.setSecurityRealm(hudsonRealm)
instance.save()
def keycloak_realm = new KeycloakSecurityRealm(true)
instance.setSecurityRealm(keycloak_realm)
instance.setAuthorizationStrategy(new FullControlOnceLoggedInAuthorizationStrategy())
instance.save()
In the end, i want to
create an admin user
configure the Keycloak plugin
set the users autorisations.
Thanks you in advance for your help :)

A possibly outdated issue, but I would like to share that I also had problems using Groovy scripts in the init.groovy.d to maintain the configurations in Jenkins, including Keycloak configurations. And the best way to solve it was through a declarative model using the Jenkins Configuration as Code (JCasC) plugin.
Examples:
Keycloak
jenkins:
securityRealm: keycloak
unclassified:
keycloakSecurityRealm:
keycloakJson: |-
{
"realm": "my-realm",
"auth-server-url": "https://my-keycloak-url/auth",
"ssl-required": "all",
"resource": "jenkins",
"public-client": true,
"confidential-port": 0
}
source: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos/keycloak
Credentials
credentials:
system:
domainCredentials:
- domain:
name: "test.com"
description: "test.com domain"
specifications:
- hostnameSpecification:
includes: "*.test.com"
credentials:
- usernamePassword:
scope: SYSTEM
id: sudo_password
username: root
password: ${SUDO_PASSWORD}
source: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos/credentials

Following solution works for me.
#!/usr/bin/env groovy
import jenkins.model.Jenkins
import hudson.security.*
import org.jenkinsci.plugins.KeycloakSecurityRealm
Jenkins jenkins = Jenkins.get()
def desc = jenkins.getDescriptor("org.jenkinsci.plugins.KeycloakSecurityRealm")
// JSON based on the keycloak configuration
desc.setKeycloakJson( "{\n" +
" \"realm\": \"myRealm\",\n" +
" \"auth-server-url\": \"https://keycloak/auth/\",\n" +
" \"ssl-required\": \"external\",\n" +
" \"resource\": \"jenkins\",\n" +
" \"public-client\": true,\n" +
" \"confidential-port\": 0\n" +
"}")
desc.save()
jenkins.setSecurityRealm(new KeycloakSecurityRealm())
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
strategy.setAllowAnonymousRead(false)
jenkins.setAuthorizationStrategy(strategy)
jenkins.save()

Related

Edit user in Jenkins via groovy script

I am wondering if I can change password, username, email in Jenkins user. Because I am able to create user via groovy script like this:
import hudson.model.*
def user = instance.securityRealm.createAccount(userId, password)
user.addProperty(new Mailer.UserProperty(email));
instance.save()
Jenkins interface allows me to manage user credentials, but script which allow to change password/email/username would be very helpfull. I didnt find examples.
I tried many times with script like this, but It didnt work
import hudson.model.*
User user = User.getAll().get(1)
user.setProperty(newPassword)
Here's a simple code that works :
import jenkins.model.*
import hudson.security.*
import hudson.tasks.Mailer
def env = System.getenv()
def jenkins = Jenkins.getInstance()
if(!(jenkins.getSecurityRealm() instanceof HudsonPrivateSecurityRealm))
jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(false))
if(!(jenkins.getAuthorizationStrategy() instanceof GlobalMatrixAuthorizationStrategy))
jenkins.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy())
// update admin Jenkins user account
def user = jenkins.getSecurityRealm().getUser('admin')
email= 'jenkins-admin#gmail.com'
user.addProperty(new Mailer.UserProperty(email));
For Jenkins Jenkins 2.361.1, I have used such Jenkins groovy script to update user's password:
User.getById("userName",false).addProperty(hudson.security.HudsonPrivateSecurityRealm.Details.fromPlainPassword("new-password"));
You can also easily run it from bash script or similar, given $USERNAME and $PASSWORD are set:
echo "script=User.getById(\"$USERNAME\",false).addProperty(hudson.security.HudsonPrivateSecurityRealm.Details.fromPlainPassword(\"$PASSWORD\"));" | \
curl -d #- --user admin:access_token http://<ip>:8080/scriptText

Jenkins: Automate CI Docker instance

I'm trying to setup Jenkins to be fully automated once I launch it from a docker container.
My question is how do I automate the configuration of the global Jenkins settings. For example the items in manage jenkins and credentials?
I'm using this a reference:
https://wiki.jenkins.io/display/jenkins/remote+access+api
Currently, I have the set these items up manually. I would like to fully automate the CI server creation. Is this possible with Jenkins or is there some human intervention that is required?
Any help would be greatly appreciated.
we used chef to setup the master , and it run some groovy scripts to install all the plugin and configuration. it almost done fully automatically , beside 1 or 2 plugins that I didn't find the syntax to configure all others works fine.
I installed all the plugins using Jenkins CLI , check yourJenkins/cli/ for reference.
for the general configuration you can install all the tools
import jenkins.model.*
import hudson.model.*
def inst1 = Jenkins.getInstance()
def desc1 = inst1.getDescriptor("hudson.tools.JDKInstaller")
println desc1.doPostCredential('buildJenkins#gmail.com','JenkinsOracleXXXXX')
import jenkins.model.*
import hudson.model.*
import hudson.tools.*
// JDK installation
def inst = Jenkins.getInstance()
def desc = inst.getDescriptor("hudson.model.JDK")
def versions = [
"jdk-1.8.101": "jdk-8u101-oth-JPR",
// "jdk-1.8.102": "jdk-8u102-oth-JPR"
]
general variables
// general properties
instance = Jenkins.getInstance()
globalNodeProperties = instance.getGlobalNodeProperties()
envVarsNodePropertyList = globalNodeProperties.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class)
newEnvVarsNodeProperty = null
envVars = null
if ( envVarsNodePropertyList == null || envVarsNodePropertyList.size() == 0 ) {
newEnvVarsNodeProperty = new hudson.slaves.EnvironmentVariablesNodeProperty();
globalNodeProperties.add(newEnvVarsNodeProperty)
envVars = newEnvVarsNodeProperty.getEnvVars()
} else {
envVars = envVarsNodePropertyList.get(0).getEnvVars()
}
envVars.put("ARTIFACTORY_URL", "artifactory-url")
envVars.put("ARTIFACTORY_USER", "jenkins")
envVars.put("DOCKER_USER", "docker-push")
instance.save()
email address
// admin Email
def jenkinsLocationConfiguration = JenkinsLocationConfiguration.get()
jenkinsLocationConfiguration.setAdminAddress('admin#yours.com')
jenkinsLocationConfiguration.save()
there a lot of examples , just look for groovy Jenkins configuration ..
if you have any specific question let me know.

Jenkins credentials - Gitlab API token

I've been searching the whole web for a snippet on how to create GitLab API credential with groovy. and creating Gitlab connection using that API credential for 'Build merge request' purposes, It would be really helpful. Thanks in advance
UPDATE:
I found a solution anyway. I created the GitlabAPI creds manually and took its XML and parsed it with jinja2 to make it dynamic. then I've passed it to the Jenkins CLI create creds by xml
cat /tmp/gitlab-credential.xml | \
java -jar {{ cli_jar_location }} \
-s http://{{ jenkins_hostname }}:{{ http_port }} \
create-credentials-by-xml "SystemCredentialsProvider::SystemContextResolver::jenkins" "(global)"
I encountered similar need to create the gitlab api credential via groovy. Below is the solution I managed to figure out, adapted from https://gist.github.com/iocanel/9de5c976cc0bd5011653
import jenkins.model.*
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.common.*
import com.cloudbees.plugins.credentials.domains.*
import com.cloudbees.plugins.credentials.impl.*
import com.dabsquared.gitlabjenkins.connection.*
import hudson.util.Secret
domain = Domain.global()
store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
token = new Secret("my-token")
gitlabToken = new GitLabApiTokenImpl(
CredentialsScope.GLOBAL,
"gitlab-token",
"token for gitlab",
token
)
store.addCredentials(domain, gitlabToken)

Executing hudson specific function in jenkins pipeline

I have been trying to find a solution for changing build parameters programmatically using jenkins pipeline plugin where i have jenkinsfile with following content:
#!/usr/bin/env groovy
import hudson.model.*
properties(
[
parameters(
[
string(defaultValue: 'win64', description: 'PLATFORM', name: 'PLATFORM'),
string(defaultValue: '12.1.0', description: 'PRODUCT_VERSION', name: 'PRODUCT_VERSION')
]
)
]
)
stage('working with parameters'){
node('master'){
def thr = Thread.currentThread()
def build = thr?.executable
def paramsDef = build.getProperty(ParametersDefinitionProperty.class)
if (paramsDef) {
paramsDef.parameterDefinitions.each{ param ->
if (param.name == 'PLATFORM') {
println("Changing parameter ${param.name} default value was '${param.defaultValue}' to 'osx10'")
param.defaultValue = "osx10"
}
}
}
}
}
But it fails everytime with error as :
groovy.lang.MissingPropertyException: No such property: executable for class: java.lang.Thread
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
After searching a lot i could find somewhere that this script needs to run as system groovy script and everywhere they are referring to Groovy plugin but as i am using pipeline project, i am not able to understand how can i force pipeline to execute my scripts as system groovy script.
Please solve my queries as i have left no link on google unopened :(

I want to create jenkins credentials via ansible

I am putting together a developer machine using ansible. In that machine i am installing jenkins.
I have created the jobs for jenkins with ansible:
- shell: "java -jar {{ jenkins.cli_jar }} -s {{ jenkins.server }} create-job \
{{ item.name }} < {{ jenkins.jobs_dir }}/{{ item.xml_file }}"
with_items: "jenkins.jobs"
And installed the plugins, via cli etc.
But now i am missing the ssh credentials for the jobs; i just want a ssh credential with user "jenkins" and that uses "From the Jenkins master ~/.ssh".
This type of credentials are the ones i am talking about:
Maybe is a groovy script but i haven't find a lot of information about it. Thanks for the help.
You can use the jenkins client from command line on the machine where the jenkins runs like:
java -jar jenkins-cli.jar -s http://localhost:8080/ groovy create-credential.groovy
with create-credential.groovy:
import jenkins.model.*
import com.cloudbees.plugins.credentials.CredentialsScope
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
def addPassword = { username, new_password ->
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
Jenkins.instance
)
def c = creds.findResult { it.username == username ? it : null }
if ( c ) {
println "found credential ${c.id} for username ${c.username}"
} else {
def credentials_store = Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
def scope = CredentialsScope.GLOBAL
def description = ""
def result = credentials_store.addCredentials(
com.cloudbees.plugins.credentials.domains.Domain.global(),
new UsernamePasswordCredentialsImpl(scope, null, description, username, new_password)
)
if (result) {
println "credential added for ${username}"
} else {
println "failed to add credential for ${username}"
}
}
}
addPassword('pinky', 'narf')
This will add the global credential for user 'pinky' with password 'narf'
As of version 2.1.1 of the plugin (June 2016) this is possible through the CLI or the REST API:
https://github.com/jenkinsci/credentials-plugin/blob/master/docs/user.adoc#creating-a-credentials
from that page:
$ cat > credential.xml <<EOF
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<scope>GLOBAL</scope>
<id>deploy-key</id>
<username>wecoyote</username>
<password>secret123</password>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
EOF
$ curl -X POST -H content-type:application/xml -d #credential.xml \
https://jenkins.example.com/job/example-folder/credentials/store/folder/\
domain/testing/createCredentials
Jenkins credentials plugin doesn't allow credentials creation using API (https://issues.jenkins-ci.org/browse/JENKINS-28407).
A viable solution would be recording a credential creation using your prefered browser and JMeter proxy or Selenium IDE. and replaying it using JMeter CLI or saving the Selenium recorded test as a groovy script.
You may also take a look at https://github.com/jenkinsci/credentials-plugin/pull/33
Here is an example ansible task that uses "jenkins_script" instead of directly specifying the CLI or calling the REST API, and it adds the benefit of updating existing credentials.
- name: establish credentials
jenkins_script:
script: |
import jenkins.model.*
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.cloudbees.plugins.credentials.CredentialsScope
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials
import com.cloudbees.plugins.credentials.domains.Domain
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
def domain = Domain.global()
def instance = Jenkins.instance
def credstore = instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
def existingCreds = CredentialsProvider.lookupCredentials(
StandardUsernameCredentials.class, instance).findResult {
it.username == '${username}' ? it : null
}
def newCreds = new UsernamePasswordCredentialsImpl(
CredentialsScope.GLOBAL, null,
'${description}', '${username}', '${password}')
if (existingCreds) {
credstore.updateCredentials(domain, existingCreds, newCreds)
} else {
credstore.addCredentials(domain, newCreds)
}
args:
description: "entrada credential"
username: "{{ item.username }}"
password: "{{ item.password }}"
user: "{{ entrada_user_name }}"
password: "{{ entrada_user_password }}"
with_items: "{{ entrada_cicd_credentials }}"

Resources