BLOG | NGINX

借助 NGINX Unit 在零信任环境中运行 Spring Boot 应用

NGINX-Part-of-F5-horiz-black-type-RGB
Timo Stark 缩略图
Timo Stark
Published August 18, 2021

近来,好像人人都在讨论“安全性”。保护应用安全历来挑战重重,上云之后更是难上加难。而一种看起来比较靠谱的解决方案是“零信任”。Gartner 将“零信任”定义为:

……一种在所有计算基础架构中消除绝对信任的方法,“零信任”意味着会有意地且持续地计算和调整信任级别,使得“适时、适度地访问企业资源”得以实现。

但“零信任”究竟是如何在云环境中工作的,有哪些技术可以帮助您实现“零信任”?本文将在一个常见用例的背景下介绍零信任:

假设您是一家拥有各种由 Java 提供支持的 API 和服务的保险公司。现在您已迁移到云端,生产级工作负载由 CI/CD 流水线自动构建,并部署在公有云服务提供商的 Kubernetes 集群中。在处理敏感的客户信息时,一个主要要求就是使用 TLS 加密所有的流量。

您已在边缘负载均衡器和 Ingress Controller 上启用了加密,但对 Ingress Controller 和应用本身之间的流量进行加密的最佳方法是什么?答案就包括了需要启用应用服务器来处理 TLS。

许多 Java 商店使用 Apache Tomcat 作为首选的应用服务器,并将 Spring Boot 作为框架来构建独立的生产就绪型 Spring 应用(比使用 Java 本身更容易)。针对可以处理 HTTPS 流量的应用,本文详细展示了如何为其配置内置 Apache Tomcat 的 Spring Boot(以及 NGINX Unit)。

Spring Boot:HTTPS 流量通信

在撰写本文时,Spring Boot 已在 GitHub 上获得了近 6万个赞,它是 Java 框架领域一颗耀眼的巨星:好上手、轻量级且功能强大。Spring Boot 项目可以通过内置的应用服务器(例如 Apache Tomcat)编译成自包含的 .jar 文件。要启动 Java 服务,只需执行 .jar 文件并开始向暴露的端口(默认为 8080)发送流量即可,非常简单!

为了正确处理 TLS 连接(HTTPS 流量),您还需要为 Java 服务执行以下几个步骤。有关这些步骤的更多详细信息,请参阅 Spring 文档

这些说明适用于自签名证书和密钥,但对于生产环境,我们强烈建议替换来自官方证书颁发机构 (CA) 的证书密钥对。

  1. 创建包含证书和密钥的密钥存储器:

    # keytool -genkey -alias tomcat -keyalg RSA -keystore certstore
  2. 将密钥存储器放在 Tomcat 肯定能访问的容器镜像中。

  3. 将这些属性添加到 application.properties 文件中,并使用适当的密码替换 secret

    server.port = 8443
    server.ssl.key-store = classpath:keystore.jks
    server.ssl.key-store-password = secret

配置完成后,Spring Boot 应用将监听端口 8443 的 HTTPS 连接情况。但如果您还想接受 HTTP 连接怎么办?一旦在 application.properties 文件中配置了 HTTPS,您就不能再配置 HTTP;您必须在 Java 代码中实现 HTTP 处理。如需了解典型示例,请参阅 GitHub 上的 spring-projects 仓库。

事实证明,将 4 层 TLS 加密委托给应用框架(例如 Spring Boot)是可行的,但却不方便操作。如果您还使用其他语言和框架(例如 Ruby 和 Rails,或 Python 和 Flask)编写应用,则情况会更加复杂,因为每个框架都拥有自己的配置监听器以及处理密钥和证书的方式。但幸运的是,有一些工具可以让事情变得简单得多!

NGINX Unit 前来救场!

