[openstack-dev] Keystone Split Backend Debugging

Miller, Mark M (EB SW Cloud - R&D - Corvallis) mark.m.miller at hp.com
Mon Jul 29 22:59:18 UTC 2013


I have a little more information after adding logging statements and try catch blocks to loadwsgi.py:

2013-07-19 14:11:38    DEBUG [root] ********** After use_eventlet ******
2013-07-19 14:11:38    DEBUG [root] ***** In create_server *****
2013-07-19 14:11:38    DEBUG [root] ***** Paramters (/etc/keystone/keystone-paste.ini, admin)  *****
2013-07-19 14:11:38    DEBUG [root] ***** In loadapp (config:/etc/keystone/keystone-paste.ini, admin) *****
2013-07-19 14:11:38    DEBUG [root] ***** In loadobj (config:/etc/keystone/keystone-paste.ini, admin) *****
2013-07-19 14:11:38    DEBUG [root] ***** In loadcontext (config:/etc/keystone/keystone-paste.ini, admin) *****
2013-07-19 14:11:38    DEBUG [root] ***** In loadcontext (egg:Paste#urlmap, None) *****
2013-07-19 14:11:38    DEBUG [root] loadobj Exception: No module named ldap

Mark

From: Miller, Mark M (EB SW Cloud - R&D - Corvallis)
Sent: Monday, July 29, 2013 2:44 PM
To: OpenStack Development Mailing List (openstack-dev at lists.openstack.org<mailto:openstack-dev at lists.openstack.org>)
Subject: [openstack-dev] Keystone Split Backend Debugging

Hello,

Summary:

I am attempting to configure the Keystone H-2 release to use an Enterprise Directory as the Identity backend and SQL as the Assignment backend (without TLS for now). I first installed Keystone H-2 on an Ubuntu vm server and got it up and running using a local SQL database for both the Identity and Assignment backend. I then changed the [identity] section to use "driver = keystone.identity.backends.ldap.Identity" as well as attempting to set many of the variables in the [ldap] section of file keystone.conf. I did not expect it to work right off the bat, but I am getting no error information in the keystone.log file so I am trying to figure out how to debug what is failing. I also have tcpdump on and it is not recording any requests for the ldap port:

        tcpdump -i eth0 host ldap. mycompany.com -vv

Details:

The following non-secure python test code works to test the LDAP server connection:

host = 'ldap://ldap.mycompany.com:389'
base = 'o= mycompany.com'
scope = ldap.SCOPE_SUBTREE

def get_user_public_data(userEmail):

    ldapBound = False

    try:
        attrs = ['cn', 'mail', 'uid']

        ldap_client = ldap.initialize(host)
        r = ldap_client.search_s(base, scope, '(uid=%s)' % userEmail, attrs)

        for dn, entry in r:
            print 'dn=', repr(dn)

            for k in entry.keys():
                print '\t', k, '=', entry[k]

        return "LDAP get public data completed"

    except ldap.INVALID_CREDENTIALS, errMsg:
        return 'Wrong username ili password. Error: %s' % errMsg
    except ldap.SERVER_DOWN, errMsg:
        return 'AD server not awailable. Error: %s' % errMsg
    except ldap.LDAPError, errMsg:
        return "Couldn't Connect. Error: %s" % errMsg
    finally:
        if ldapBound:
            ldap_client.unbind_s()


print ('get_user_public_data: ' + get_user_public_data('mark.m.miller@ mycompany.com' ))

sys.exit(0)

The following secure python test code also works:

import sys
import ldap
import getpass

host = 'ldaps://ldap. mycompany.com:636'
base = 'o= mycompany.com'
scope = ldap.SCOPE_SUBTREE

binduser = "cn=KeystoneDevUser, ou=Applications, o= mycompany.com"
bindpw = "secretword;"

def get_user_public_data(userEmail):

    ldapBound = False

    try:
        # build a client
#        ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND)
        ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, "d:/etc/ssl/certs/hpca2ssG2_ns.cer")
#        ldap.set_option( ldap.OPT_DEBUG_LEVEL, 255 )

        ldap_client = ldap.initialize(host)
        ldap_client.protocol_version = ldap.VERSION3

        # perform a synchronous bind
        ldap_client.simple_bind_s(binduser,bindpw)
        ldapBound = True

        filter = ('(uid=%s)' % userEmail)
        attrs = ['cn', 'mail', 'uid', ' employeeStatus']

        r = ldap_client.search_s(base, scope, filter, attrs)

        for dn, entry in r:
            print 'dn=', repr(dn)

            for k in entry.keys():
                print '\t', k, '=', entry[k]

        return "LDAP get public data completed"

    except ldap.INVALID_CREDENTIALS, errMsg:
        return 'Wrong username ili password. Error: %s' % errMsg
    except ldap.SERVER_DOWN, errMsg:
        return 'AD server not awailable. Error: %s' % errMsg
    except ldap.LDAPError, errMsg:
        return "Couldn't Connect. Error: %s" % errMsg
    finally:
        if ldapBound:
            ldap_client.unbind_s()


