Full support for Keystone LDAP integration
Adding full support for integrating Keystone via LDAP. Enables support for managing all LDAP related Keystone options. - Add two examples of LDAP configuration, although LDAP environments are highly variable, these will help get everyone started - Modify the keystone::ldap class to support all LDAP related options - Check sane defaults in the keystone::ldap class to hopefully reduce mistakes - Add a dependency on the python-ldap package - Modify the LDAP test to match the new class - Make the default-tenant optional since some LDAP backends do not support this Change-Id: Ie6879eb4816fd2b906f72cac8deb3b62bd4b2430
This commit is contained in:
66
examples/ldap_full.pp
Normal file
66
examples/ldap_full.pp
Normal file
@@ -0,0 +1,66 @@
|
||||
# A full example from a real deployment that allows Keystone to modify
|
||||
# everything except users, uses enabled_emulation, and ldaps
|
||||
|
||||
# Ensure this matches what is in LDAP or keystone will try to recreate
|
||||
# the admin user
|
||||
class { 'keystone::roles::admin':
|
||||
email => 'test@example.com',
|
||||
password => 'ChangeMe',
|
||||
}
|
||||
|
||||
# You can test this connection with ldapsearch first to ensure it works.
|
||||
# LDAP configurations are *highly* dependent on your setup and this file
|
||||
# will need to be tweaked. This sample talks to ldap.example.com, here is
|
||||
# an example of ldapsearch that will search users on this box:
|
||||
# ldapsearch -v -x -H 'ldap://69.134.70.154:389' -D \
|
||||
# "uid=bind,cn=users,cn=accounts,dc=example,dc=com" -w SecretPass \
|
||||
# -b cn=users,cn=accounts,dc=example,dc=com
|
||||
class { 'keystone:ldap':
|
||||
url => 'ldap://ldap.example.com:389',
|
||||
user => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com',
|
||||
password => 'SecretPass',
|
||||
suffix => 'dc=example,dc=com',
|
||||
query_scope => 'sub',
|
||||
user_tree_dn => 'cn=users,cn=accounts,dc=example,dc=com',
|
||||
user_id_attribute => 'uid',
|
||||
user_name_attribute => 'uid',
|
||||
user_mail_attribute => 'mail',
|
||||
user_allow_create => 'False',
|
||||
user_allow_update => 'False',
|
||||
user_allow_delete => 'False',
|
||||
user_enabled_emulation => 'True',
|
||||
user_enabled_emulation_dn => 'cn=openstack-enabled,cn=groups,cn=accounts,dc=example,dc=com',
|
||||
group_tree_dn => 'ou=groups,ou=openstack,dc=example,dc=com',
|
||||
group_objectclass => 'organizationalRole',
|
||||
group_id_attribute => 'cn',
|
||||
group_name_attribute => 'cn',
|
||||
group_member_attribute => 'RoleOccupant',
|
||||
group_desc_attribute => 'description',
|
||||
group_allow_create => 'True',
|
||||
group_allow_update => 'True',
|
||||
group_allow_delete => 'True',
|
||||
tenant_tree_dn => 'ou=projects,ou=openstack,dc=example,dc=com',
|
||||
tenant_objectclass => 'organizationalUnit',
|
||||
tenant_id_attribute => 'ou',
|
||||
tenant_member_attribute => 'member',
|
||||
tenant_name_attribute => 'ou',
|
||||
tenant_desc_attribute => 'description',
|
||||
tenant_allow_create => 'True',
|
||||
tenant_allow_update => 'True',
|
||||
tenant_allow_delete => 'True',
|
||||
tenant_enabled_emulation => 'True',
|
||||
tenant_enabled_emulation_dn => 'cn=enabled,ou=openstack,dc=example,dc=com',
|
||||
role_tree_dn => 'ou=roles,ou=openstack,dc=example,dc=com',
|
||||
role_objectclass => 'organizationalRole',
|
||||
role_id_attribute => 'cn',
|
||||
role_name_attribute => 'cn',
|
||||
role_member_attribute => 'roleOccupant',
|
||||
role_allow_create => 'True',
|
||||
role_allow_update => 'True',
|
||||
role_allow_delete => 'True',
|
||||
identity_driver => 'keystone.identity.backends.ldap.Identity',
|
||||
assignment_driver => 'keystone.assignment.backends.ldap.Assignment',
|
||||
use_tls => 'True',
|
||||
tls_cacertfile => '/etc/ssl/certs/ca-certificates.crt',
|
||||
tls_req_cert => 'demand',
|
||||
}
|
||||
28
examples/ldap_identity.pp
Normal file
28
examples/ldap_identity.pp
Normal file
@@ -0,0 +1,28 @@
|
||||
# Example using LDAP to manage user identity only.
|
||||
# This setup will not allow changes to users.
|
||||
|
||||
# Ensure this matches what is in LDAP or keystone will try to recreate
|
||||
# the admin user
|
||||
class { 'keystone::roles::admin':
|
||||
email => 'test@example.com',
|
||||
password => 'ChangeMe',
|
||||
}
|
||||
|
||||
# You can test this connection with ldapsearch first to ensure it works.
|
||||
# This was tested against a FreeIPA box, you will likely need to change the
|
||||
# attributes to match your configuration.
|
||||
class { 'keystone:ldap':
|
||||
identity_driver => 'keystone.identity.backends.ldap.Identity',
|
||||
url => 'ldap://ldap.example.com:389',
|
||||
user => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com',
|
||||
password => 'SecretPass',
|
||||
suffix => 'dc=example,dc=com',
|
||||
query_scope => 'sub',
|
||||
user_tree_dn => 'cn=users,cn=accounts,dc=example,dc=com',
|
||||
user_id_attribute => 'uid',
|
||||
user_name_attribute => 'uid',
|
||||
user_mail_attribute => 'mail',
|
||||
user_allow_create => 'False',
|
||||
user_allow_update => 'False',
|
||||
user_allow_delete => 'False'
|
||||
}
|
||||
@@ -99,6 +99,7 @@ Puppet::Type.type(:keystone_user).provide(
|
||||
end
|
||||
|
||||
def tenant
|
||||
return resource[:tenant] if resource[:ignore_default_tenant]
|
||||
user_id = user_hash[resource[:name]][:id]
|
||||
begin
|
||||
tenantId = self.class.get_keystone_object('user', user_id, 'tenantId')
|
||||
|
||||
@@ -16,6 +16,11 @@ Puppet::Type.newtype(:keystone_user) do
|
||||
newvalues(/\S+/)
|
||||
end
|
||||
|
||||
newparam(:ignore_default_tenant, :boolean => true) do
|
||||
newvalues(:true, :false)
|
||||
defaultto false
|
||||
end
|
||||
|
||||
newproperty(:enabled) do
|
||||
newvalues(/(t|T)rue/, /(f|F)alse/)
|
||||
defaultto('True')
|
||||
|
||||
@@ -6,29 +6,175 @@
|
||||
# == Authors
|
||||
#
|
||||
# Dan Bode dan@puppetlabs.com
|
||||
# Matt Fischer matt.fischer@twcable.com
|
||||
#
|
||||
# == Copyright
|
||||
#
|
||||
# Copyright 2012 Puppetlabs Inc, unless otherwise noted.
|
||||
#
|
||||
class keystone::ldap(
|
||||
$url = 'ldap://localhost',
|
||||
$user = 'dc=Manager,dc=example,dc=com',
|
||||
$password = 'None',
|
||||
$suffix = 'cn=example,cn=com',
|
||||
$user_tree_dn = 'ou=Users,dc=example,dc=com',
|
||||
$tenant_tree_dn = 'ou=Roles,dc=example,dc=com',
|
||||
$role_tree_dn = 'dc=example,dc=com'
|
||||
$url = undef,
|
||||
$user = undef,
|
||||
$password = undef,
|
||||
$suffix = undef,
|
||||
$query_scope = undef,
|
||||
$page_size = undef,
|
||||
$user_tree_dn = undef,
|
||||
$user_filter = undef,
|
||||
$user_objectclass = undef,
|
||||
$user_id_attribute = undef,
|
||||
$user_name_attribute = undef,
|
||||
$user_mail_attribute = undef,
|
||||
$user_enabled_attribute = undef,
|
||||
$user_enabled_mask = undef,
|
||||
$user_enabled_default = undef,
|
||||
$user_attribute_ignore = undef,
|
||||
$user_default_project_id_attribute = undef,
|
||||
$user_allow_create = undef,
|
||||
$user_allow_update = undef,
|
||||
$user_allow_delete = undef,
|
||||
$user_pass_attribute = undef,
|
||||
$user_enabled_emulation = undef,
|
||||
$user_enabled_emulation_dn = undef,
|
||||
$user_additional_attribute_mapping = undef,
|
||||
$tenant_tree_dn = undef,
|
||||
$tenant_filter = undef,
|
||||
$tenant_objectclass = undef,
|
||||
$tenant_id_attribute = undef,
|
||||
$tenant_name_attribute = undef,
|
||||
$tenant_mail_attribute = undef,
|
||||
$tenant_enabled_attribute = undef,
|
||||
$tenant_domain_id_attribute = undef,
|
||||
$tenant_attribute_ignore = undef,
|
||||
$tenant_allow_create = undef,
|
||||
$tenant_allow_update = undef,
|
||||
$tenant_allow_delete = undef,
|
||||
$tenant_enabled_emulation = undef,
|
||||
$tenant_enabled_emulation_dn = undef,
|
||||
$tenant_additional_attribute_mapping = undef,
|
||||
$role_tree_dn = undef,
|
||||
$role_filter = undef,
|
||||
$role_objectclass = undef,
|
||||
$role_id_attribute = undef,
|
||||
$role_name_attribute = undef,
|
||||
$role_member_attribute = undef,
|
||||
$role_attribute_ignore = undef,
|
||||
$role_allow_create = undef,
|
||||
$role_allow_update = undef,
|
||||
$role_allow_delete = undef,
|
||||
$role_additional_attribute_mapping = undef,
|
||||
$group_tree_dn = undef,
|
||||
$group_filter = undef,
|
||||
$group_objectclass = undef,
|
||||
$group_id_attribute = undef,
|
||||
$group_name_attribute = undef,
|
||||
$group_member_attribute = undef,
|
||||
$group_desc_attribute = undef,
|
||||
$group_attribute_ignore = undef,
|
||||
$group_allow_create = undef,
|
||||
$group_allow_update = undef,
|
||||
$group_allow_delete = undef,
|
||||
$group_additional_attribute_mapping = undef,
|
||||
$tenant_tree_dn = undef,
|
||||
$role_tree_dn = undef,
|
||||
$use_tls = undef,
|
||||
$tls_cacertdir = undef,
|
||||
$tls_cacertfile = undef,
|
||||
$tls_req_cert = undef,
|
||||
$identity_driver = undef,
|
||||
$assignment_driver = undef,
|
||||
) {
|
||||
|
||||
package { 'python-ldap':
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
# check for some common driver name mistakes
|
||||
if ($assignment_driver != undef) {
|
||||
if ! ($assignment_driver =~ /^keystone.assignment.backends.*Assignment$/) {
|
||||
fail('assigment driver should be of the form \'keystone.assignment.backends.*Assignment\'')
|
||||
}
|
||||
}
|
||||
|
||||
if ($identity_driver != undef) {
|
||||
if ! ($identity_driver =~ /^keystone.identity.backends.*Identity$/) {
|
||||
fail('identity driver should be of the form \'keystone.identity.backends.*Identity\'')
|
||||
}
|
||||
}
|
||||
|
||||
if ($tls_cacertdir != undef) {
|
||||
file { $tls_cacertdir:
|
||||
ensure => directory
|
||||
}
|
||||
}
|
||||
|
||||
keystone_config {
|
||||
'ldap/url': value => $url;
|
||||
'ldap/user': value => $user;
|
||||
'ldap/password': value => $password;
|
||||
'ldap/suffix': value => $suffix;
|
||||
'ldap/user_tree_dn': value => $user_tree_dn;
|
||||
'ldap/tenant_tree_dn': value => $tenant_tree_dn;
|
||||
'ldap/role_tree_dn': value => $role_tree_dn;
|
||||
# 'ldap/tree_dn': value => "dc=example,dc=com";
|
||||
'ldap/url': value => $url;
|
||||
'ldap/user': value => $user;
|
||||
'ldap/password': value => $password, secret => true;
|
||||
'ldap/suffix': value => $suffix;
|
||||
'ldap/query_scope': value => $query_scope;
|
||||
'ldap/page_size': value => $page_size;
|
||||
'ldap/user_tree_dn': value => $user_tree_dn;
|
||||
'ldap/user_filter': value => $user_filter;
|
||||
'ldap/user_objectclass': value => $user_objectclass;
|
||||
'ldap/user_id_attribute': value => $user_id_attribute;
|
||||
'ldap/user_name_attribute': value => $user_name_attribute;
|
||||
'ldap/user_mail_attribute': value => $user_mail_attribute;
|
||||
'ldap/user_enabled_attribute': value => $user_enabled_attribute;
|
||||
'ldap/user_enabled_mask': value => $user_enabled_attribute;
|
||||
'ldap/user_enabled_default': value => $user_enabled_attribute;
|
||||
'ldap/user_attribute_ignore': value => $user_enabled_attribute;
|
||||
'ldap/user_default_project_id_attribute': value => $user_enabled_attribute;
|
||||
'ldap/user_allow_create': value => $user_allow_create;
|
||||
'ldap/user_allow_update': value => $user_allow_update;
|
||||
'ldap/user_allow_delete': value => $user_allow_delete;
|
||||
'ldap/user_pass_attribute': value => $user_pass_attribute;
|
||||
'ldap/user_enabled_emulation': value => $user_enabled_emulation;
|
||||
'ldap/user_enabled_emulation_dn': value => $user_enabled_emulation_dn;
|
||||
'ldap/tenant_tree_dn': value => $tenant_tree_dn;
|
||||
'ldap/tenant_filter': value => $tenant_filter;
|
||||
'ldap/tenant_objectclass': value => $tenant_objectclass;
|
||||
'ldap/tenant_id_attribute': value => $tenant_id_attribute;
|
||||
'ldap/tenant_name_attribute': value => $tenant_name_attribute;
|
||||
'ldap/tenant_mail_attribute': value => $tenant_mail_attribute;
|
||||
'ldap/tenant_enabled_attribute': value => $tenant_enabled_attribute;
|
||||
'ldap/tenant_attribute_ignore': value => $tenant_attribute_ignore;
|
||||
'ldap/tenant_domain_id_attribute': value => $tenant_domain_id_attribute;
|
||||
'ldap/tenant_allow_create': value => $tenant_allow_create;
|
||||
'ldap/tenant_allow_update': value => $tenant_allow_update;
|
||||
'ldap/tenant_allow_delete': value => $tenant_allow_delete;
|
||||
'ldap/tenant_enabled_emulation': value => $tenant_enabled_emulation;
|
||||
'ldap/tenant_enabled_emulation_dn': value => $tenant_enabled_emulation_dn;
|
||||
'ldap/tenant_additional_attribute_mapping': value => $tenant_additional_attribute_mapping;
|
||||
'ldap/role_tree_dn': value => $role_tree_dn;
|
||||
'ldap/role_filter': value => $role_filter;
|
||||
'ldap/role_objectclass': value => $role_objectclass;
|
||||
'ldap/role_id_attribute': value => $role_id_attribute;
|
||||
'ldap/role_name_attribute': value => $role_name_attribute;
|
||||
'ldap/role_member_attribute': value => $role_member_attribute;
|
||||
'ldap/role_attribute_ignore': value => $role_attribute_ignore;
|
||||
'ldap/role_allow_create': value => $role_allow_create;
|
||||
'ldap/role_allow_update': value => $role_allow_update;
|
||||
'ldap/role_allow_delete': value => $role_allow_delete;
|
||||
'ldap/role_additional_attribute_mapping': value => $role_additional_attribute_mapping;
|
||||
'ldap/group_tree_dn': value => $group_tree_dn;
|
||||
'ldap/group_filter': value => $group_filter;
|
||||
'ldap/group_objectclass': value => $group_objectclass;
|
||||
'ldap/group_id_attribute': value => $group_id_attribute;
|
||||
'ldap/group_name_attribute': value => $group_name_attribute;
|
||||
'ldap/group_member_attribute': value => $group_member_attribute;
|
||||
'ldap/group_desc_attribute': value => $group_desc_attribute;
|
||||
'ldap/group_attribute_ignore': value => $group_attribute_ignore;
|
||||
'ldap/group_allow_create': value => $group_allow_create;
|
||||
'ldap/group_allow_update': value => $group_allow_update;
|
||||
'ldap/group_allow_delete': value => $group_allow_delete;
|
||||
'ldap/group_additional_attribute_mapping': value => $group_additional_attribute_mapping;
|
||||
'ldap/use_tls': value => $use_tls;
|
||||
'ldap/tls_cacertdir': value => $tls_cacertdir;
|
||||
'ldap/tls_cacertfile': value => $tls_cacertfile;
|
||||
'ldap/tls_req_cert': value => $tls_req_cert;
|
||||
'identity/driver': value => $identity_driver;
|
||||
'assignment/driver': value => $assignment_driver;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,27 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'keystone::ldap' do
|
||||
|
||||
describe 'with default params' do
|
||||
|
||||
it 'should contain default params' do
|
||||
|
||||
should contain_keystone_config('ldap/url').with_value('ldap://localhost')
|
||||
should contain_keystone_config('ldap/user').with_value('dc=Manager,dc=example,dc=com')
|
||||
should contain_keystone_config('ldap/password').with_value('None')
|
||||
should contain_keystone_config('ldap/suffix').with_value('cn=example,cn=com')
|
||||
should contain_keystone_config('ldap/user_tree_dn').with_value('ou=Users,dc=example,dc=com')
|
||||
should contain_keystone_config('ldap/tenant_tree_dn').with_value('ou=Roles,dc=example,dc=com')
|
||||
should contain_keystone_config('ldap/role_tree_dn').with_value('dc=example,dc=com')
|
||||
describe 'with basic params' do
|
||||
let :params do
|
||||
{
|
||||
:url => 'ldap://foo',
|
||||
:user => 'cn=foo,dc=example,dc=com',
|
||||
:password => 'abcdefg',
|
||||
:user_tree_dn => 'cn=users,dc=example,dc=com',
|
||||
:user_allow_create => 'False',
|
||||
:user_allow_update => 'False',
|
||||
:user_allow_delete => 'False',
|
||||
}
|
||||
end
|
||||
it { should contain_package('python-ldap') }
|
||||
it 'should have basic params' do
|
||||
should contain_keystone_config('ldap/url').with_value('ldap://foo')
|
||||
should contain_keystone_config('ldap/user').with_value('cn=foo,dc=example,dc=com')
|
||||
should contain_keystone_config('ldap/password').with_value('abcdefg').with_secret(true)
|
||||
should contain_keystone_config('ldap/user_tree_dn').with_value('cn=users,dc=example,dc=com')
|
||||
should contain_keystone_config('ldap/user_allow_create').with_value('False')
|
||||
should contain_keystone_config('ldap/user_allow_update').with_value('False')
|
||||
should contain_keystone_config('ldap/user_allow_delete').with_value('False')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user