Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to setup LDAP auth #339

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
159 changes: 134 additions & 25 deletions files/puppet_helper.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ import com.cloudbees.plugins.credentials.domains.*;
import com.cloudbees.plugins.credentials.impl.*
import com.cloudbees.plugins.credentials.impl.*;
import hudson.plugins.sshslaves.*;
import jenkins.security.*;
import jenkins.model.*;
import jenkins.security.*;
import hudson.model.*;
import hudson.security.*;

class InvalidAuthenticationStrategy extends Exception{}

Expand Down Expand Up @@ -245,7 +248,7 @@ class Actions {
]

if ( credentials.hasProperty('password') ) {
current_credentials['password'] = credentials.password.plainText
current_credentials['password'] = credentials.password.plainText
} else {
current_credentials['private_key'] = credentials.privateKey
current_credentials['passphrase'] = credentials.passphrase.plainText
Expand All @@ -255,38 +258,144 @@ class Actions {
out.println(builder)
}

////////////////////////
// set_security
////////////////////////
/*
* Set up security for the Jenkins instance. This currently supports
* only a small number of configurations. If authentication is enabled, it
* uses the internal user database.
*/
void set_security(String security_model) {
//////////////////////////////
// enable slave to master acl
//////////////////////////////
void enable_slave_to_master_acl(String act) {
def s2m = new AdminWhitelistRule()
if(act == "true") {
// for 'enabled' state we need to pass 'false'
s2m.setMasterKillSwitch(false)
}
if(act == "false") {
s2m.setMasterKillSwitch(true)
}
// requires Jenkins restart
Hudson.instance.safeRestart()
}

//////////////////////////////
// set security ldap
//////////////////////////////
void set_security_ldap(
String overwrite_permissions=null,
String item_perms=null,
String server=null,
String rootDN=null,
String userSearch=null,
String inhibitInferRootDN=null,
String userSearchBase=null,
String groupSearchBase=null,
String managerDN=null,
String managerPassword=null,
String ldapuser,
String email=null,
String password,
String name=null,
String pub_keys=null,
String s2m_acl=null
) {

if (inhibitInferRootDN==null) {
inhibitInferRootDN = false
}
def instance = Jenkins.getInstance()
def strategy
def realm
List users = item_perms.split(' ')

if (security_model == 'disabled') {
instance.disableSecurity()
return null
if (!(instance.getAuthorizationStrategy() instanceof hudson.security.GlobalMatrixAuthorizationStrategy)) {
overwrite_permissions = 'true'
}
create_or_update_user(ldapuser, email, password, name, pub_keys)
strategy = new hudson.security.GlobalMatrixAuthorizationStrategy()
for (String user : users) {
for (Permission p : Item.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : Computer.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : Hudson.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : Run.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : View.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
}
realm = new hudson.security.LDAPSecurityRealm(
server, rootDN, userSearchBase, userSearch, groupSearchBase, managerDN, managerPassword, inhibitInferRootDN.toBoolean()
)
// apply new strategy&realm
if (overwrite_permissions == 'true') {
instance.setAuthorizationStrategy(strategy)
}
instance.setSecurityRealm(realm)
// commit new settings permanently (in config.xml)
instance.save()
// now setup s2m if requested
if(s2m_acl == 'true') {
enable_slave_to_master_acl(s2m_acl)
}
}

//////////////////////////////
// set security unsecured
//////////////////////////////
void set_security_unsecured() {
def instance = Jenkins.getInstance()
def strategy
def realm
switch (security_model) {
case 'full_control':
strategy = new hudson.security.FullControlOnceLoggedInAuthorizationStrategy()
realm = new hudson.security.HudsonPrivateSecurityRealm(false, false, null)
break
case 'unsecured':
strategy = new hudson.security.AuthorizationStrategy.Unsecured()
realm = new hudson.security.HudsonPrivateSecurityRealm(false, false, null)
break
default:
throw new InvalidAuthenticationStrategy()
}
strategy = new hudson.security.AuthorizationStrategy.Unsecured()
realm = new hudson.security.HudsonPrivateSecurityRealm(false, false, null)
instance.setAuthorizationStrategy(strategy)
instance.setSecurityRealm(realm)
instance.save()
}

//////////////////////////////
// set security password
//////////////////////////////
void set_security_password(String user, String email, String password, String name=null, String pub_keys=null, String s2m_acl=null) {
def instance = Jenkins.getInstance()
def overwrite_permissions
def strategy
def realm
strategy = new hudson.security.GlobalMatrixAuthorizationStrategy()
if (!(instance.getAuthorizationStrategy() instanceof hudson.security.GlobalMatrixAuthorizationStrategy)) {
overwrite_permissions = 'true'
}
create_or_update_user(user, email, password, name, pub_keys)
for (Permission p : Item.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : Computer.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : Hudson.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : Run.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
for (Permission p : View.PERMISSIONS.getPermissions()) {
strategy.add(p,user)
}
realm = new hudson.security.HudsonPrivateSecurityRealm(false)
// apply new strategy&realm
if (overwrite_permissions == 'true') {
instance.setAuthorizationStrategy(strategy)
instance.setSecurityRealm(realm)
}
// commit new settings permanently (in config.xml)
instance.save()
// now setup s2m if requested
if(s2m_acl == 'true') {
enable_slave_to_master_acl(s2m_acl)
}
}

////////////////////////
Expand Down
Binary file added manifests/.DS_Store
Binary file not shown.
34 changes: 33 additions & 1 deletion manifests/cli_helper.pp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,47 @@
# A helper script for creating resources via the Jenkins cli
#
class jenkins::cli_helper (
$jenkins_ssh_private_key_contents = '',
$jenkins_ssh_public_key_contents = '',
$ssh_keyfile = undef,
){
include ::jenkins
include ::jenkins::cli

$libdir = $::jenkins::libdir
$cli_jar = $::jenkins::cli::jar
$port = jenkins_port()

file { "${libdir}/.ssh/" :
ensure => directory,
owner => 'jenkins',
group => 'jenkins',
mode => '0700',
require => User['jenkins'],
}

if ($jenkins_ssh_private_key_contents) {
file { "${libdir}/.ssh/id_rsa" :
owner => 'jenkins',
group => 'jenkins',
mode => '0600',
content => $jenkins_ssh_private_key_contents,
replace => true,
require => File["${libdir}/.ssh/"],
}
}

if ($jenkins_ssh_public_key_contents) {
file { "${libdir}/.ssh/id_rsa.pub" :
owner => 'jenkins',
group => 'jenkins',
mode => '0644',
content => "${jenkins_ssh_public_key_contents} jenkins@master",
replace => true,
require => File["${libdir}/.ssh"],
}
}

$helper_groovy = "${libdir}/puppet_helper.groovy"
file {$helper_groovy:
source => 'puppet:///modules/jenkins/puppet_helper.groovy',
Expand Down
21 changes: 21 additions & 0 deletions manifests/ldap/config.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Jenkins ldap configuration
#
class jenkins::ldap::config (
$ldap_config = {
'jenkins_management_email'=> '',
'jenkins_management_login'=> '',
'jenkins_management_name' => '',
'jenkins_management_password' => '',
'ldap_access_group' => '',
'ldap_group_search_base' => '',
'ldap_inhibit_root_dn' => '',
'ldap_manager' => 'ldap-manager',
'ldap_manager_passwd' => 'ldap-password',
'ldap_overwrite_permissions' => 'true',
'ldap_root_dn' => 'dc=company,dc=net',
'ldap_uri' => 'ldap://ldap',
'ldap_user_search' => 'uid={0}',
'ldap_user_search_base' => '',
}
)

49 changes: 46 additions & 3 deletions manifests/security.pp
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,60 @@
# Jenkins security configuration
#
class jenkins::security (
$security_model = undef,
$jenkins_management = {},
$jenkins_s2m_acl = false,
$security_model = undef,
){
validate_string($security_model)

include ::jenkins::cli_helper

if ($security_model == 'unsecured') {
$security_opt_params = 'set_security_unsecured'
}

if ($security_model == 'ldap') {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One suggestion, since this is a lot to place on the command line. What about writing a configuration file to disk temporarily and then having the groovy helper read that configuration file?

I worry that there command line might end up being too long

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my native types and provider branch I've been passing json into the puppet_helper on the stdin, which has worked well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing like reviving old branches...

@jhoblitt Your example json URL appears to be dead, are you still using this branch to setup Jenkins LDAP authentication ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matonb That code has been merged into this module.

include ::jenkins::ldap::config
$jenkins_ssh_public_key_contents = file('${libdir}/.ssh/id_rsa.pub')
$security_opt_params = join([
'set_security_ldap',
"'${ldap_config}[ldap_overwrite_permissions]'",
"'${ldap_config}[ldap_access_group]'",
"'${ldap_config}[ldap_uri]'",
"'${ldap_config}[ldap_root_dn]'",
"'${ldap_config}[ldap_user_search]'",
"'${ldap_config}[ldap_inhibit_root_dn]'",
"'${ldap_config}[ldap_user_search_base]'",
"'${ldap_config}[ldap_group_search_base]'",
"'${ldap_config}[ldap_manager]'",
"'${ldap_config}[ldap_manager_passwd]'",
"'${jenkins_management_login}'",
"'${jenkins_management_email}'",
"'${jenkins_management_password}'",
"'${jenkins_management_name}'",
"'${jenkins_ssh_public_key_contents}'",
"'${jenkins_s2m_acl}'",
], ' ')
}

if ($security_model == 'password') {
$jenkins_ssh_public_key_contents = file('${libdir}/.ssh/id_rsa.pub')
$security_opt_params = join([
'set_security_password',
"'${jenkins_management_login}'",
"'${jenkins_management_email}'",
"'${jenkins_management_password}'",
"'${jenkins_management_name}'",
"'${jenkins_ssh_public_key_contents}'",
"'${jenkins_s2m_acl}'",
], ' ')
}

# XXX not idempotent
jenkins::cli::exec { "jenkins-security-${security_model}":
command => [
'set_security',
$security_model,
$security_opt_params
],
user => 'jenkins',
}
}