NGINX Unit 是一个开源的多语言应用服务器、反向代理和静态文件服务器,由 NGINX 核心工程团队为类 Unix 系统编写。借助 NGINX Unit,您可以使用标准化的 API 同时运行和管理用多种不同语言编写而成的应用,在撰写本文时,它支持除 Java 之外的七种语言:汇编、Go、JavaScript (Node.js®)、Perl、PHP、Python 及 Ruby。

Unit 还允许您单独配置 HTTP 和 HTTPS 接口,而不必再受使用它们的应用的限制。我们来通过 Spring Boot API 示例探索这个强大的功能。首先,我们必须为 Unit 服务器构建 Spring Boot 应用。在 Unit 实现 Java Servlet API 版本 3 时,唯一的变化是在 GradleMaven 构建定义中增加了一行。我们使用 Gradle 进行测试。

  1. war 插件添加到 build.gradle 文件:

    plugins {  id 'org.springframework.boot' version '2.4.4'
      id 'io.spring.dependency-management' version '1.0.11.RELEASE'
      id 'java'
      id 'war'
    }
  2. 构建 .war 文件:

    # ./gradlew build
  3. 生成的文件是 build/libs/rootProject‑Version.war,其中:

  4. 在名为 config.json 的文件中定义 Unit 配置:

    {
        "listeners": {
            "*:8080": {
                "pass": "applications/java"
            }
        },
        "applications": {
            "java": {
                "user": "unit",
                "group": "unit",
                "type": "java",
                "environment": {
                    "Deployment": "0.0.1"
                },
                "classpath": [],
                "webapp": "/path/to/build/libs/demo-0.0.1-SNAPSHOT.war"
            }
        }
    }
  5. 激活配置(有关详细信息,参阅文档):

    # curl -X PUT --data-binary @config.json --unix-socket \       /path/to/control.unit.sock http://localhost/config/applications/java-app

好了,就是这样!Spring Boot 应用现在正在 Unit 上运行,并且不需要 Tomcat 或其他 Java 应用服务器。

启用 HTTPS

您可能会问,“但如何启用 HTTPS 呢?”问得好,开干吧!您可以通过以下步骤轻松启用 HTTPS。(如上文所述,我们使用的是自签名证书。在生产环境中,请您确保使用 CA 签名证书。)

  1. 创建自签名证书包:

    # cat cert.pem ca.pem key.pem > bundle.pem
  2. 将证书包上传到 Unit:

    # curl -X PUT --data-binary @bundle.pem --unix-socket \
           /path/to/control.unit.sock http://localhost/certificates/bundle
  3. 在一个名为 listener.json 的文件中定义 HTTPS 监听器的配置:

    "127.0.0.1:443": {    "pass": "applications/java-app",
        "tls": {
            "certificate": "bundle"
        }
    }
  4. 激活新的监听器:

    # curl -X PUT --data-binary @listener.json --unix-socket \ /path/to/control.unit.sock http://localhost/config/listeners

应用现在接受了 TLS 加密连接 — 无需重新启动应用或 Unit。但其最强大之处在于,上述过程同样适用于使用 Unit 支持的任何语言和框架编写的应用。因此,无需深入了解特定语言的详细信息即可配置 HTTPS。

结语

强大的 NGINX Unit 监听器功能使得对于 HTTP 和 HTTPS 的支持变得更简单,并且这种支持完全不受应用的限制,因为加密是应用于监听器层而非应用层的。如要了解服务器名称指示 (SNI) 和自定义 OpenSSL 配置命令等其他 TLS 功能,请参阅 NGINX Unit 文档

如要开始使用 NGINX Unit,请参阅安装说明

NGINX Plus 用户可免费获得 NGINX Unit 支持。立即下载 30 天免费试用版,或与我们联系以讨论您的用例。


"This blog post may reference products that are no longer available and/or no longer supported. For the most current information about available F5 NGINX products and solutions, explore our NGINX product family. NGINX is now part of F5. All previous NGINX.com links will redirect to similar NGINX content on F5.com."