Help us learn about your current experience with the documentation. Take the survey.

FIPS 140-2 和 140-3

FIPS 是 “Federal Information Processing Standard”(联邦信息处理标准)的缩写,它为“加密模块”(Cryptographic Module, CM)定义了特定的安全实践。加密模块是一组硬件、软件和/或固件,用于实现经批准的安全功能(包括加密算法和密钥生成),并包含在加密边界内。

在 GitLab 中,加密模块几乎总是指其他产品或软件包发布中的嵌入式软件组件,且特定于某个二进制文件的版本。例如,特定版本的 Ubuntu 内核加密 API 加密模块或 OpenSSL 项目的 FIPS Provider。

模块在通过 NIST 认证实验室完成测试,并在 加密模块验证计划 中列有有效证书后,才会获得验证。加密模块必须根据其 CMVP 安全策略进行编译、安装和配置。

为什么需要关注?

GitLab 致力于为需要遵守 FIPS 140-2 和 140-3 标准的客户发布软件。

FIPS 140 是在美国公共部门开展业务的必要要求,同样适用于部分非美国公共部门组织以及特定行业(如医疗、金融等),具体取决于使用场景。FIPS 140-2 和 FIPS 140-3 的要求适用于所有美国联邦机构,包括他们购买的软件(无论是自托管还是云服务)。机构必须使用基于加密的安全系统,为所有操作和资产提供充分的信息安全保障,如 15 U.S.C. § 278g-3 所定义。

未经验证的加密技术目前被认为无法为信息或数据提供任何保护。实际上,此类数据将被视为未受保护的明文。如果机构要求信息或数据必须通过加密保护,则 FIPS 140-2 或 FIPS 140-3 即适用。本质上,如果需要加密,则必须经过验证。若加密模块被撤销,则不再允许使用该模块。

挑战在于,使用经过 FIPS 验证的模块需要使用特定版本的软件包或二进制文件。历史上,一些组织会通过固定版本(pin)或版本锁定(version-lock)来保持合规性。但问题是,这些经过验证的模块最终难免会出现漏洞,而获得新版本验证的漫长周期意味着同时满足以下两项联邦要求是不现实的:

  • 使用经过验证的模块。
  • 及时修复漏洞。

此领域的监管环境和政策制定是动态变化的,需要 GitLab 密切关注。

应避免使用的术语

这些术语在 GitLab 和软件供应商中被广泛使用。但我们应该避免使用它们,并更新我们的文档。

  • “FIPS compliant” 或 “FIPS compliance”:这些并非 NIST 或 CMVP 定义的官方术语,因此不应使用,因为它们可能引起歧义或主观解释。
    • 符合 FIPS 140 要求必须遵守整个标准以及加密模块的所有安全要求,包括严格使用 CMVP 验证的模块、CMVP 批准的安全功能、CMVP 批准的敏感参数生成和建立方法,以及 CMVP 批准的身份验证机制。
    • 该术语通常等同于使用 “CMVP-approved security functions”,而这仅是标准的一个方面。

应使用的术语

以下 官方术语和短语 已获 CMVP 批准使用。

  • “FIPS 140-2 Validated” 或 “FIPS-validated”:指具有 CMVP 证书和编号的加密模块。
  • “FIPS 140-2 Inside” 或 “FIPS inside”:指嵌入了 FIPS 验证模块的产品,例如 GitLab、GitLab 软件组件或 GitLab 分发的软件。如果产品内部包含 FIPS 140-2 模块并使用 FIPS 官方徽标,则必须同时标注 “FIPS 140-2 Inside” 和证书编号。
  • “CMVP-approved security functions” 或 “FIPS-approved algorithms”:虽然后者在技术上不是官方短语,但它传达了相同含义,并为不熟悉 NIST 术语的人提供了额外背景。这指的是 NIST SP 800-140C,其中规定了 CMVP 批准的加密算法及其授权使用场景。

GitLab 的 FIPS 140 实现

