如何防止使用Spring Boot将危险控制器包含在生产配置文件中?

时间:2018-03-16 23:39:12

标签: java spring spring-boot gradle

TL;博士 如何将类排除在bootJar生成的jar文件中,具体取决于Spring配置文件?

我会故意模糊,但会尽量提供尽可能多的信息。

我有一个C#.NET web api(JSON over HTTP / 1.1)。该api从第三方接收加密的有效载荷。这个第三方有一个为Java编写的库,但不是C#。由于时间限制和其他因素,我们决定使用Spring Boot站起来使用Java API,并调用该API,而不是自己实现它们的库。

流程是

  1. 将加密的有效负载发送到C#API
  2. (C#)将加密的有效负载发送到Java API
  3. (Java)解密加密的有效载荷
  4. (Java)使用第三方库进行数据转换/验证
  5. (Java)重新加密有效负载
  6. (Java)将加密的有效负载返回给C#API
  7. (C#)发送给其他第三方
  8. 我们有一套自动集成测试,目前用C#编写。

    我们需要确保,在给定有效负载的情况下,当它被发送到C#API时,有效负载将被转发到Java API,正确解密,正确转换,并为其他第三方正确地重新加密 - 处理。

    为了促进这一点,我在Java API上创建了一个新的控制器,它接收明文有效负载,加密它(就像第三方那样)并将其返回给调用者。然后,调用者可以发送该加密的有效负载在Java API上执行不同的控制器以执行解密+验证,并将重新加密的有效负载发送回调用者。

    Java API信任这些自动创建的有效负载。 Java API在运行时生成一个新的密钥对,当它收到明文有效负载时,它会使用运行时生成的私钥对其进行签名,并信任使用运行时生成的公钥签名的消息。

    我现在遇到的问题是我不希望这个功能在生产中可用。这些有效负载的内容对于糟糕的演员来说太敏感了。

    我通过向控制器添加@Profile("test")属性解决了部分问题。这允许我在运行时配置它,如

    java -jar sensitive-app.jar --spring.profiles.active=production
    

    这样,在运行时,sp​​ring会阻止控制器工作

    {
        "timestamp": "2018-03-16T23:20:00.781+0000",
        "status": 404,
        "error": "Not Found",
        "message": "No message available",
        "path": "/dangerous-endpoint"
    }
    

    然而,我明白没有什么是不可动摇的。尽可能地,我想确保任何可以访问盒子的不良演员都不会遇到这种情况;或者换句话说,即使攻击者可以访问该框,也可以使用

    启动应用程序
    java -jar sensitive-app.jar --spring.profiles.active=test
    

    控制器仍无效。

    我正在使用spring-boot gradle插件构建这个jar。

    我能想到的唯一方法是首先防止控制器被包含在jar中。

    我尝试将其添加到我的构建脚本

    bootJar {
        exclude('sensitive/dangerous/**')
    }
    

    但是我看到类文件仍然包含在jar中。

    然后我想知道是否有某种方法可以让spring插件根据属性智能地包含或排除文件,例如

    gradlew clean build bootJar -Dspring.build.profile=production
    

    但找不到任何东西。

    我还试图排除源集中的文件

    sourceSets {
        main {
            java {
                if (project.environment == 'prod') {
                    exclude '**/dangerous/**'
                }
            }
        }
    }
    

    但是类文件仍然在jar文件中(在BOOT-INF/classes文件夹下)

    注意:此控制器需要在所有非生产环境中都可用,因此无法直接阻止编译此文件。

    如何排除某个类被包含在bootJar生成的jar文件中;或者有没有办法告诉gradle构建将包含在Spring配置文件中的文件?

2 个答案:

答案 0 :(得分:1)

我会采取不同的策略。

我会编写危险的控制器,以便在JVM环境中寻找非常具体的东西(例如自定义系统属性或环境变量)。

  • 让控制器测试变量并在检测到它正在生产中使用时抛出异常。大声失败,早点!可能将其放入静态初始化程序中,以便在控制器加载/接线时发生故障。

  • 安排属性/变量/以任何方式设置的内容都不会被您选择的构建/部署方法意外复制到生产中。 (有多种方法可以做到这一点......但是你有意对上下文进行模糊处理,因此很难建议合适的方法。)

这种方法的优点是它应该免受某人干扰构建脚本的影响。但建议通过构建脚本以及来排除控制器。 (腰带和牙套......)

答案 1 :(得分:0)

您可以使用gradle sourceSets执行此操作。

将此添加到您的gradle.build:

def env = project.hasProperty('env') ? project.env : 'development'

sourceSets {
    main {
        java {
            srcDir 'src'
            if ( env == 'production' ) {
                println "DANGEROUS source set is being used for project complie (env = $env)!"
            } else {
                println "SAFE source set is being used for project complie (env = $env)."
                exclude '**/dangerous/**'
            }
        }
    }
}

您可以使用" -P"。

传入项目属性

使用危险的Java代码调用进行编译:

gradle clean build bootJar -Penv=production

默认构建不包含危险的Java代码。

注意

如果您使用的是IDE,那么很多人都不会尊重您声明的源集。您将不得不使用gradle IDE(eclipse,idea)插件并添加相同的逻辑。

CI

这样的东西通常可以在部署到各种环境时通过CI作业传递。 此外,您可以将application.properties文件加载到gradle中,或使用系统属性来确定环境。