×

【Ovirt 笔记】engine 用户扩展管理分析与整理

96
羽杰
2018.06.13 11:41* 字数 1661

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

分析整理的版本为 Ovirt 4.2.3 版本。

1. 用户与角色

  • Red Hat 虚拟化包含两种用户域(本地用户域和外部用户域)
    • 本地用户域
      • 在 engine(engine-setup) 安装的过程中会创建一个称之为内部域的本地用户域和一个 admin 的默认用户。
      • 可以使用 ovirt-aaa-jdbc-tool 工具在内部域上创建附加用户。
      • 在本地域上创建的用户被称之为本地用户。
    • 外部用户域
      • 可以将外部目录服务器(如 Red Hat Directory Server、ActiveDirectory、OpenLDAP 和许多其他支持的选项)附加到 Red Hat 虚拟化环境中,并将它们用作外部域。
      • 在外部域上创建的用户帐户被称为目录用户。
  • 本地用户和目录用户都需要 engine 分配适当的角色和权限,才能在环境中运行。
  • 通过使用 ovirt-engine-extension-aaa-jdbc 可以创建除了默认内部域之外的本地用户域。
  • 通过使用 ovirt-engine-extension-aaa-ldap 可以定制外部目录设置,扩展支持许多不同的 LDAP 服务器类型。
    • 提供了一个交互式设置脚本,帮助设置大多数 LDAP 类型。

2. 本地用户域

  • aaa-jdbc 扩展来自于 ovirt 3.6 版本,提供了默认的 internal 内部配置文件。
    • 升级 ovirt 3.5 时,将该版本之前传统供应商修改为 aaa-jdbc 供应商。
    • 相关配置可以通过 aaa-jdbc 提供的配置文件完成。
    • 配置在执行 engine-setup 的时候完成。

2.1 创建 aaa-jdbc 配置文件

  • engien-setup 配置相关的执行
@util.export
def createPlugins(context):
    aaa.Plugin(context=context)
    aaainternal.Plugin(context=context)
......
  • 其中 aaainternal.py 中创建了 aaa-jdbc 的默认内部域配置文件。
