1

在部署在 JBoss Fuse 6.1.0-379 中的 Blueprint 应用程序中,我想保护用于创建数据库连接的密码。我阅读了这篇文章并添加<enc:property-placeholder>到蓝图配置中。然而,我的蓝图配置有许多属性占位符,而且 Jasypt 占位符解析器似乎正在尝试解密我在 Camel 上下文中定义的所有占位符。当蓝图上下文启动时,我得到以下异常:

11:59:51,233 | ERROR | t-379-dmz/deploy | BlueprintCamelContext            | 151 - org.apache.camel.camel-blueprint - 2.12.0.redhat-610379 | Error occurred during starting Camel: CamelContext(camel-5) due Failed to create route route7: Route(route7)[[From[{{uri}}]] -> [Log[logging]]] because of Failed to resolve endpoint: {{uri}} due to: org.jasypt.exceptions.EncryptionOperationNotPossibleException
org.apache.camel.FailedToCreateRouteException: Failed to create route route7: Route(route7)[[From[{{uri}}]] -> [Log[logging]]] because of Failed to resolve endpoint: {{uri}} due to: org.jasypt.exceptions.EncryptionOperationNotPossibleException
    at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:182)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:778)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:1955)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:1705)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:1579)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:1547)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.blueprint.BlueprintCamelContext.start(BlueprintCamelContext.java:177)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
    at org.apache.camel.blueprint.BlueprintCamelContext.maybeStart(BlueprintCamelContext.java:209)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
    at org.apache.camel.blueprint.BlueprintCamelContext.serviceChanged(BlueprintCamelContext.java:147)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
    at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:934)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:795)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:544)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4666)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.Felix.registerService(Felix.java:3674)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:347)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.aries.blueprint.container.BlueprintContainerImpl.registerService(BlueprintContainerImpl.java:448)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
    at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:383)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
    at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:261)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
    at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:270)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
    at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:233)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
    at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)[11:org.apache.aries.util:1.0.1.redhat-610379]
    at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)[11:org.apache.aries.util:1.0.1.redhat-610379]
    at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)[11:org.apache.aries.util:1.0.1.redhat-610379]
    at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)[11:org.apache.aries.util:1.0.1.redhat-610379]
    at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)[11:org.apache.aries.util:1.0.1.redhat-610379]
    at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1103)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:696)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:484)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4650)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.Felix$4.run(Felix.java:2123)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.Felix.runInContext(Felix.java:2147)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.Felix.startBundle(Felix.java:2121)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1247)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1219)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startAllBundles(DirectoryWatcher.java:1208)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:503)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:291)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: {{uri}} due to: org.jasypt.exceptions.EncryptionOperationNotPossibleException
    at org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:480)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.util.CamelContextHelper.getMandatoryEndpoint(CamelContextHelper.java:71)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.model.RouteDefinition.resolveEndpoint(RouteDefinition.java:192)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:106)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:112)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.model.FromDefinition.resolveEndpoint(FromDefinition.java:72)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultRouteContext.getEndpoint(DefaultRouteContext.java:88)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:890)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:177)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    ... 38 more
Caused by: org.apache.camel.RuntimeCamelException: org.jasypt.exceptions.EncryptionOperationNotPossibleException
    at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1363)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1005)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.blueprint.BlueprintPropertiesParser.parseProperty(BlueprintPropertiesParser.java:137)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
    at org.apache.camel.component.properties.DefaultPropertiesParser.createPlaceholderPart(DefaultPropertiesParser.java:201)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.component.properties.DefaultPropertiesParser.doParseUri(DefaultPropertiesParser.java:105)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.component.properties.DefaultPropertiesParser.parseUri(DefaultPropertiesParser.java:51)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:160)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:119)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultCamelContext.resolvePropertyPlaceholders(DefaultCamelContext.java:1155)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    at org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:478)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    ... 46 more
Caused by: org.jasypt.exceptions.EncryptionOperationNotPossibleException
    at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:918)
    at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:725)
    at org.apache.karaf.jaas.jasypt.handler.EncryptablePropertyPlaceholder.getProperty(EncryptablePropertyPlaceholder.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_25]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_25]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_25]
    at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_25]
    at org.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1001)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
    ... 54 more

我创建了一个带有蓝图上下文的测试包,它只包含在 Camel 上下文中定义的一个占位符属性,而没有使用加密的 ENC() 占位符语法。我刚刚添加<enc:property-placeholder>,捆绑包未能以相同的异常 ( org.jasypt.exceptions.EncryptionOperationNotPossibleException) 开始。

这是期望的行为吗?

我的蓝图配置:

<?xml version="1.0" encoding="UTF-8"?> 
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
           xmlns:enc="http://karaf.apache.org/xmlns/jasypt/v1.0.0"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">


    <cm:property-placeholder persistent-id="encrypt.config" update-strategy="reload" >
        <cm:default-properties>
            <cm:property name="uri" value="timer://foo?fixedRate=true&amp;period=6000"/>
        </cm:default-properties>
    </cm:property-placeholder>

    <enc:property-placeholder>
        <enc:encryptor class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
            <property name="config">
                <bean class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
                    <property name="algorithm" value="PBEWithMD5AndDES" />
                    <property name="password" value="password" />
                </bean>
            </property>
        </enc:encryptor>
    </enc:property-placeholder>

     <camelContext xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns="http://camel.apache.org/schema/blueprint"
                  xsi:schemaLocation="http://camel.apache.org/schema/blueprint">
        <route>
            <from uri="{{uri}}"/>
            <log message="logging" loggingLevel="INFO" id="logBeforeService"></log>
        </route>
     </camelContext>

</blueprint>
4

1 回答 1

0

编辑:来自 RedHat 支持的回应