GitLab 是一家 优先采用 SaaS 模式(SaaS First) 的公司,因此我们遵循 联邦风险和授权管理计划(FedRAMP) 的最新指导。FedRAMP 要求云服务提供商在所有需要加密的地方使用经过 FIPS 验证的加密模块,包括加密、哈希、随机数生成和密钥生成。但是,根据 FedRAMP 安全控制基线的 SC-13 控制要求,在以下情况下可以使用未经 FIPS 验证的加密模块:

  • 已知 FIPS 验证版本存在漏洞。
  • 正在使用存在漏洞的功能。
  • 非 FIPS 版本修复了该漏洞。
  • 非FIPS版本已提交给NIST进行FIPS验证。即,在CMVP网站上列为“模块进行中(Modules In Process)”或“测试中实现(Implementation Under Test)”。
  • 已添加计划与行动方案(POA&M)以跟踪批准和部署时机。

FedRAMP 发布了一份草案(请注意:可能变更)《加密模块选择和使用政策》,旨在提供更实用的实施指导。值得注意的是,该政策倾向于通过补丁或更新来修复已知漏洞,而不是继续使用已知存在漏洞的已验证 FIPS 软件,因为已知漏洞的存在所带来的风险超过了验证提供的保障价值。

根据此草案政策的 CSP01 要求,GitLab 采取对加密模块应用补丁的立场。根据 CSP10,加密模块选择的优先顺序如下:

  1. 在验证的模块中修复漏洞。
  2. 使用未经验证的模块,按以下优先顺序:
    • 模块与 FIPS 验证模块基本相似;算法已验证。
    • 模块正在 FIPS 验证过程中;算法已验证。
    • 之前验证的模块 FIPS 验证已过期;算法已验证。
    • 模块未在 FIPS 验证过程中;算法已验证。
    • 算法已批准和测试但尚未验证,且模块未在 FIPS 验证过程中。

如何进行审计?

第三方评估组织(3PAO)通过以下方式验证使用经过 FIPS 验证的 CM:

  1. 检查证书编号。
  2. 验证 CM 是否以批准模式配置,并且仅使用 CM 安全策略中列为批准的算法。

GitLab 也进行内部持续监控,并且过去曾聘请独立审计机构根据 FIPS 140 标准审计我们的软件。结果可在 Trust Center 中找到。

GitLab FIPS 批准的软件

GitLab 目前为 Omnibus(Linux 软件包)部署、云原生(Helm chart)部署、GitLab Runner、安全分析器等发布软件。如上所述,GitLab 遵循 FedRAMP 指导,因此我们尽可能包含 FIPS 140-2 验证模块(内置 FIPS),但至少包含 FIPS 批准的算法(CMVP 批准的安全功能)。在无法同时实现安全性和 FIPS 140-2 合规性的情况下,GitLab 优先考虑安全性。

FIPS 模式下不支持的功能

某些 GitLab 功能在启用 FIPS 模式时可能无法正常工作。以下功能已知在 FIPS 模式下不工作。但可能还有其他未列出的功能在 FIPS 模式下也无法正常工作:

此外,以下软件包存储库在 FIPS 模式下被禁用:

开发指南

有关更多信息,请参阅上文并参考 GitLab 加密标准。如有疑问,请联系 #sec-assurance,或如果需要澄清某些内容,请提交 MR。