print ('get_user_public_data: ' + get_user_public_data('mark.m.miller@ mycompany.com' ))

sys.exit(0)

Here is my keystone.conf file:

[DEFAULT]
# A "shared secret" between keystone and other openstack services
admin_token = 012345SECRET99TOKEN012345

# The IP address of the network interface to listen on
bind_host = 0.0.0.0

# The port number which the public service listens on
public_port = 5000

# The port number which the public admin listens on
admin_port = 35357

# The base endpoint URLs for keystone that are advertised to clients
# (NOTE: this does NOT affect how keystone listens for connections)
public_endpoint = http://localhost:%(public_port)s/<http://localhost:%25(public_port)s/>
admin_endpoint = http://localhost:%(admin_port)s/<http://localhost:%25(admin_port)s/>

# The port number which the OpenStack Compute service listens on
compute_port = 8774

# Path to your policy definition containing identity actions
policy_file = policy.json

# Rule to check if no matching policy definition is found
# FIXME(dolph): This should really be defined as [policy] default_rule
policy_default_rule = admin_required

# Role for migrating membership relationships
# During a SQL upgrade, the following values will be used to create a new role
# that will replace records in the user_tenant_membership table with explicit
# role grants.  After migration, the member_role_id will be used in the API
# add_user_to_project, and member_role_name will be ignored.
member_role_id = 9fe2ff9ee4384b1894a90878d3e92bab
member_role_name = _member_

# enforced by optional sizelimit middleware (keystone.middleware:RequestBodySizeLimiter)
max_request_body_size = 114688

# limit the sizes of user & tenant ID/names
max_param_size = 64

# similar to max_param_size, but provides an exception for token values
# max_token_size = 8192
max_token_size = 32768

# === Logging Options ===
# Print debugging output
# (includes plaintext request logging, potentially including passwords)
debug = True

# Print more verbose output
verbose = True

# Name of log file to output to. If not set, logging will go to stdout.
log_file = keystone.log

# The directory to keep log files in (will be prepended to --logfile)
log_dir = /var/log/keystone

# Use syslog for logging.
use_syslog = False

# syslog facility to receive log lines
# syslog_log_facility = LOG_USER

# If this option is specified, the logging configuration file specified is
# used and overrides any other logging options specified. Please see the
# Python logging module documentation for details on logging configuration
# files.
# log_config = logging.conf

# A logging.Formatter log message format string which may use any of the
# available logging.LogRecord attributes.
log_format = %(asctime)s %(levelname)8s [%(name)s] %(message)s

# Format string for %(asctime)s in log records.
log_date_format = %Y-%m-%d %H:%M:%S

# onready allows you to send a notification when the process is ready to serve
# For example, to have it notify using systemd, one could set shell command:
# onready = systemd-notify --ready
# or a module with notify() method:
# onready = keystone.common.systemd

[sql]
# The SQLAlchemy connection string used to connect to the database
# connection = sqlite:///keystone.db
connection = mysql://keystonedbadmin:password@15.253.58.141/keystone

# the timeout before idle sql connections are reaped
idle_timeout = 200

[identity]
driver = keystone.identity.backends.ldap.Identity
# driver = keystone.identity.backends.sql.Identity

# This references the domain to use for all Identity API v2 requests (which are
# not aware of domains). A domain with this ID will be created for you by
# keystone-manage db_sync in migration 008.  The domain referenced by this ID
# cannot be deleted on the v3 API, to prevent accidentally breaking the v2 API.
# There is nothing special about this domain, other than the fact that it must
# exist to order to maintain support for your v2 clients.
default_domain_id = default

[credential]
driver = keystone.credential.backends.sql.Credential

[trust]
# driver = keystone.trust.backends.sql.Trust

# delegation and impersonation features can be optionally disabled
# enabled = True

[os_inherit]
# role-assignment inheritance to projects from owning domain can be
# optionally enabled
# enabled = False

[catalog]
# dynamic, sql-based backend (supports API/CLI-based management commands)
driver = keystone.catalog.backends.sql.Catalog

# static, file-based backend (does *NOT* support any management commands)
# driver = keystone.catalog.backends.templated.TemplatedCatalog

template_file = default_catalog.templates

[token]
# Provides token persistence.
driver = keystone.token.backends.sql.Token

# Controls the token construction, validation, and revocation operations.
# provider = keystone.token.providers.pki.Provider

# Amount of time a token should remain valid (in seconds)
expiration = 999986400

# External auth mechanisms that should add bind information to token.
# eg kerberos, x509
# bind =

# Enforcement policy on tokens presented to keystone with bind information.
# One of disabled, permissive, strict, required or a specifically required bind
# mode e.g. kerberos or x509 to require binding to that authentication.
# enforce_token_bind = permissive

[policy]
driver = keystone.policy.backends.sql.Policy

[ec2]
driver = keystone.contrib.ec2.backends.kvs.Ec2

[assignment]
driver = keystone.assignment.backends.sql.Assignment

