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/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/tree_dn':        value => "dc=example,dc=com";
 | 
			
		||||
    '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