Skip to content

Commit

Permalink
Move plugin removal to plugins recipe
Browse files Browse the repository at this point in the history
Signed-off-by: Crola1702 <[email protected]>
  • Loading branch information
Crola1702 committed Jan 30, 2025
1 parent 8d4ccbd commit 38cbcc2
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 52 deletions.
232 changes: 180 additions & 52 deletions recipes/jenkins.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,6 @@
node.run_state[:jenkins_password] = chef_user['password']
node.default['jenkins']['executor']['protocol'] = 'http'

# Remove plugins that were required previously but are not now.
# Delete *.jpi files in plugin directory by filtering plugins to remove from a grep command
plugin_remove_filter = node.default['ros_buildfarm']['jenkins']['remove_plugins'].map! {|e| "#{e}.jpi"}.join("|")
execute "ls /var/lib/jenkins/plugins | grep -E \"#{plugin_remove_filter}\" | xargs -r rm" do
# If there are no plugins, then we don't need to remove anythi ng
only_if { ::Dir.exist? '/var/lib/jenkins/plugins/' }
end

# Install plugins required to run ros_buildfarm.
include_recipe '::plugins'

Expand Down Expand Up @@ -157,30 +149,47 @@
# This method uses the Jenkins internal user database and manages permissions directly with chef.
# * Groovy scripted:
# This method can be used to enable more complex authentication / authorization strategies and security realms.
if node['ros_buildfarm']['jenkins']['auth_strategy'] == 'groovy'

# Create init.groovy.d directory to save important groovy files
directory '/var/lib/jenkins/init.groovy.d' do
mode '0755'
owner 'jenkins'
group 'jenkins'
end

if node.default['ros_buildfarm']['jenkins']['auth_strategy'] == 'groovy'
auth_strategy_script = data_bag_item('ros_buildfarm_jenkins_scripts', 'auth_strategy')[node.chef_environment]
if auth_strategy_script.nil?
Chef::Log.fatal("No auth strategy script for #{node.chef_environment} in ros_buildfarm_jenkins_scripts but auth_strategy is set to groovy.")
raise
end
jenkins_script 'auth_strategy' do
command auth_strategy_script['command']

file '/var/lib/jenkins/init.groovy.d/auth_strategy.groovy' do
content auth_strategy_script['command']
mode '0755'
owner 'jenkins'
group 'jenkins'
end
elsif node['ros_buildfarm']['jenkins']['auth_strategy'] == 'default'
jenkins_script 'establish security realm' do
command <<~GROOVY
import hudson.model.*
import jenkins.model.*
import hudson.security.HudsonPrivateSecurityRealm
import hudson.security.SecurityRealm
def jenkins = Jenkins.getInstance()
// Boolean `!` binds closer than instanceof so parenthesize the instanceof operation
if (!(jenkins.getSecurityRealm() instanceof HudsonPrivateSecurityRealm)) {
jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(false))
jenkins.save()
}
GROOVY
elsif node.default['ros_buildfarm']['jenkins']['auth_strategy'] == 'default'
default_auth_script = <<~GROOVY
import hudson.model.*
import jenkins.model.*
import hudson.security.HudsonPrivateSecurityRealm
import hudson.security.SecurityRealm
def jenkins = Jenkins.getInstance()
// Boolean `!` binds closer than instanceof so parenthesize the instanceof operation
if (!(jenkins.getSecurityRealm() instanceof HudsonPrivateSecurityRealm)) {
jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(false))
jenkins.save()
}
GROOVY

file '/var/lib/jenkins/init.groovy.d/auth_strategy.groovy' do
content default_auth_script
mode '0755'
owner 'jenkins'
group 'jenkins'
end

# Restart jenkins after updating the security realm otherwise running without
Expand All @@ -190,6 +199,10 @@ def jenkins = Jenkins.getInstance()
end

# Aggregate permissions to assign to each user with a groovy script.
users_creation_scripts = [
default_auth_script
]

permissions = []
data_bag('ros_buildfarm_jenkins_users').each do |id|
user = data_bag_item('ros_buildfarm_jenkins_users', id)
Expand All @@ -205,19 +218,26 @@ def jenkins = Jenkins.getInstance()
# not know what would happen if we tried to create a concrete user with the
# username anonymous so let's just don't.
next if user['username'] == 'anonymous'
jenkins_user user['username'] do
password user['password']
public_keys user['public_keys']
email user['email'] if user['email']
end

user_creation_script = <<~GROOVY
user = hudson.model.User.get("#{user['username']}")
if (#{!user['email'].nil?}) {
email = new hudson.tasks.Mailer.UserProperty("#{user['email']}")
user.addProperty(email)
}
password = hudson.security.HudsonPrivateSecurityRealm.Details.fromPlainPassword("#{user['password']}")
user.addProperty(password)
keys = new org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl(#{user['public_keys'].join('\n')})
user.addProperty(keys)
user.save()
GROOVY

users_creation_scripts << user_creation_script
end
jenkins_script 'matrix_authentication_permissions' do
command <<~GROOVY
import hudson.model.*
import jenkins.model.*

matrix_auth_permissions_script = <<~GROOVY
import hudson.security.ProjectMatrixAuthorizationStrategy
def jenkins = Jenkins.getInstance()
matrix_auth = new ProjectMatrixAuthorizationStrategy()
#{permissions.map { |p, u| "matrix_auth.add(#{p}, \"#{u}\")" }.join "\n"}
Expand All @@ -227,6 +247,14 @@ def jenkins = Jenkins.getInstance()
jenkins.save()
}
GROOVY