[ssl]
#enable = True
enable = False
#certfile = /etc/keystone/pki/certs/ssl_cert.pem
#keyfile = /etc/keystone/pki/private/ssl_key.pem
#ca_certs = /etc/keystone/pki/certs/cacert.pem
#ca_key = /etc/keystone/pki/private/cakey.pem
#key_size = 1024
#valid_days = 3650
#ca_password = None
#cert_required = False
#cert_subject = /C=US/ST=Unset/L=Unset/O=Unset/CN=localhost

[signing]
# Deprecated in favor of provider in the [token] section
token_format = UUID
#token_format = PKI

#certfile = /etc/keystone/pki/certs/signing_cert.pem
#keyfile = /etc/keystone/pki/private/signing_key.pem
#ca_certs = /etc/keystone/pki/certs/cacert.pem
#ca_key = /etc/keystone/pki/private/cakey.pem
#key_size = 2048
#valid_days = 3650
#ca_password = None
#cert_subject = /C=US/ST=Unset/L=Unset/O=Unset/CN=www.example.com

[ldap]
url = "ldap://ldap. mycompany.com:389"
# url = "ldaps://ldap. mycompany.com:636"
user = "cn=KeystoneDevUser, ou=Applications, o= mycompany.com"
password = "secretword;"
suffix = "o= mycompany.com"
# suffix = cn=example,cn=com
use_dumb_member = False
allow_subtree_delete = False
# dumb_member = cn=dumb,dc=example,dc=com

# Maximum results per page; a value of zero ('0') disables paging (default)
page_size = 0

# The LDAP dereferencing option for queries. This can be either 'never',
# 'searching', 'always', 'finding' or 'default'. The 'default' option falls
# back to using default dereferencing configured by your ldap.conf.
# alias_dereferencing = default

# The LDAP scope for queries, this can be either 'one'
# (onelevel/singleLevel) or 'sub' (subtree/wholeSubtree)
# query_scope = one

# user_tree_dn = ou=Users,dc=example,dc=com
user_tree_dn = ou=People,o= mycompany.com
# user_filter =
user_objectclass = People
# user_domain_id_attribute = businessCategory
# user_id_attribute = cn
user_id_attribute = uid
user_name_attribute = cn
user_mail_attribute = mail
user_pass_attribute = userPassword
user_enabled_attribute = employeeStatus
# user_enabled_mask = 0
user_enabled_default = "Active"
user_attribute_ignore = tenant_id,tenants
user_allow_create = False
user_allow_update = False
user_allow_delete = False
user_enabled_emulation = False
# user_enabled_emulation_dn =

# tenant_tree_dn = ou=Projects,dc=example,dc=com
# tenant_filter =
# tenant_objectclass = groupOfNames
# tenant_domain_id_attribute = businessCategory
# tenant_id_attribute = cn
# tenant_member_attribute = member
# tenant_name_attribute = ou
# tenant_desc_attribute = desc
# tenant_enabled_attribute = enabled
# tenant_attribute_ignore =
# tenant_allow_create = True
# tenant_allow_update = True
# tenant_allow_delete = True
# tenant_enabled_emulation = False
# tenant_enabled_emulation_dn =

# role_tree_dn = ou=Roles,dc=example,dc=com
# role_filter =
# role_objectclass = organizationalRole
# role_id_attribute = cn
# role_name_attribute = ou
# role_member_attribute = roleOccupant
# role_attribute_ignore =
# role_allow_create = True
# role_allow_update = True
# role_allow_delete = True

# group_tree_dn =
# group_filter =
# group_objectclass = groupOfNames
# group_id_attribute = cn
# group_name_attribute = ou
# group_member_attribute = member
# group_desc_attribute = desc
# group_attribute_ignore =
# group_allow_create = True
# group_allow_update = True
# group_allow_delete = True

# ldap TLS options
# if both tls_cacertfile and tls_cacertdir are set then
# tls_cacertfile will be used and tls_cacertdir is ignored
# valid options for tls_req_cert are demand, never, and allow
use_tls = False
# tls_cacertfile =
tls_cacertdir =
# tls_req_cert = demand

# Additional attribute mappings can be used to map ldap attributes to internal
# keystone attributes. This allows keystone to fulfill ldap objectclass
# requirements. An example to map the description and gecos attributes to a
# user's name would be:
# user_additional_attribute_mapping = description:name, gecos:name
#
# domain_additional_attribute_mapping =
# group_additional_attribute_mapping =
# role_additional_attribute_mapping =
# project_additional_attribute_mapping =
# user_additional_attribute_mapping =

[auth]
methods = external,password,token
#external = keystone.auth.plugins.external.ExternalDefault
password = keystone.auth.plugins.password.Password
token = keystone.auth.plugins.token.Token

[paste_deploy]
# Name of the paste configuration file that defines the available pipelines
config_file = keystone-paste.ini

Keystone.log file contents:

        Simply restates the keystone.conf file contents.



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstack.org/pipermail/openstack-dev/attachments/20130729/57d03140/attachment.html>


More information about the OpenStack-dev mailing list