self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append(
            filetransaction.FileTransaction(
                name=(
                    os.path.join(
                        oenginecons.FileLocations.OVIRT_ENGINE_EXTENSIONS_DIR,
                        '%s-authn.properties' % profile
                    )
                ),
                mode=0o600,
                owner=self.environment[osetupcons.SystemEnv.USER_ENGINE],
                enforcePermissions=True,
                content=(
                    'ovirt.engine.extension.name = internal-authn\n'
                    'ovirt.engine.extension.bindings.method = jbossmodule\n'

                    'ovirt.engine.extension.binding.jbossmodule.module = '
                    'org.ovirt.engine.extensions.builtin\n'

                    'ovirt.engine.extension.binding.jbossmodule.class = '
                    'org.ovirt.engine.extensions.aaa.builtin.internal.'
                    'InternalAuthn\n'

                    'ovirt.engine.extension.provides = '
                    'org.ovirt.engine.api.extensions.aaa.Authn\n'

                    'ovirt.engine.aaa.authn.profile.name = {profile}\n'
                    'ovirt.engine.aaa.authn.authz.plugin = {authzName}\n'
                    'config.authn.user.name = {admin_user}\n'
                    'config.authn.user.password = {pbe}\n'
  • 创建的配置文件路径在 /etc/ovirt-engine/extensions.d 目录中。
    • internal-authz.properties 为授权配置。
    • internal-authn.properties 为认证配置。
[root@rhvm extensions.d]# pwd
/etc/ovirt-engine/extensions.d
[root@rhvm extensions.d]# ls
internal-authn.properties  internal-authz.properties
  • internal-authn.properties 的内容。
[root@rhvm extensions.d]# cat internal-authn.properties 
ovirt.engine.extension.name = internal-authn
ovirt.engine.extension.bindings.method = jbossmodule
ovirt.engine.extension.binding.jbossmodule.module = org.ovirt.engine.extensions.builtin
ovirt.engine.extension.binding.jbossmodule.class = org.ovirt.engine.extensions.aaa.builtin.internal.InternalAuthn
ovirt.engine.extension.provides = org.ovirt.engine.api.extensions.aaa.Authn
ovirt.engine.aaa.authn.profile.name = internal
ovirt.engine.aaa.authn.authz.plugin = internal-authz
参数 说明
ovirt.engine.extension.name 扩展模块的名称为 internal-authn。
ovirt.engine.extension.bindings.method 扩展的方法,使用了 Jboss 的 module。
ovirt.engine.extension.binding.jbossmodule.module 加载的 Jboss module。
ovirt.engine.extension.binding.jbossmodule.class 加载 Jboss module 的 class 类。
ovirt.engine.extension.provides 使用的供应者类(代理)。
ovirt.engine.aaa.authn.profile.name 域名。
ovirt.engine.aaa.authn.authz.plugin 依赖的模块。
config.datasource.file 数据库相关配置文件路径。
ovirt.engine.extension.enabled 是否启用,默认为 true。
  • internal-authz.properties 的内容。
[root@rhvm extensions.d]# cat internal-authz.properties 
ovirt.engine.extension.name = internal-authz
ovirt.engine.extension.bindings.method = jbossmodule
ovirt.engine.extension.binding.jbossmodule.module = org.ovirt.engine.extensions.builtin
ovirt.engine.extension.binding.jbossmodule.class = org.ovirt.engine.extensions.aaa.builtin.internal.InternalAuthz
ovirt.engine.extension.provides = org.ovirt.engine.api.extensions.aaa.Authz
参数 说明
ovirt.engine.extension.name 扩展模块的名称 internal-authz。
ovirt.engine.extension.bindings.method 扩展的方法,使用了 Jboss 的 module。
ovirt.engine.extension.binding.jbossmodule.module 加载的 Jboss module。
ovirt.engine.extension.binding.jbossmodule.class 加载 Jboss module 的 class 类。
ovirt.engine.extension.provides 使用的供应者类(代理)。
config.datasource.file 数据库相关配置文件路径。
ovirt.engine.extension.enabled 是否启用,默认为 true。

2.2 加载 aaa-jdbc 配置信息

  • engine 使用 EngineExtensionsManager 类进行配置信息的加载。
    • 在 engine 初始化的 Backend 类中执行。
EngineExtensionsManager.getInstance().engineInitialize();
  • 读取用户扩展管理的配置文件。
    • 配置目录为 /user/share/ovirt-engine/extensions.d/etc/ovirt-engine/extensions.d
[root@rhvm extensions.d]# cat /usr/share/ovirt-engine/services/ovirt-engine/ovirt-engine.conf | grep ENGINE_EXTENSION_PATH
ENGINE_EXTENSION_PATH="${ENGINE_USR}/extensions.d:${ENGINE_ETC}/extensions.d"
for (File directory : EngineLocalConfig.getInstance().getExtensionsDirectories()) {
            if (!directory.exists()) {
                log.warn("The directory '{}' cotaning configuration files does not exist.",
                        directory.getAbsolutePath());
            } else {

                // The order of the files inside the directory is relevant, as the objects are created in
                // the same order
                // that
                // the files are processed, so it is better to sort them so that objects will always be
                // created in the
                // same
                // order regardless of how the filesystem decides to store the entries of the directory:
                File[] files = directory.listFiles();
                if (files != null) {
                    sort(files);
                    for (File file : files) {
                        if (file.getName().endsWith(".properties")) {
                            try {
                                load(file);
                            } catch (Exception ex) {
                                log.error("Could not load extension based on configuration file '{}'. Please check the configuration file is valid. Exception message is: {}",
                                        file.getAbsolutePath(),
                                        ex.getMessage());
                                log.debug("", ex);
                            }
                        }
                    }
                }
            }
}
public String load(File file) {
        try (
            InputStream is = new FileInputStream(file);
            Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)
        ) {
            Properties props = new Properties();
            props.load(reader);
            return loadImpl(props, file);
        } catch (IOException exception) {
            throw new ConfigurationException(String.format("Can't load object configuration file '%1$s': %2$s",
                    file.getAbsolutePath(), exception.getMessage()), exception);
        }
}
  • 根据配置等信息,生成扩展实体对象。
    • loadedEntries 链表中包含了不同用户域(ovirt.engine.extension.name)和其配置文件对象的映射关系。
    • bindingsLoaders 链表中包含了不同构造器(bindingsLoader)和其名称(ovirt.engine.extension.bindings.method)的映射关系,这里是 jbossmodule,对应了 JBossBindingsLoader 构造器。
    • JBossBindingsLoader 可以通过指定 module 名称加载不同的 Jboss module。
ExtensionEntry entry = new ExtensionEntry(props, confFile);
......
entry.extension = loadExtension(props);
            entry.extension.getContext().mput(
                    Base.ContextKeys.GLOBAL_CONTEXT,
                    globalContext
                    ).mput(
                            TRACE_LOG_CONTEXT_KEY,
                            traceLog
                    ).mput(
                            Base.ContextKeys.INTERFACE_VERSION_MIN,
                            0
                    ).mput(
                            Base.ContextKeys.INTERFACE_VERSION_MAX,
                            Base.INTERFACE_VERSION_CURRENT
                    ).mput(
                            Base.ContextKeys.LOCALE,
                            Locale.getDefault().toString()
                    ).mput(
                            Base.ContextKeys.CONFIGURATION_FILE,
                            entry.file == null ? null : entry.file.getAbsolutePath()
                    ).mput(
                            Base.ContextKeys.CONFIGURATION,
                            props
                    ).mput(
                            Base.ContextKeys.CONFIGURATION_SENSITIVE_KEYS,
                            splitString(props.getProperty(Base.ConfigKeys.SENSITIVE_KEYS, ""))
                    ).mput(
                            Base.ContextKeys.INSTANCE_NAME,
                            entry.name
                    ).mput(
                            Base.ContextKeys.PROVIDES,
                            splitString(props.getProperty(Base.ConfigKeys.PROVIDES, ""))
                    );
  • 根据配置文件中定义的构造器(bindingsLoader)名称,获得不同的构造器,再由此构造器加载配置文件中指定的 Jboss module 和执行指定的 Jboss module class。
BindingsLoader loader = bindingsLoaders.get(props.getProperty(Base.ConfigKeys.BINDINGS_METHOD));
......
public ExtensionProxy load(Properties props) throws Exception {
            Module module = loadModule(
                props.getProperty(Base.ConfigKeys.BINDINGS_JBOSSMODULE_MODULE)
            );

            return new ExtensionProxy(
                module.getClassLoader(),
                lookupService(
                    module,
                    Extension.class,
                    props.getProperty(Base.ConfigKeys.BINDINGS_JBOSSMODULE_CLASS)
                ).newInstance()
            );
}
  • 根据配置文件中指定的值
    • 加载的 Jboss module 是 org.ovirt.engine.extensions.builtin
    • 执行的类是 org.ovirt.engine.extensions.aaa.builtin.internal.InternalAuthn
  • ExtensionProxy 是一个扩展代理类,在加载 Jboss module 的时候会进行创建,并把指定执行的 Jboss module class 类实例化后的对象放入其中。这里为 InternalAuthn 对象和 InternalAuthz 对象。
  • ExtensionProxy 类中包含了一个 ExtMap 对象。该对象是一个 ConcurrentMap,包含有扩展属性和值的映射关系。

2.3 使用默认的本地用户域支持

  • 上述配置文件中指定的 Jboss module class 就是对该扩展支持的实现策略。
    • 默认情况下使用 InternalAuthn 处理用户的认证,使用 InternalAuthz 处理用户的授权。
  • 用户 Sso 登录使用了 AuthenticationUtils 类中的 login 方法进行登录认证。
    • 其中 profile 为 ExtensionProxy 扩展代理类,authn 即 InternalAuthn
    • 执行 InternalAuthninvoke 进行认证处理。
ExtMap outputMap = profile.authn.invoke(new ExtMap().mput(
                            Base.InvokeKeys.COMMAND,
                            Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS
                    ).mput(
                            Authn.InvokeKeys.USER,
                            user
                    ).mput(
                            Authn.InvokeKeys.CREDENTIALS,
                            credentials.getPassword()
                    )
public void invoke(ExtMap input, ExtMap output) {
        try {
            if (input.get(Base.InvokeKeys.COMMAND).equals(Base.InvokeCommands.LOAD)) {
                doLoad(input);
            } else if (input.get(Base.InvokeKeys.COMMAND).equals(Base.InvokeCommands.INITIALIZE)) {
                // Do nothing
            } else if (input.get(Base.InvokeKeys.COMMAND).equals(Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS)) {
                doAuthenticate(input, output);
            } else {
                output.put(Base.InvokeKeys.RESULT, Base.InvokeResult.UNSUPPORTED);
            }
            output.putIfAbsent(Base.InvokeKeys.RESULT, Base.InvokeResult.SUCCESS);
        } catch (Exception ex) {
            output.mput(Base.InvokeKeys.RESULT, Base.InvokeResult.FAILED).
                   mput(Base.InvokeKeys.MESSAGE, ex.getMessage());
        }

}
  • 根据传递不同的 COMMAND,进行不同的处理。
    • AUTHENTICATE_CREDENTIALS 进行用户认证。
    • USER 传递的是用户。
    • CREDENTIALS 传递的是密码。
private void doAuthenticate(ExtMap input, ExtMap output) throws IOException, GeneralSecurityException {
        output.put(Authn.InvokeKeys.PRINCIPAL, input.get(Authn.InvokeKeys.USER));
        if (
            input.get(Authn.InvokeKeys.USER).equals(adminUser) &&
            EnvelopePBE.check(adminPassword, input.get(Authn.InvokeKeys.CREDENTIALS))
        ) {
            output.mput(
                    Authn.InvokeKeys.RESULT,
                    Authn.AuthResult.SUCCESS
                    ).mput(
                            Authn.InvokeKeys.AUTH_RECORD,
                            new ExtMap().mput(
                                    Authn.AuthRecord.PRINCIPAL,
                                    adminUser
                                    )
                    );
        } else {
            output.put(Authn.InvokeKeys.RESULT, Authn.AuthResult.CREDENTIALS_INVALID);
        }
}
......
Properties config = context.get(Base.ContextKeys.CONFIGURATION);
adminUser = config.getProperty("config.authn.user.name", "admin");
adminPassword = config.getProperty("config.authn.user.password");
  • 认证后进行不同结果的组装并返回。至此完成默认本地用户域的认证,授权模块类似。

2.4 使用扩展的本地用户域支持

  • Ovirt 4.2 版本中,安装 ovirt-engine-extension-aaa-jdbc 的 rpm 包, aaa-jdbc 提供的配置文件会被覆盖为新的配置文件。
  • 新配置文件,同样在 engine-setup 过程中创建。
    • 其中 aaajdbc.py 中创建了 aaa-jdbc 的扩展内部域配置文件。
    • 使用 AuthnExtension 处理用户的认证,使用 AuthzExtension 处理用户的授权。
@util.export
def createPlugins(context):
    aaa.Plugin(context=context)
    ......
    aaajdbc.Plugin(context=context)
......
  • internal-authn.properties 的内容。
yum install ovirt-engine-extension-aaa-jdbc
[root@rhvm extensions.d]# cat internal-authn.properties
ovirt.engine.extension.name = internal-authn
ovirt.engine.extension.bindings.method = jbossmodule
ovirt.engine.extension.binding.jbossmodule.module = org.ovirt.engine.extension.aaa.jdbc
ovirt.engine.extension.binding.jbossmodule.class = org.ovirt.engine.extension.aaa.jdbc.binding.api.AuthnExtension
ovirt.engine.extension.provides = org.ovirt.engine.api.extensions.aaa.Authn
ovirt.engine.aaa.authn.profile.name = internal
ovirt.engine.aaa.authn.authz.plugin = internal-authz
config.datasource.file = /etc/ovirt-engine/aaa/internal.properties
  • internal-authz.properties 的内容。
[root@rhvm extensions.d]# cat internal-authz.properties
ovirt.engine.extension.name = internal-authz
ovirt.engine.extension.bindings.method = jbossmodule
ovirt.engine.extension.binding.jbossmodule.module = org.ovirt.engine.extension.aaa.jdbc
ovirt.engine.extension.binding.jbossmodule.class = org.ovirt.engine.extension.aaa.jdbc.binding.api.AuthzExtension
ovirt.engine.extension.provides = org.ovirt.engine.api.extensions.aaa.Authz
config.datasource.file = /etc/ovirt-engine/aaa/internal.properties
  • 加载的 Jboss module 修改为 org.ovirt.engine.extension.aaa.jdbc,执行的 Jboss module class 修改为 org.ovirt.engine.extension.aaa.jdbc.binding.api.AuthnExtension
  • AuthnExtension 类的代码,在 ovirt-engine-extension-aaa-jdbc 的源码包中可以找到。
  • 与默认的本地用户域支持一样的加载和执行方式。Sso 登录调用了 AuthnExtensioninvoke 方法。
public void invoke(ExtMap input, ExtMap output) {
        try {
            if (tasks != null) {
                tasks.execute();
            }
            if (input.get(Base.InvokeKeys.COMMAND).equals(Base.InvokeCommands.LOAD)) {
                doLoad(input);
            } else if (input.get(Base.InvokeKeys.COMMAND).equals(Base.InvokeCommands.INITIALIZE)) {
                doInit(input);
            } else if (input.get(Base.InvokeKeys.COMMAND).equals(Base.InvokeCommands.TERMINATE)) {
                // Nothing to do.
            } else if (
                (input.get(Base.InvokeKeys.COMMAND).equals(Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS)) ||
                (input.get(Base.InvokeKeys.COMMAND).equals(Authn.InvokeCommands.CREDENTIALS_CHANGE))
            ) {
                doAuth(input, output);
            } else {
                output.put(Base.InvokeKeys.RESULT, Base.InvokeResult.UNSUPPORTED);
                throw new IllegalArgumentException("unsupported:" + input.get(Base.InvokeKeys.COMMAND));
            }
            output.mput(Base.InvokeKeys.RESULT, Base.InvokeResult.SUCCESS);
        } catch (Throwable e) {
            LOG.error(
                "Unexpected Exception invoking: {}",
                input.<ExtUUID>get(Base.InvokeKeys.COMMAND)
            );
            LOG.debug(
                "Exception:",
                e
            );
            output.putIfAbsent(Base.InvokeKeys.RESULT, Base.InvokeResult.FAILED);
            output.put(Base.InvokeKeys.MESSAGE, e.getMessage());
        }
}
  • 用户认证执行。
Authentication.AuthResponse response = authentication.doAuth(
            input.get(Authn.InvokeKeys.USER, String.class),
            input.get(Authn.InvokeKeys.CREDENTIALS, String.class),
            input.get(Base.InvokeKeys.COMMAND).equals(Authn.InvokeCommands.CREDENTIALS_CHANGE),
            input.get(Authn.InvokeKeys.CREDENTIALS_NEW, String.class)
);
  • 在数据库中查询用户的有效性等。
Schema.get(
                new ExtMap().mput(Schema.InvokeKeys.ENTITY, Schema.Entities.USER)
                .mput(Schema.InvokeKeys.DATA_SOURCE, ds)
                .mput(Schema.InvokeKeys.SETTINGS_RESULT, settings)
                .mput(
                    Schema.InvokeKeys.ENTITY_KEYS,
                    new ExtMap().mput(
                        Schema.UserIdentifiers.USERNAME,
                        subject
                    )
                )
            ).get(
                Schema.InvokeKeys.USER_RESULT,
                Schema.User.class
            );
if (input.get(InvokeKeys.ENTITY, ExtUUID.class).equals(Entities.USER)) {
            ret.mput(
                InvokeKeys.USER_RESULT,
                new Sql.Query(
                    Formatter.format(
                        GET_USER,
                        generateWhere(input.get(InvokeKeys.ENTITY_KEYS, ExtMap.class))
                    )
                ).asResults(
                    ds,
                    USER_RESOLVER,
                    input.get(InvokeKeys.SETTINGS_RESULT, ExtMap.class)
                )
            );
  • 数据库的连接配置在 aaa-jdbc 提供的配置文件中进行了指定。
config.datasource.file = /etc/ovirt-engine/aaa/internal.properties
[root@rhvm extensions.d]# cat /etc/ovirt-engine/aaa/internal.properties
config.datasource.jdbcurl=jdbc:postgresql://localhost:5432/engine?sslfactory=org.postgresql.ssl.NonValidatingFactory
config.datasource.dbuser=engine
config.datasource.dbpassword=Au1qXqSMx3nDRxCQD94RVq
config.datasource.jdbcdriver=org.postgresql.Driver
config.datasource.schemaname=aaa_jdbc
  • 扩展的本地用户域支持创建了新的表空间 aaa_jdbc
    • 其中 users 表为用户表,保存了用户名、密码等信息。
    • settings 为扩展属性表,是该扩展功能额外增加的本地用户属性。
  • settings 表的内容在实例化 Schema 类时,进行了查询加载。
public static class Settings {
        /**
         * Authentication related
         */
        public static final ExtKey PASSWORD_HISTORY_LIMIT = new ExtKey("", Integer.class, "e843bc2a-0878-4b6f-9be3-32e83169fb7c");
        public static final ExtKey LOCK_MINUTES = new ExtKey("", Integer.class, "78b5138a-d52b-464d-a2a7-5fed55bdf7b3");
        public static final ExtKey PRESENT_WELCOME_MESSAGE = new ExtKey("", Boolean.class, "0ae5affd-15e5-4bb1-9910-f091b64b7197");
        public static final ExtKey MESSAGE_SEPARATOR = new ExtKey("", String.class, "ecf6d62a-10f8-4fad-b401-75c9d0788955");
        public static final ExtKey MESSAGE_OF_THE_DAY = new ExtKey("", String.class, "df496823-6814-4720-a302-c723f629f847");
        public static final ExtKey PASSWORD_EXPIRATION_DAYS = new ExtKey("", Integer.class, "dc3e2fb4-cbcc-4f5c-9b06-5db9ec534aa8");
......
private static class SettingsResolver implements Sql.ResultsResolver<ExtMap> {
        @Override
        public ExtMap resolve(ResultSet rs, ExtMap ctx) throws SQLException {
            ExtMap settings = new ExtMap();
            ExtMap descriptions = new ExtMap();
            UUID uuid;
            ExtKey key = null;
            String value = null;
            try {
                while (rs.next()) {
                    uuid = UUID.fromString(rs.getString("uuid"));
                    key = SETTING_KEYS.get(uuid);
                    value = rs.getString("value");
                    if (key != null) {
                        settings.put(
                            new ExtKey(rs.getString("name"), key.getType(), key.getUuid().getUuid().toString()),
                            key.getType().getConstructor(java.lang.String.class).newInstance(value)
                        );
                        descriptions.put(
                            new ExtKey(rs.getString("name"), String.class, key.getUuid().getUuid().toString()),
                            rs.getString("description")
                        );
                    } else {
                        throw new RuntimeException("key for " + uuid + " not found");
                    }
                }
            } catch ( NoSuchMethodException|InvocationTargetException|InstantiationException|IllegalAccessException e) {
                throw new RuntimeException(
                    Formatter.format(
                        "Could not convert setting to expected type. value: {} requested type: {}",
                        value,
                        key.getType()
                    ),
                    e
                );
            }
            return settings.mput(Settings.SETTING_DESCRIPTIONS, descriptions);
        }
}

3. 外部用户域

  • 与本地用户域使用方式类似,安装 ovirt-engine-extension-aaa-ldap,会创建新的 aaa-jdbc 配置文件。
    • AuthzExtension 类的代码,在 ovirt-engine-extension-aaa-ldap 的源码包中可以找到。
yum install ovirt-engine-extension-aaa-ldap
[root@rhvm extensions.d]# cat ad-authz.properties
ovirt.engine.extension.name = ad-authz
ovirt.engine.extension.bindings.method = jbossmodule
ovirt.engine.extension.binding.jbossmodule.module =
org.ovirt.engine-extensions.aaa.ldap
ovirt.engine.extension.binding.jbossmodule.class =
org.ovirt.engineextensions.aaa.ldap.AuthzExtension
ovirt.engine.extension.provides =
org.ovirt.engine.api.extensions.aaa.Authz
config.profile.file.1 = /etc/ovirt-engine/aaa/ad.properties
  • LDAP 配置文件内容
# Select one
#
include = <openldap.properties>
#include = <389ds.properties>
#include = <rhds.properties>
#include = <ipa.properties>
#include = <iplanet.properties>
#include = <rfc2307-389ds.properties>
#include = <rfc2307-rhds.properties>
#include = <rfc2307-openldap.properties>
#include = <rfc2307-edir.properties>
#include = <rfc2307-generic.properties>
# Server
Red Hat Virtualization 4.2 Administration Guide
236
#
vars.server = ldap1.company.com
# Search user and its password.
#
vars.user = uid=search,cn=users,cn=accounts,dc=company,dc=com
vars.password = 123456
pool.default.serverset.single.server = ${global:vars.server}
pool.default.auth.simple.bindDN = ${global:vars.user}
pool.default.auth.simple.password = ${global:vars.password}
  • 若要使用 TLS 或 SSL 协议与 LDAP 服务器进行交互,需要获取 LDAP 服务器的根 CA 证书并使用它创建公共密钥存储文件。
    • 在配置文件中指定公共密钥存储文件的完整路径和访问文件的密码。
# Create keystore, import certificate chain and uncomment
# if using tls.
pool.default.ssl.startTLS = true
pool.default.ssl.truststore.file = /full/path/to/myrootca.jks
pool.default.ssl.truststore.password = password
ovirt
Web note ad 1