users_creation_scripts << matrix_auth_permissions_script

file '/var/lib/jenkins/init.groovy.d/auth_strategy.groovy' do
content users_creation_scripts.join("\n")
mode '0755'
owner 'jenkins'
group 'jenkins'
end
else
Chef::Log.warn("Jenkins auth_strategy attribute `#{node['ros_buildfarm']['jenkins']['auth_strategy']}` is unknown. No authentication will be configured.")
Expand Down Expand Up @@ -306,32 +334,132 @@ def jenkins = Jenkins.getInstance()

package 'docker.io'

# Setup credentials

credentials_scripts = [
<<~GROOVY
import jenkins.model.*
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.impl.*
import com.cloudbees.plugins.credentials.common.*
import com.cloudbees.plugins.credentials.domains.*
import com.cloudbees.jenkins.plugins.sshcredentials.impl.*
import hudson.util.Secret;
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
global_domain = Domain.global()
credentials_store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
available_credentials = CredentialsProvider.lookupCredentials(
StandardUsernameCredentials.class,
Jenkins.getInstance(),
hudson.security.ACL.SYSTEM,
new SchemeRequirement("ssh")
)
GROOVY
]

data_bag('ros_buildfarm_password_credentials').each do |item|
password_credential = data_bag_item('ros_buildfarm_password_credentials', item)
jenkins_password_credentials password_credential['id'] do
id password_credential['id']
description password_credential['description']
username password_credential['username'] if password_credential['username']
password password_credential['password']
end

credentials_scripts << <<~GROOVY
credentials = new UsernamePasswordCredentialsImpl(
CredentialsScope.GLOBAL,
"#{password_credential['id']}",
"#{password_credential['description']}",
"#{password_credential['username'] if password_credential['username']}",
"#{password_credential['password']}"
)
existing_credentials = CredentialsMatchers.firstOrNull(
available_credentials,
CredentialsMatchers.withId("#{password_credential['id']}")
)
if (existing_credentials != null) {
credentials_store.updateCredentials(
global_domain,
existing_credentials,
credentials
)
} else {
credentials_store.addCredentials(global_domain, credentials)
}
GROOVY
end

data_bag('ros_buildfarm_private_key_credentials').each do |item|
private_key_credential = data_bag_item('ros_buildfarm_private_key_credentials', item)[node.chef_environment]
jenkins_private_key_credentials private_key_credential['name'] do
id private_key_credential['name']
description private_key_credential['description']
private_key private_key_credential['private_key']
end

credentials_scripts << <<~GROOVY
private_key = """#{private_key_credential['private_key']}
"""
credentials = new BasicSSHUserPrivateKey(
CredentialsScope.GLOBAL,
"#{private_key_credential['name']}",
"#{private_key_credential['username'] if private_key_credential['username']}",
new BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(private_key),
"#{private_key_credential['passphrase'] if private_key_credential['passphrase']}",
"#{private_key_credential['description']}"
)
existing_credentials = CredentialsMatchers.firstOrNull(
available_credentials,
CredentialsMatchers.withId("#{private_key_credential['id']}")
)
if (existing_credentials != null) {
credentials_store.updateCredentials(
global_domain,
existing_credentials,
credentials
)
} else {
credentials_store.addCredentials(global_domain, credentials)
}
GROOVY
end

data_bag('ros_buildfarm_secret_text_credentials').each do |item|
secret_text_credential = data_bag_item('ros_buildfarm_secret_text_credentials', item)[node.chef_environment]
jenkins_secret_text_credentials secret_text_credential['name'] do
id secret_text_credential['name']
description secret_text_credential['description']
secret secret_text_credential['secret_text']
end
credentials_scripts << <<~GROOVY
secret = new Secret("#{secret_text_credential['secret_text']}")
credentials = new StringCredentialsImpl(
CredentialsScope.GLOBAL,
"#{secret_text_credential['name']}",
"#{secret_text_credential['description']}",
secret
)
available_secret_text = CredentialsProvider.lookupCredentials(
StringCredentials.class,
Jenkins.getInstance(),
hudson.security.ACL.SYSTEM
).findAll({
it.secret == secret &&
it.description == "#{secret_text_credential['description']}"
})
existing_credentials = available_secret_text.size() > 0 ? available_secret_text[0] : null
if (existing_credentials != null) {
credentials_store.updateCredentials(
global_domain,
existing_credentials,
credentials
)
} else {
credentials_store.addCredentials(global_domain, credentials)
}
GROOVY
end

file '/var/lib/jenkins/init.groovy.d/credentials_config.groovy' do
content credentials_scripts.join("\n")
mode '0755'
owner 'jenkins'
group 'jenkins'
end

# Remove Jenkins fingerprint files
Expand Down
9 changes: 9 additions & 0 deletions recipes/plugins.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@
user "jenkins"
notifies :restart, 'service[jenkins]', :delayed
end

# Remove plugins that were required previously but are not now. By:
# * Listing all plugins (.jpi files) in the plugin directories
# * Delete the plugins (.jpi file) stated in ['jenkins']['remove_plugins']
plugin_remove_filter = node.default['ros_buildfarm']['jenkins']['remove_plugins'].map! {|e| "#{e}.jpi"}.join("|")
execute "ls /var/lib/jenkins/plugins | grep -E \"#{plugin_remove_filter}\" | xargs -r rm" do
# If there are no plugins, then we don't need to remove anything
only_if { ::Dir.exist? '/var/lib/jenkins/plugins/' }
end

0 comments on commit 38cbcc2

Please sign in to comment.