以下是开发 GitLab FIPS 批准软件的一些指南:

  • 我们应使大多数(如果不是全部)加密调用使用经过 FIPS 验证的 OpenSSL(示例),无论是:

    • 作为操作系统或容器基础镜像的一部分嵌入(首选)。
    • 独立部署。

    OpenSSL 3.0 现在可以使用名为 OpenSSL FIPS Provider fips.so 的 CMVP 验证模块,同时允许对 OpenSSL 的其余部分进行安全补丁而不会使模块失效(参考 OpenSSL README-FIPS.md)。这也现已可在 RHEL 9 和 UBI9 上使用(CMVP 证书 #4746)。

  • 我们应避免使用未经批准的加密算法(例如 MD5),并切换到 经过批准的 FIPS 140-3 算法(例如 SHA256)。因为 MD5 在密码学上已被攻破,所以这是一个好习惯。

  • 在某些情况下,非批准的加密算法可用于非加密目的。例如,SHA1 不是 FIPS 140-3 算法,但 Git 使用它进行非加密目的,因此我们可以使用它。在这些情况下,我们必须记录为何不用于加密目的,或者完全禁用该功能。

  • 向后兼容性。在某些功能中,切换算法可能会破坏现有功能。例如,数据库存储使用 bcrypt 加密的密码,这些密码无法在用户协助的情况下重新加密。

  1. GitLab 已将其 FIPS 批准的软件发布标准化为 RHEL 和 UBI,我们应遵循以下模式为 Ruby、Go、CNG、Omnibus 以及其他软件(如 Runner、安全分析器等)进行开发。

安装符合 FIPS 的 GitLab

本指南专门面向有要求运行符合 FIPS 的生产 GitLab 实例的公共用户或 GitLab 团队成员。本指南概述了一种混合部署,结合了 Omnibus 和我们的云原生 GitLab 安装的元素。

先决条件

  • Amazon Web Services (AWS) 账户。我们的首个目标环境运行在 AWS 上,并使用其他符合 FIPS 的 AWS 资源。对于许多 AWS 资源,您必须使用 FIPS 特定端点
  • 能够运行 Ubuntu 20.04 机器用于 GitLab。我们的首个目标环境使用混合架构。
  • 高级搜索(Advanced Search):GitLab 不提供打包的 Elastic 或 OpenSearch 部署。您必须使用符合 FIPS 的服务或禁用高级搜索。

设置启用了 FIPS 的集群

您可以使用 GitLab 环境工具包(GitLab Environment Toolkit) 来搭建一个用于开发和测试的启用了 FIPS 的集群。如先决条件中所述,这些说明使用 Amazon Web Services (AWS),因为这是首个目标环境。

设置您的环境

首先,您的 AWS 账户必须在 AWS Marketplace 控制台 中订阅一个启用了 FIPS 的 Amazon 机器镜像(AMI)。

本示例假设 Canonical Group LimitedUbuntu Pro 20.04 FIPS LTS AMI 已添加到您的账户中。此操作系统用于在 Amazon EC2 中运行的虚拟机。

Omnibus

获取启用了 FIPS 的 GitLab 集群的最简单方法是使用 Omnibus 参考架构。有关更多详细信息,请参阅 GET 快速入门指南。以下说明基于快速入门指南,对于 云原生混合(Cloud Native Hybrid) 安装也是必需的。

Terraform:使用 FIPS AMI

GitLab 团队成员可以在此内部手册页面查看有关如何使用 FIPS AMI 的更多信息: https://internal.gitlab.com/handbook/engineering/fedramp-compliance/get-configure/#terraform---use-fips-ami

Ansible:指定 FIPS Omnibus 构建

标准的 Omnibus GitLab 发行版构建自己的 OpenSSL 库,该库未经 FIPS 验证。但是,我们有每日构建,可以创建链接到操作系统 OpenSSL 库的 Omnibus 软件包。要使用此软件包,请在 Ansible vars.yml 中更新 gitlab_editiongitlab_repo_script_url 字段。

GitLab 团队成员可以在此内部手册页面查看有关 Ansible (AWS) 的更多信息: https://internal.gitlab.com/handbook/engineering/fedramp-compliance/get-configure/#ansible-aws

云原生混合(Cloud Native Hybrid)

云原生混合安装同时使用 Omnibus 和云原生 GitLab (CNG) 镜像。前面的说明涵盖了 Omnibus 部分,但还需要两个额外步骤来在 CNG 中启用 FIPS:

  1. 使用自定义的 Amazon Elastic Kubernetes Service (EKS) AMI。
  2. 使用基于 Red Hat Universal Base Image (UBI) 构建的 GitLab 容器。
构建自定义 EKS AMI

由于 Amazon 尚未发布启用了 FIPS 的 AMI,您必须使用 Packer 自己构建一个。

Amazon 发布了以下包含有关自定义 EKS AMI 信息的 Git 仓库:

GitHub 拉取请求 使得为 Kubernetes v1.21 创建启用了 FIPS 的 Amazon Linux 2 EKS AMI 成为可能。构建镜像的步骤如下:

  1. 安装 Packer

  2. 运行以下命令:

    git clone https://github.com/awslabs/amazon-eks-ami
    cd amazon-eks-ami
    git fetch origin pull/898/head:fips-ami
    git checkout fips-ami
    AWS_DEFAULT_REGION=us-east-1 make 1.21-fips # 请确保相应设置区域

如果您使用的是不同版本的 Kubernetes,请相应调整 make 命令和 Makefile

当 AMI 构建完成时,应创建一个新的 AMI,并显示类似以下消息:

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
us-west-2: ami-0a25e760cd00b027e

在此示例中,AMI ID 是 ami-0a25e760cd00b027e,但您的值可能不同。

构建启用了 FIPS 的基于 RHEL 的系统应该是可行的,但 存在一个未解决的问题阻止 Packer 构建完成

由于这是基于特定版本镜像构建的自定义 AMI,您必须定期重新构建自定义 AMI,以保持与最新的安全补丁和升级同步。

Terraform:使用自定义 EKS AMI

GitLab 团队成员可以在此内部手册页面查看有关如何使用自定义 EKS AMI 的更多信息: https://internal.gitlab.com/handbook/engineering/fedramp-compliance/get-configure/#terraform---use-a-custom-eks-ami

Ansible:使用 UBI 镜像

CNG 使用 Helm Chart 来管理要部署的容器镜像。要使用基于 UBI 的容器,请编辑 Ansible vars.yml 以使用自定义 Charts 变量:

all:
  vars:
    # ...
    gitlab_charts_custom_config_file: '/path/to/gitlab-environment-toolkit/ansible/environments/gitlab-10k/inventory/charts.yml'

现在在上述指定位置创建 charts.yml,并使用带有 -fips 后缀的标签。

有关更多详细信息,包括作为参考的 示例 values 文件,请参阅我们关于 Charts FIPS 的文档

您也可以使用发布标签,但版本控制比较棘手,因为每个组件可能使用自己的版本控制方案。例如,对于 GitLab v15.2:

global:
  image:
    tagSuffix: -fips
  certificates:
    image:
      tag: 20211220-r0
  kubectl:
    image:
      tag: 1.18.20

gitlab:
  gitaly:
    image:
      tag: v15.2.0
  gitlab-exporter:
    image:
      tag: 11.17.1
  gitlab-shell:
    image:
      tag: v14.9.0
  gitlab-mailroom:
    image:
      tag: v15.2.0
  gitlab-pages:
    image:
      tag: v1.61.0
  migrations:
    image:
      tag: v15.2.0
  sidekiq:
    image:
      tag: v15.2.0
  toolbox:
    image:
      tag: v15.2.0
  webservice:
    image:
      tag: v15.2.0
    workhorse:
      tag: v15.2.0

FIPS 性能基准测试

质量工程赋能团队(Quality Engineering Enablement)通过比较启用了 FIPS 的环境与非 FIPS 环境的性能来协助这些工作。

测试显示在某些地方存在影响,例如 Gitaly SSL,但影响不足以影响客户。

您可以在以下问题中找到有关 FIPS 性能基准测试的更多信息:

设置启用了 FIPS 的开发环境

最简单的方法是设置一个运行 Red Hat Enterprise Linux 8 的虚拟机。

Red Hat 为开发者提供免费许可证,并允许从 Red Hat 开发者门户 下载 CD 镜像。需要注册。

虚拟机设置完成后,您可以按照 GDK(GitLab Development Kit) 的安装说明进行操作,包括 RHEL 的高级说明。不使用 asdf 工具进行依赖管理,因为必须使用 Red Hat 提供的 Go 编译器和其他系统依赖项。

启用 FIPS 模式

安装完 GDK 及其依赖项后,运行以下命令(以 root 身份),然后重启虚拟机:

fips-mode-setup --enable

您可以通过运行以下命令检查是否已生效:

fips-mode-setup --check

在此环境中,OpenSSL 会拒绝执行 FIPS 标准禁止的加密操作。这使您可以重现与 FIPS 相关的错误,并验证修复。

您应该能够在虚拟机内部打开 Web 浏览器并登录到 GitLab 实例。

您可以通过运行以下命令再次禁用 FIPS 模式,然后重启虚拟机:

fips-mode-setup --disable

在代码中检测 FIPS 启用状态

您可以在 Ruby 代码中查询 Gitlab::FIPS 以确定实例是否启用了 FIPS:

def default_min_key_size(name)
  if Gitlab::FIPS.enabled?
    Gitlab::SSHPublicKey.supported_sizes(name).select(&:positive?).min || -1
  else
    0
  end
end

Omnibus FIPS 软件包

GitLab 有一个专用仓库(gitlab/gitlab-fips),用于构建符合 FIPS 的 Omnibus GitLab。这些 GitLab 构建编译为使用系统 OpenSSL,而不是 Omnibus 内嵌的 OpenSSL 版本。这些软件包为以下系统构建:

  • RHEL 8 和 9(及兼容系统)
  • AmazonLinux 2 和 2023
  • Ubuntu 20.04

这些软件包被 GitLab 环境工具包(GET) 使用。

请参阅 关于 FIPS 构建如何创建的部分

系统 Libgcrypt

由于一个错误,GitLab 17.6 及更早版本的 FIPS Linux 软件包没有使用系统 Libgcrypt,而是使用了与常规 Linux 软件包捆绑的相同 Libgcrypt。

此问题已在 GitLab 17.7 的所有 FIPS Linux 软件包中修复,AmazonLinux 2 除外。AmazonLinux 2 的 Libgcrypt 版本与 FIPS Linux 软件包附带的 GPGMEGnuPG 版本不兼容。

AmazonLinux 2 的 FIPS Linux 软件包将继续使用与常规 Linux 软件包捆绑的相同 Libgcrypt,否则我们将不得不降级 GPGME 和 GnuPG。

如果您需要完全合规,必须迁移到另一个提供 FIPS Linux 软件包的操作系统。

每日构建的 Omnibus FIPS 软件包

分发团队创建了 每日 FIPS Omnibus 构建,可用于测试目的。切勿将其用于生产环境。

Runner

请参阅 安装符合 FIPS 的 GitLab Runner 的文档

验证 FIPS

以下部分描述了验证 FIPS 是否启用的方法。

内核

$ cat /proc/sys/crypto/fips_enabled
1

Ruby (Omnibus 镜像)

$ /opt/gitlab/embedded/bin/irb
irb(main):001:0> require 'openssl'; OpenSSL.fips_mode
=> true

Ruby (CNG 镜像)

$ irb
irb(main):001:0> require 'openssl'; OpenSSL.fips_mode
=> true

Go

Google 在 Go 编译器中维护一个 dev.boringcrypto 分支,该分支可以静态链接 BoringSSL(一个从 OpenSSL 分支出来的 FIPS 验证模块)。然而,BoringCrypto 未获官方支持,尽管其他公司在使用它。

GitLab 使用 golang-fips(一个 dev.boringcrypto 分支的 分支)来构建通过 dlopen 动态链接 OpenSSL 的 Go 程序。这有几个优点:

  • 使用经过 FIPS 验证的系统 OpenSSL(RHEL/UBI)非常直接。
  • 这是 Red Hat go-toolset 软件包 使用的源代码。
  • go-toolset 不同,此分支似乎能跟上最新的 Go 版本。

但是,为此工作必须通过 CGO_ENABLED=1 启用 cgo。调用 C 代码时会有性能损失。

在 Linux x86 上使用 golang-fips 编译的项目会自动构建使用 OpenSSL 的加密例程。虽然 boringcrypto 构建标签会自动存在,但实际上不需要额外的构建标签。存在 特定的构建标签 来禁用这些加密钩子。

我们可以通过 go tool nm 检查给定的二进制文件是否在使用 OpenSSL,并查找名为 Cfunc__goboringcryptocrypto/internal/boring/sig.BoringCrypto 的符号。

例如:

$ # 在 Golang-FIPS 1.17 库中查找
$ go tool nm nginx-ingress-controller | grep '_Cfunc__goboringcrypto_|\bcrypto/internal/boring/sig\.BoringCrypto' | tail
 2a0b650 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_SHA384_Final
 2a0b658 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_SHA384_Init
 2a0b660 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_SHA384_Update
 2a0b668 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_SHA512_Final
 2a0b670 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_SHA512_Init
 2a0b678 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_SHA512_Update
 2a0b680 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_internal_ECDSA_sign
 2a0b688 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_internal_ECDSA_verify
 2a0b690 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_internal_ERR_error_string_n
 2a0b698 D crypto/internal/boring._cgo_71ae3cd1ca33_Cfunc__goboringcrypto_internal_ERR_get_error
$ # 在 Golang-FIPS 1.22 库中查找
$ go tool nm tenctl | grep '_Cfunc__goboringcrypto_|\bcrypto/internal/boring/sig\.BoringCrypto'
  4cb840 t crypto/internal/boring/sig.BoringCrypto.abi0

此外,LabKit 包含例程来 检查是否启用了 FIPS

FIPS 构建是如何创建的

许多 GitLab 项目(例如:Gitaly、GitLab Pages)已标准化使用 FIPS_MODE=1 make 在本地构建 FIPS 二进制文件。

Omnibus

Omnibus FIPS 构建通过设置 USE_SYSTEM_SSL 环境变量为 true 来触发。当设置此环境变量时,Omnibus 配方依赖项(如 curl、NGINX 和 libgit2)将链接到系统 OpenSSL。OpenSSL 将不会包含在 Omnibus 构建中。

Omnibus 构建是使用 使用 golang-fips 编译器的容器镜像 创建的。例如,此任务 创建了用于构建 RHEL 8 软件包的 registry.gitlab.com/gitlab-org/gitlab-omnibus-builder/centos_8_fips:3.3.1 镜像。

为其他 Linux 发行版添加新的 FIPS 构建

首先,您需要确保目标 Linux 发行版有对应的 Omnibus 构建器镜像。用于构建 Omnibus 软件包的镜像是由 Omnibus Builder 镜像 创建的。

请参阅 此合并请求。可以通过以下方式添加新镜像:

  1. 添加带有 _fips 后缀的 CI 任务(例如:ubuntu_18.04_fips)。
  2. 确保 Dockerfile 使用 Snippets.new(fips: fips).populate 而不是 Snippets.new.populate

在此镜像被标记后,向 Omnibus GitLab 添加一个新的 [CI 任务]。

云原生 GitLab (CNG)

云原生 GitLab CI 管道使用几个基础镜像生成镜像:

UBI 镜像附带了与 RHEL 使用的相同的 OpenSSL 软件包。这使得无需 RHEL 即可构建符合 FIPS 的二进制文件成为可能。RHEL 8.2 附带了 经过 FIPS 验证的 OpenSSL,但 8.5 版本正在接受 FIPS 验证。

此合并请求 为 CNG 镜像引入了一个 FIPS 管道。标记为 FIPS 的镜像带有 -fips 后缀。例如,webservice 容器具有以下标签:

  • master
  • master-ubi
  • master-fips

FIPS 构建的基础镜像

使用 FIPS 管道测试合并请求

可以触发 Package 和 QA 的合并请求,也可以触发 FIPS 软件包和参考架构测试管道。触发使用的基础镜像是 Ubuntu 20.04 FIPS:

  1. 如果尚未触发,则触发 e2e:test-on-omnibus-ee 任务。
  2. gitlab-omnibus-mirror 子管道上,手动触发 Trigger:package:fips
  3. 软件包任务完成后,手动触发 RAT:FIPS 任务。