所以这是一个已知问题,并且有几个 Jira 问题(此处此处),并且似乎该问题已在较新版本的 Camel 中得到解决。我已经用名为 jboss-fuse-6.1.0.redhat-379-r1p3 的补丁提供的 2.12.0.redhat-611412 版本进行了测试,并且不再抛出异常。

不管我之前说过什么,我对这个实现非常满意。如果它无法解密实际加密的值,我希望抛出异常,而这正是发生的情况。我将加密值修改为 ENC(invalid_and_should_throw_exception),并且抛出了一个异常,就像我期望的那样。

Caused by: org.jasypt.exceptions.EncryptionOperationNotPossibleException

编辑:更简洁的答案

在解析属性占位符值的方式方面,Camel-Blueprint 的行为与 Camel-Core 不同。Camel-Core 要求开发人员为骆驼属性语法 [1] 定义一个骆驼属性占位符解析器,它解析骆驼上下文中的属性。显然,这背后的原因是为了避免 spring 属性语法 [2] 和 Camel 简单表达式语言语法 [3] 之间的冲突。开发人员可以选择通过添加额外配置来连接 Spring Property Placeholder Resolver 和 Camel。

[1 - Camel 属性语法]

{{org.my.prop}}

[2 - Spring 属性语法]

${org.my.prop}

[3 - 简单表达式语言语法]

${exchange.body}

在 Camel-Blueprint 中,蓝图属性占位符解析器和 Camel 上下文之间的桥接是自动发生的。创建 Blueprint Camel Context 时,会将 Blueprint Bundle Context 注入其中。使用 Blueprint Bundle Context,Camel 将所有 bean 从中提取出来,并确定它们是否可分配给 Apache Aries 实现 AbstractPropertyPlaceholder。对于您定义的属性占位符解析器的每个实例,Camel 能够调用它们的 resolveProperty 方法,而无需解析每个解析器定义的属性语法。

因为 Jasypt 属性占位符解析器需要占位符语法 [4],所以它只是忽略与此语法匹配的所有内容。因为 Camel-Blueprint 绕过了确保属性语法的验证,所以我们最终会遇到这样一个场景:Camel 告诉 Jasypt 占位符解析器解密我们尝试在 Camel 上下文中使用的每个属性。这当然会引发异常,因为您正在尝试解密尚未加密的属性。

[4 - Jasypt 蓝图属性语法]

ENC(encrypted.value)

解决方案:

  1. 创建一个实现 Jasypt StringEncryptor 并将 StandardPBEStringEncryptor 作为属性保存的类。实现的加密和解密方法调用 StandardPBEStringEncryptor 的加密和解密方法,但捕获任何抛出的异常。

    • 这是我在原始答案中给出的解决方案。
    • 如果无法解密不应忽略的加密值,这很危险。捆绑包不应启动,以防止例如您的数据库帐户被锁定。
  2. 在将值传递给占位符解析器之前手动解密值。

    • 您可以创建一个配置服务,在其中编译来自各种来源的所有配置,手动解密所有加密值,然后将属性公开为 OSGi 服务,以便跨包共享。
    • 我已经放弃了这个设计,它基本上是重新实现了由 Karaf 本地提供的 ConfigurationAdmin 服务(增加了 Karaf 不提供的解密),它只是不如 Karaf 提供的那么好,因为它不是能够检测应用程序配置何时更改。
  3. 在运行时解密值。
    • 也不喜欢这个,要求你的应用程序知道哪些应用程序属性应该被加密。

我通过我们的支持合同向 Redhat 提出了支持请求,如果有任何问题,我会及时通知您。

原答案:

我想我想通了这一点。根据骆驼文档,在蓝图中骆驼能够检测到存在蓝图占位符解析器,并尝试使用它来解析其属性。

这样做的问题是它不关心占位符前缀和后缀是什么,它只是继续使用它而不顾一切。Jasypt 占位符解析器已被设计为仅在占位符前缀为“ENC(”且后缀为“)”时才被调用,记住 Camel 并不关心这一点。Camel 将其未解析的属性传递给 Jasypt 属性解析器,后者当然会尝试解密它们。因为它们没有加密,所以会引发异常。

为了解决这个问题,我创建了一个自定义加密器,它实现了 Jasypt StringEncryptor。自定义加密器包含 StandardPBEStingEncryptor 的一个实例,并使用它来执行实际的加密/解密。关键区别在于异常被捕获和忽略,因此如果在尝试解密未加密的骆驼属性时抛出异常,那么它会被忽略并且应用程序会继续正常运行。

Java 类:

package uk.co.test;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomEncryptor implements StringEncryptor {

    private StandardPBEStringEncryptor encryptor;
    private static final Logger LOG = LoggerFactory.getLogger(CustomEncryptor.class);

    public CustomEncryptor(String password) {
        encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(password);
    }

    @Override
    public String decrypt(String value) {

        String ret = null;

        try {
            ret = encryptor.decrypt(value);
        } catch (Exception e) {
            LOG.error("Failed to decrypt value.");
        }

        return ret;
    }

    @Override
    public String encrypt(String value) {

        String ret = null;

        try {
            ret = encryptor.encrypt(value);
        } catch (Exception e) {
            LOG.error("Failed to encrypt value.");
        }

        return ret;
    }

    public StandardPBEStringEncryptor getEncryptor() {
        return encryptor;
    }

    public void setEncryptor(StandardPBEStringEncryptor encryptor) {
        this.encryptor = encryptor;
    }

}

蓝图配置:

<enc:property-placeholder>
    <enc:encryptor class="uk.co.test.CustomEncryptor">
        <argument value="myPass" />
    </enc:encryptor>
</enc:property-placeholder>
于 2015-06-11T15:01:03.490 回答