默认情况下,Apache ActiveMQ Artemis 服务器配置文件中的所有密码都以明文形式存在。这通常不会造成安全问题,因为这些文件应该受到很好的保护,防止未经授权的访问。但是,在某些情况下,用户不希望将其密码暴露给不必要的人员。
Apache ActiveMQ Artemis 可以配置为在其配置文件中使用“掩码”密码。掩码密码是真实密码的模糊字符串表示。为了掩码密码,用户将使用“编解码器”。编解码器接收真实密码并输出掩码版本。然后,用户可以用新的掩码密码替换配置文件中的真实密码。当 Apache ActiveMQ Artemis 加载掩码密码时,它使用编解码器将其解码回真实密码。
Apache ActiveMQ Artemis 提供了一个默认编解码器。用户可以选择使用或实现自己的编解码器来掩码密码。
一般来说,可以使用两种方法之一来识别掩码密码。第一种是ENC()
语法,即任何包含在ENC()
中的字符串值都将被视为掩码密码。例如
ENC(xyz)
以上表示密码已掩码,掩码值为xyz
。
ENC()
语法是掩码密码的**首选方法**,并且在 Artemis 的每个密码配置中都得到普遍支持。
另一种传统方法是使用mask-password
属性来指示配置文件中的密码应被视为“掩码”。例如
<mask-password>true</mask-password>
<cluster-password>xyz</cluster-password>
这种方法现在已**弃用**,仅为了保持向后兼容性而存在。较新的配置可能不支持它。
1. 生成掩码密码
要掩码密码,请使用 Artemis *实例* 的bin
目录中的mask
命令。此命令不会从 Artemis 主目录工作。
默认情况下,mask
命令使用默认编解码器的传统双向算法,除非在broker.xml
中定义了自定义编解码器,并且--password-codec
选项为true
。传统的双向
算法现在已**弃用**,仅为了保持向后兼容性而存在,请改用自定义编解码器。以下是一个简单的示例
./artemis mask <plaintextPassword>
您将得到类似以下内容
result: 32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360
只需复制32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360
,并使用ENC()
语法用它替换您的明文密码,例如ENC(32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360)
。
您还可以将--key
参数与默认编解码器一起使用。阅读有关默认编解码器的更多信息,以了解有关此参数的更多详细信息。
此过程适用于以下密码
-
broker.xml
-
login.config
-
bootstrap.xml
-
management.xml
此过程**不**适用于以下密码
-
artemis-users.properties
可以使用mask
命令使用--hash
命令行选项为artemis-users.properties
生成掩码密码。但是,也可以使用下面描述的user
命令提供的工具集来完成此操作。
2. 掩码配置
除了支持ENC()
语法之外,服务器配置文件(即 broker.xml)还具有一个属性,该属性定义了整个文件范围内的默认掩码行为。
mask-password
:此布尔类型属性指示是否应掩码密码。如果要掩码密码,请将其设置为true
。默认值为false
。如上所述,此配置参数已被ENC()
语法弃用。
password-codec
:此字符串类型属性标识将用于在代理中解码掩码密码的类的名称。如果未指定,则将使用默认的org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec
。阅读有关使用自定义编解码器的更多信息。
2.1. artemis-users.properties
Apache ActiveMQ Artemis 的默认 JAAS 安全管理器使用纯属性文件,其中用户密码默认情况下以散列形式指定。注意,在这种情况下,密码实际上是散列而不是掩码。默认的PropertiesLoginModule
不会解码artemis-users.properties
中的密码,而是会散列输入并比较两个散列值以进行密码验证。
从要添加用户/密码的 Artemis *实例* 的 CLI 使用以下命令。此命令不会从用于创建实例的 Artemis 主目录工作,并且只有在代理启动后才会生效。例如
./artemis user add --user-command-user guest --user-command-password guest --role admin
这将使用默认编解码器对密码执行单向
散列,并使用指定的参数更改artemis-users.properties
和artemis-roles.properties
文件。
artemis-users.properties
中的密码会通过查找ENC(<hash>)
语法自动检测为散列或非散列。mask-password
参数不需要为true
才能在此处使用散列密码。
仅当使用 一般来说,除了非常基本的用例之外,不建议使用属性文件和代理中心的用户信息管理。代理旨在处理消息。它不负责管理用户,尽管为了方便起见提供了有限级别的功能。建议在企业级生产用例中使用 LDAP。 |
2.2. cluster-password
如果在ENC()
语法中指定,它将被视为掩码,或者如果mask-password
为true
,则cluster-password
将被视为掩码。
2.3. 连接器和接受器
在 broker.xml 中,connector
和acceptor
配置有时需要指定密码。例如,如果用户要使用sslEnabled=true
的acceptor
,则可以指定keyStorePassword
和trustStorePassword
。由于接受器和连接器是可插入的实现,因此每种传输将具有不同的密码掩码需求。
首选方法是简单地使用ENC()
语法。
如果使用传统的mask-password
和password-codec
值,则当初始化connector
或acceptor
时,Apache ActiveMQ Artemis 将使用键activemq.usemaskedpassword
和activemq.passwordcodec
分别将这些值添加到参数中。Netty 和 InVM 实现将根据需要使用这些值,而任何其他实现都可以访问这些值以供需要时使用。
2.4. 核心桥接
核心桥接在服务器配置文件中配置,因此其password
属性的掩码遵循与cluster-password
相同的规则。它支持ENC()
语法。
对于使用mask-password
属性,下表总结了上述属性之间的关系
mask-password | cluster-password | 接受器/连接器密码 | 桥接密码 |
---|---|---|---|
不存在 |
纯文本 |
纯文本 |
纯文本 |
false |
纯文本 |
纯文本 |
纯文本 |
true |
掩码 |
掩码 |
掩码 |
建议您在新的应用程序/部署中使用ENC()
语法。
2.4.1. 示例
在以下示例中,如果相关属性或属性不存在,则意味着它们未在配置文件中指定。 |
-
未掩码
<cluster-password>bbc</cluster-password>
这表示集群密码是纯文本值
bbc
。 -
掩码 1
<cluster-password>ENC(80cf731af62c290)</cluster-password>
这表示集群密码是掩码值
80cf731af62c290
。 -
掩码 2
<mask-password>true</mask-password> <cluster-password>80cf731af62c290</cluster-password>
这表示集群密码是掩码值,Apache ActiveMQ Artemis 将使用默认编解码器来解码它。配置文件、连接器、接受器和桥接中的所有其他密码也将使用掩码密码。
2.5. bootstrap.xml
代理嵌入一个 Web 服务器,用于托管某些 Web 应用程序,例如管理控制台。它在bootstrap.xml
中作为 Web 组件配置。可以使用https
协议来保护 Web 服务器,并且可以使用密钥库密码和/或信任库密码来配置它,这些密码默认情况下以明文形式指定。
要掩码这些密码,您需要使用ENC()
语法。这里不支持mask-password
布尔值。
您还可以设置passwordCodec
属性,如果您要使用除默认编解码器之外的其他密码编解码器。例如
<web path="web">
<binding uri="https://127.0.0.1:8443"
keyStorePassword="ENC(-5a2376c61c668aaf)"
trustStorePassword="ENC(3d617352d12839eb71208edf41d66b34)">
<app url="activemq-branding" war="activemq-branding.war"/>
</binding>
</web>
2.6. management.xml
代理嵌入一个 JMX 连接器,用于管理。可以使用 SSL 来保护连接器,并且可以使用密钥库密码和/或信任库密码来配置它,这些密码默认情况下以明文形式指定。
要掩码这些密码,您需要使用ENC()
语法。这里不支持mask-password
布尔值。
您还可以设置password-codec
属性,如果您要使用除默认编解码器之外的其他密码编解码器。例如
<connector
connector-port="1099"
connector-host="localhost"
secured="true"
key-store-path="myKeystore.jks"
key-store-password="ENC(3a34fd21b82bf2a822fa49a8d8fa115d"
trust-store-path="myTruststore.jks"
trust-store-password="ENC(3a34fd21b82bf2a822fa49a8d8fa115d)"/>
使用此配置,ra.xml 中的所有密码及其所有 MDB 都必须以掩码形式存在。
2.7. PropertiesLoginModule
Artemis 支持在 JAAS 配置文件(默认名称为login.config
)中配置 Properties 登录模块。默认情况下,用户的密码以明文形式存在,或者使用默认编解码器进行掩码。
要使用自定义编解码器类,请将org.apache.activemq.jaas.properties.password.codec
属性设置为类名,例如,要使用com.example.MySensitiveDataCodecImpl
编解码器类
PropertiesLoginWithPasswordCodec { org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule required debug=true org.apache.activemq.jaas.properties.user="users.properties" org.apache.activemq.jaas.properties.role="roles.properties" org.apache.activemq.jaas.properties.password.codec="com.example.MySensitiveDataCodecImpl"; };
2.8. LDAPLoginModule
Artemis 支持在 JAAS 配置文件(默认名称为login.config
)中配置 LDAP 登录模块。连接到 LDAP 服务器时,通常需要在配置文件中提供连接密码。默认情况下,此密码以明文形式存在。
要掩码它,您需要使用ENC()
语法在登录模块中配置密码。要使用以下属性指定编解码器
passwordCodec
- 密码编解码器类名。(如果不存在,将使用默认编解码器)
例如
LDAPLoginExternalPasswordCodec { org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required debug=true initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory connectionURL="ldap://127.0.0.1:1024" connectionUsername="uid=admin,ou=system" connectionPassword="ENC(-170b9ef34d79ed12)" passwordCodec="org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;key=helloworld" connectionProtocol=s authentication=simple userBase="ou=system" userSearchMatching="(uid={0})" userSearchSubtree=false roleBase="ou=system" roleName=dummyRoleName roleSearchMatching="(uid={1})" roleSearchSubtree=false ; };
2.9. JCA 资源适配器
ra.xml 和 MDB 激活配置都具有一个password
属性,可以使用ENC()
语法对其进行掩码,这是一种首选方法。
或者,它可以使用 ra.xml 中的一个可选属性来指示密码已掩码
- UseMaskedPassword
-
如果设置为“true”,则密码已掩码。默认值为
false
。
ra.xml
中还有一个属性可以指定编解码器
- PasswordCodec
-
用于解码遮罩密码的编解码器的类名及其参数。如果
UseMaskedPassword
为false
,则忽略此属性。此属性的格式是可选地后跟键/值对的完整限定类名。它与 JMS 桥梁的格式相同。示例
示例 1 使用ENC()
语法
<config-property>
<config-property-name>password</config-property-name>
<config-property-type>String</config-property-type>
<config-property-value>ENC(80cf731af62c290)</config-property-value>
</config-property>
<config-property>
<config-property-name>PasswordCodec</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>com.foo.ACodec;key=helloworld</config-property-value>
</config-property>
示例 2 使用 "UseMaskedPassword" 属性
<config-property>
<config-property-name>UseMaskedPassword</config-property-name>
<config-property-type>boolean</config-property-type>
<config-property-value>true</config-property-value>
</config-property>
<config-property>
<config-property-name>password</config-property-name>
<config-property-type>String</config-property-type>
<config-property-value>80cf731af62c290</config-property-value>
</config-property>
<config-property>
<config-property-name>PasswordCodec</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>com.foo.ACodec;key=helloworld</config-property-value>
</config-property>
3. 选择密码掩码的编解码器
如前几节所述,所有密码掩码都需要一个编解码器。编解码器使用一种算法将掩码密码转换为其原始明文形式,以便在各种安全操作中使用。用于解码的算法必须与用于编码的算法匹配。否则,解码可能无法成功。
为了方便用户,Apache ActiveMQ Artemis 提供了一个默认编解码器。但是,如果用户愿意,他们可以实现自己的编解码器。
3.1. 默认编解码器
如果配置中未指定编解码器,则使用默认编解码器。默认编解码器的类名为org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec
。它提供 2 种算法:one-way
和two-way
。one-way
算法可以对字符串进行哈希运算,是 PropertiesLoginModule 使用的默认算法。two-way
算法可以使用key
对字符串进行编码/解码。two-way
算法在org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec
中有一个默认密钥,但使用默认密钥会让恶意行为者可以使用该密钥来取消掩码密码。它现在已弃用,仅为保持向后兼容性而存在,请改为使用 自定义编解码器。此处使用的key
非常重要,因为在掩码和取消掩码密码时必须使用相同的密钥。它只是编解码器提供给底层算法的一串字符。有几种方法可以提供您自己的密钥
-
使用
key=value
语法在编解码器配置中指定密钥。具体配置会根据您尝试掩码的密码略有不同,但例如,可以在broker.xml
中使用<password-codec>
完成此操作<password-codec>org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;key=myKey</password-codec>
支持密码掩码的任何文件中都可能存在类似的配置,例如
boostrap.xml
、login.config
、management.xml
等。这种方法的主要缺点是密钥将以明文形式存储在配置文件中。 -
设置系统属性 -Dartemis.default.sensitive.string.codec.key=myKey。
-
设置环境属性
ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY
。使用这种方法的优点是,密钥更难找到,因为它不会存在于任何配置文件中。可以在代理启动之前立即设置它,然后在代理完成启动之后立即从环境中清除它。
3.2. 使用自定义编解码器
可以使用自定义编解码器,而不是内置编解码器。只需确保编解码器位于 Apache ActiveMQ Artemis 的类路径中即可。如果编解码器的服务提供程序安装在类路径中,则自定义编解码器也可以通过服务加载,而不是通过类加载。然后,将服务器配置为使用它,如下所示
<password-codec>com.foo.SomeCodec;key1=value1;key2=value2</password-codec>
如果您的编解码器需要向其传递参数,则可以在配置时通过键/值对进行操作。例如,如果您的编解码器需要一个 "key-location" 参数,则可以这样定义
<password-codec>com.foo.NewCodec;key-location=/some/url/to/keyfile</password-codec>
然后,将您的群集密码配置为如下所示
<cluster-password>ENC(masked_password)</cluster-password>
当 Apache ActiveMQ Artemis 读取群集密码时,它将初始化NewCodec
并使用它来解码 "mask_password"。它还使用新定义的编解码器处理所有密码。
3.2.1. 实现自定义编解码器
若要使用与内置编解码器不同的编解码器,您可以从现有库中选择一个或自己实现它。所有编解码器必须实现org.apache.activemq.artemis.utils.SensitiveDataCodec<String>
接口。因此,新编解码器的定义方式如下
public class MyCodec implements SensitiveDataCodec<String> {
@Override
public String decode(Object mask) throws Exception {
// Decode the mask into clear text password.
return "the password";
}
@Override
public String encode(Object secret) throws Exception {
// Mask the clear text password.
return "the masked password";
}
@Override
public void init(Map<String, String> params) {
// Initialization done here. It is called right after the codec has been created.
}
@Override
public boolean verify(char[] value, String encodedValue) {
// Return true if the value matches the encodedValue.
return checkValueMatchesEncoding(value, encodedValue);
}
}
最后但并非最不重要的一点是,获得自己的编解码器后,请 将其添加到类路径中,否则代理将无法加载它!