如何使用 WildFly 连接到受 Kerberos 保护的 Apache Phoenix 数据源?
How to connect to a Kerberos-secured Apache Phoenix data source with WildFly?
我最近花了几周时间试图让 WildFly 成功连接到 Kerberized Apache Phoenix 数据源。关于如何做到这一点的文档数量惊人地有限,但既然我已经破解了它,我正在分享。
环境:
- 野蝇9+。等效的 JBoss 版本也应该可以工作(但未经测试)。 WildFly 8 不包含所需的
org.jboss.security.negotiation.KerberosLoginModule
class(但您可以破解它,请参阅 Kerberos sql server datasource in Wildfly 8.2)。我使用的是 WildFly 10.1。0.Final,并使用了独立部署。
- 阿帕奇凤凰 4.2.0.2.2.4.10。我没有测试任何其他版本。
- Kerberos v5。我的 KDC 是 运行 在 Windows Active Directory 上,但这应该不会造成明显的差异。
- 我的Hadoop环境是HortonWorks版本,由Ambari维护。 Ambari 确保所有配置文件和 Kerberos 实现设置都是正确的。
首先,您需要将系统 属性 添加到 WildFly 的 standalone.xml
以指定 Kerberos 配置文件的位置:
...
</extensions>
<system-properties>
<property name="java.security.krb5.conf" value="/path/to/krb5.conf"/>
</system-properties>
...
我不打算在这里讨论 krb5.conf
文件的格式,因为它取决于您自己的 Kerberos 实现。重要的是它包含 KDC 的默认领域和网络位置。在 Linux 上,您通常可以在 /etc/krb5.conf
或 /etc/security/krb5.conf
上找到它。如果您在 Windows 上使用 运行 WildFly,请确保在您的路径中使用正斜杠,例如"C:/Source/krb5.conf"
其次,向 standalone.xml
添加两个新的安全域 - 一个名为 "Client",供 ZooKeeper 使用,另一个名为 "host",供 WildFly 使用。不要问我为什么(它让我很痛苦)但是 "Client" 安全域的名称 必须 与定义在服务器上 Zookeeper 的 JAAS 客户端配置文件。如果您使用 Ambari 进行设置,"Client" 是默认名称。另外注意不能简单的提供一个jaas.config
文件作为系统属性,必须在这里定义:
<security-domain name="Client" cache-type="default">
<login-module code="com.sun.security.auth.module.Krb5LoginModule" flag="required">
<module-option name="useTicketCache" value="true"/>
<module-option name="debug" value="true"/>
</login-module>
</security-domain>
<security-domain name="host" cache-type="default">
<login-module code="org.jboss.security.negotiation.KerberosLoginModule" flag="required" module="org.jboss.security.negotiation">
<module-option name="useTicketCache" value="true"/>
<module-option name="debug" value="true"/>
<module-option name="refreshKrb5Config" value="true"/>
<module-option name="addGSSCredential" value="true"/>
</login-module>
</security-domain>
模块选项会因您的实施而异。我从默认的 Java 票证缓存中获取我的票证,它在 JRE 的 java.security
文件中定义,但如果需要,您可以在此处提供密钥表。请注意,将 storeKey
设置为 true
破坏了我的实现。查看 Java 文档以了解所有选项。请注意,每个安全域使用不同的登录模块:这并非偶然 - Phoenix 不知道如何使用 org.jboss...
版本。
现在您需要在 phoenix-<version>-client.jar
中为 WildFly 提供 org.apache.phoenix.jdbc.PhoenixDriver
class。在WildFly目录下创建如下目录树:
/modules/system/layers/base/org/apache/phoenix/main/
在 main
目录中,粘贴您可以在服务器上找到的 phoenix--client.jar(例如 /usr/hdp/<version>/phoenix/client/bin
)并创建一个 module.xml
文件:
<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.1" name="org.apache.phoenix">
<resources>
<resource-root path="phoenix-<version>-client.jar">
<filter>
<exclude-set>
<path name="javax" />
<path name="org/xml" />
<path name="org/w3c/dom" />
<path name="org/w3c/sax" />
<path name="javax/xml/parsers" />
<path name="com/sun/org/apache/xerces/internal/jaxp" />
<path name="org/apache/xerces/jaxp" />
<path name="com/sun/jersey/core/impl/provider/xml" />
</exclude-set>
</filter>
</resource-root>
<resource-root path=".">
</resource-root>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="sun.jdk"/>
<module name="org.apache.log4j"/>
<module name="javax.transaction.api"/>
<module name="org.apache.commons.logging"/>
</dependencies>
</module>
您还需要将服务器上的 hbase-site.xml
和 core-site.xml
粘贴到 main
目录中。它们通常位于 /usr/hdp/<version>/hbase/conf
和 /usr/hdp/<version>/hadoop/conf
中。如果你不添加这些,你会得到很多无用的 ZooKeeper getMaster
错误!如果你想让驱动登录到与WildFly相同的地方,那么你还应该在main
目录下创建一个log4j.xml
文件。您可以在网络上的其他地方找到示例。当 WildFly 部署时,<resource-root path="."></resource-root>
元素将那些 xml 文件添加到 class 路径。
最后,在 <subsystem xmlns="urn:jboss:domain:datasources:2.0">
部分添加一个新的数据源和驱动程序。您可以使用 CLI 或直接编辑 standalone.xml
来完成此操作,我是后者:
<datasource jndi-name="java:jboss/datasources/PhoenixDS" pool-name="PhoenixDS" enabled="true" use-java-context="true">
<connection-url>jdbc:phoenix:first.quorumserver.fqdn,second.quorumserver.fqdn:2181/hbase-secure</connection-url>
<connection-property name="phoenix.connection.autoCommit">true</connection-property>
<driver>phoenix</driver>
<validation>
<check-valid-connection-sql>SELECT 1 FROM SYSTEM.CATALOG LIMIT 1</check-valid-connection-sql>
</validation>
<security>
<security-domain>host</security-domain>
</security>
</datasource>
<drivers>
<driver name="phoenix" module="org.apache.phoenix">
<xa-datasource-class>org.apache.phoenix.jdbc.PhoenixDriver</xa-datasource-class>
</driver>
</drivers>
请务必将 first.quorumserver.fqdn,second.quorumserver.fqdn
替换为适合您环境的正确 ZooKeeper 仲裁字符串。您可以在 HBase 配置目录的 hbase-site.xml
中找到它:hbase.zookeeper.quorum
。 您不需要将 Kerberos 信息添加到连接 URL 字符串!
tl;dr
- 确保
hbase-site.xml
和 core-site.xml
在您的 class 路径中。
- 确保你有一个
<security-domain>
,其名称是 ZooKeeper 期望的(可能是 "Client"),它使用 com.sun.security.auth.module.Krb5LoginModule
.
- Phoenix 连接URL必须包含整个 ZooKeeper 仲裁。你不能错过一台服务器!确保它与
hbase-site.xml
. 中的值匹配
参考文献:
我最近花了几周时间试图让 WildFly 成功连接到 Kerberized Apache Phoenix 数据源。关于如何做到这一点的文档数量惊人地有限,但既然我已经破解了它,我正在分享。
环境:
- 野蝇9+。等效的 JBoss 版本也应该可以工作(但未经测试)。 WildFly 8 不包含所需的
org.jboss.security.negotiation.KerberosLoginModule
class(但您可以破解它,请参阅 Kerberos sql server datasource in Wildfly 8.2)。我使用的是 WildFly 10.1。0.Final,并使用了独立部署。 - 阿帕奇凤凰 4.2.0.2.2.4.10。我没有测试任何其他版本。
- Kerberos v5。我的 KDC 是 运行 在 Windows Active Directory 上,但这应该不会造成明显的差异。
- 我的Hadoop环境是HortonWorks版本,由Ambari维护。 Ambari 确保所有配置文件和 Kerberos 实现设置都是正确的。
首先,您需要将系统 属性 添加到 WildFly 的 standalone.xml
以指定 Kerberos 配置文件的位置:
...
</extensions>
<system-properties>
<property name="java.security.krb5.conf" value="/path/to/krb5.conf"/>
</system-properties>
...
我不打算在这里讨论 krb5.conf
文件的格式,因为它取决于您自己的 Kerberos 实现。重要的是它包含 KDC 的默认领域和网络位置。在 Linux 上,您通常可以在 /etc/krb5.conf
或 /etc/security/krb5.conf
上找到它。如果您在 Windows 上使用 运行 WildFly,请确保在您的路径中使用正斜杠,例如"C:/Source/krb5.conf"
其次,向 standalone.xml
添加两个新的安全域 - 一个名为 "Client",供 ZooKeeper 使用,另一个名为 "host",供 WildFly 使用。不要问我为什么(它让我很痛苦)但是 "Client" 安全域的名称 必须 与定义在服务器上 Zookeeper 的 JAAS 客户端配置文件。如果您使用 Ambari 进行设置,"Client" 是默认名称。另外注意不能简单的提供一个jaas.config
文件作为系统属性,必须在这里定义:
<security-domain name="Client" cache-type="default">
<login-module code="com.sun.security.auth.module.Krb5LoginModule" flag="required">
<module-option name="useTicketCache" value="true"/>
<module-option name="debug" value="true"/>
</login-module>
</security-domain>
<security-domain name="host" cache-type="default">
<login-module code="org.jboss.security.negotiation.KerberosLoginModule" flag="required" module="org.jboss.security.negotiation">
<module-option name="useTicketCache" value="true"/>
<module-option name="debug" value="true"/>
<module-option name="refreshKrb5Config" value="true"/>
<module-option name="addGSSCredential" value="true"/>
</login-module>
</security-domain>
模块选项会因您的实施而异。我从默认的 Java 票证缓存中获取我的票证,它在 JRE 的 java.security
文件中定义,但如果需要,您可以在此处提供密钥表。请注意,将 storeKey
设置为 true
破坏了我的实现。查看 Java 文档以了解所有选项。请注意,每个安全域使用不同的登录模块:这并非偶然 - Phoenix 不知道如何使用 org.jboss...
版本。
现在您需要在 phoenix-<version>-client.jar
中为 WildFly 提供 org.apache.phoenix.jdbc.PhoenixDriver
class。在WildFly目录下创建如下目录树:
/modules/system/layers/base/org/apache/phoenix/main/
在 main
目录中,粘贴您可以在服务器上找到的 phoenix--client.jar(例如 /usr/hdp/<version>/phoenix/client/bin
)并创建一个 module.xml
文件:
<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.1" name="org.apache.phoenix">
<resources>
<resource-root path="phoenix-<version>-client.jar">
<filter>
<exclude-set>
<path name="javax" />
<path name="org/xml" />
<path name="org/w3c/dom" />
<path name="org/w3c/sax" />
<path name="javax/xml/parsers" />
<path name="com/sun/org/apache/xerces/internal/jaxp" />
<path name="org/apache/xerces/jaxp" />
<path name="com/sun/jersey/core/impl/provider/xml" />
</exclude-set>
</filter>
</resource-root>
<resource-root path=".">
</resource-root>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="sun.jdk"/>
<module name="org.apache.log4j"/>
<module name="javax.transaction.api"/>
<module name="org.apache.commons.logging"/>
</dependencies>
</module>
您还需要将服务器上的 hbase-site.xml
和 core-site.xml
粘贴到 main
目录中。它们通常位于 /usr/hdp/<version>/hbase/conf
和 /usr/hdp/<version>/hadoop/conf
中。如果你不添加这些,你会得到很多无用的 ZooKeeper getMaster
错误!如果你想让驱动登录到与WildFly相同的地方,那么你还应该在main
目录下创建一个log4j.xml
文件。您可以在网络上的其他地方找到示例。当 WildFly 部署时,<resource-root path="."></resource-root>
元素将那些 xml 文件添加到 class 路径。
最后,在 <subsystem xmlns="urn:jboss:domain:datasources:2.0">
部分添加一个新的数据源和驱动程序。您可以使用 CLI 或直接编辑 standalone.xml
来完成此操作,我是后者:
<datasource jndi-name="java:jboss/datasources/PhoenixDS" pool-name="PhoenixDS" enabled="true" use-java-context="true">
<connection-url>jdbc:phoenix:first.quorumserver.fqdn,second.quorumserver.fqdn:2181/hbase-secure</connection-url>
<connection-property name="phoenix.connection.autoCommit">true</connection-property>
<driver>phoenix</driver>
<validation>
<check-valid-connection-sql>SELECT 1 FROM SYSTEM.CATALOG LIMIT 1</check-valid-connection-sql>
</validation>
<security>
<security-domain>host</security-domain>
</security>
</datasource>
<drivers>
<driver name="phoenix" module="org.apache.phoenix">
<xa-datasource-class>org.apache.phoenix.jdbc.PhoenixDriver</xa-datasource-class>
</driver>
</drivers>
请务必将 first.quorumserver.fqdn,second.quorumserver.fqdn
替换为适合您环境的正确 ZooKeeper 仲裁字符串。您可以在 HBase 配置目录的 hbase-site.xml
中找到它:hbase.zookeeper.quorum
。 您不需要将 Kerberos 信息添加到连接 URL 字符串!
tl;dr
- 确保
hbase-site.xml
和core-site.xml
在您的 class 路径中。 - 确保你有一个
<security-domain>
,其名称是 ZooKeeper 期望的(可能是 "Client"),它使用com.sun.security.auth.module.Krb5LoginModule
. - Phoenix 连接URL必须包含整个 ZooKeeper 仲裁。你不能错过一台服务器!确保它与
hbase-site.xml
. 中的值匹配
参考文献: