如何防止将危险的控制器包含在Spring Boot的生产配置文件中? [英] How can I prevent a dangerous controller from being included in production profile with Spring Boot?

查看:115
本文介绍了如何防止将危险的控制器包含在Spring Boot的生产配置文件中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

tl; dr 如何根据Spring配置文件将类排除在bootJar生成的jar文件中?


我会故意含糊,但会尝试提供尽可能多的信息.

我有一个C#.NET Web API(HTTP/1.1上的JSON).此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#)发送给其他第三方

我们有一套目前用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配置文件中的文件?

解决方案

我会采用其他方法.

我将编写危险的控制器,以便它在JVM环境中查找非常特定的内容(例如,自定义系统属性或环境变量).

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

  • 安排该属性/变量/所设置的任何内容都不会被您选择的构建/部署方法意外复制到生产中. (执行此操作的方法有多种...但是您故意模糊了上下文,因此很难提出合适的方法.)

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

tl;dr How can I exclude a class from being included in the jar file generated by bootJar, depending on a Spring profile?


I'm going to intentionally be vague, but will try to provide as much info as possible.

I have a C# .NET web api (JSON over HTTP/1.1). This api receives an encrypted payload from a third-party. This third-party has a library that is written for Java, but not C#. Due to time constraints and other factors, we have decided that it would be quicker to stand up a Java API with Spring Boot, and make calls to that API, rather than implementing their library ourselves.

The flow is

  1. Send encrypted payload to C# API
  2. (C#) Send encrypted payload to Java API
  3. (Java) Decrypt encrypted payload
  4. (Java) Do data transformation/verification using third-party library
  5. (Java) Re-encrypt payload
  6. (Java) Return encrypted payload to C# API
  7. (C#) Send to a different third-party

We have a suite of automated integration tests that are currently written in C#.

We need to make sure that, given a valid payload, when it's sent to the C# API, the payload gets forwarded to the Java API, gets decrypted properly, gets transformed properly, and gets re-encrypted properly for the other third-party to handle.

In order to facilitate this, I have created a new controller on the Java API that takes in the plaintext payload, encrypts it (just like the third-party would) and returns it to the caller. The caller can then send that encrypted payload do a different controller on the Java API to do the decryption+validation, and send the re-encrypted payload back to the caller.

The Java API trusts these automation-created payloads. The Java API generates a new key pair at runtime, and when it receives the plaintext payload, it signs it with the runtime-generated private key, and trusts messages signed with the runtime-generated public key.

The problem I have now, is that I don't want this functionality to be available in production. The contents of these payloads are too sensitive for bad actors to be able to manipulate.

I have solved part of the problem by adding the @Profile("test") attribute to the controller. This allows me to configure it at runtime like

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

That way, at runtime, spring prevents the controller from working

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

However, I understand that nothing is unhackable. As much as possible, I'd like to ensure that this can't be hit by any bad actors that get access to the box; or put differently, even if the attacker gets access to the box, and starts the application with

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

The controller still won't be functional.

I am building this jar using the spring-boot gradle plugin.

The only way I could think about doing this is preventing the controller from being included in the jar in the first place.

I tried adding this to my build script

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

but I see the class file still included in the jar.

Then I wondered if there was some way to have the spring plugin intelligently include or exclude files based on a property, like

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

but couldn't find anything.

I also tried to exclude the file in the sourceset

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

But the class file still ended up in the jar file (under the BOOT-INF/classes folder)

Note: This controller needs to be available in all non-production environments, so preventing compilation of this file outright is not an option.

How can I exclude a class from being included in the jar file generated by bootJar; or is there a way that I can tell gradle to build the files that would be included in a Spring profile?

解决方案

I would take a different tack.

I would write the dangerous controller so that it looked for something very specific in the JVM environment (e.g. a custom system property or environment variable).

  • Have the controller test the variable and throw in exception if it detects that it is being used in production. Fail loudly, and early! Possibly put this into a static initializer so that the failure occurs if the controller is loaded / wired.

  • Arrange that the property / variable / whatever is set in a way that cannot be accidentally copied to production by your chosen build / deploy methodology. (There are various ways to do this ... but you have been intentionally vague about the context which makes it hard to suggest an appropriate one.)

This approach has the advantage that it should be immune from someone interfering with the build script. But it would be advisable to figure out to exclude the controller via the build script as well. (Belt and braces ...)

这篇关于如何防止将危险的控制器包含在Spring Boot的生产配置文件中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