FIPS準拠

FIPSとは「Federal Information Processing Standard」の略で、「暗号モジュール」(CM) に対する一定のセキュリティ慣行を定義した文書です。これは、米国連邦機関に製品を販売するベンダーが一定のセキュリティ・フロアを満たすことを保証することを目的としています。

caution
FIPS準拠のGitLabインスタンスを構築することはできますが、すべての機能が含まれているわけではありません。FIPSに準拠したインスタンスは、FIPSのインストール手順に忠実に設定する必要があります。

現在のFIPS標準は2つあります:140-2と140-3です。GitLabでは通常FIPS 140-2を指します。

現在の状態

GitLab はこのドキュメントで指定されたビルドの FIPS 140-2 コンプライアンスを完了しています。FIPS140-2認証はカスタマーアシュアランスパッケージ、特にコミュニティパッケージでご覧いただけます。

GitLabのFIPSコンプライアンス

準拠するためには、すべてのコンポーネント(GitLab自体、Gitalyなど)が準拠し、それらのコンポーネント間の通信、それらによって使用されるストレージも準拠する必要があります。準拠できない機能は、FIPSモードが有効なときに無効にしなければなりません。

利用される暗号モジュール

暗号モジュール名CMVP番号インスタンスタイプ使用ソフトウェアコンポーネント
Ubuntu 20.04 AWSカーネル暗号API暗号モジュール4132EC2Linuxカーネル
Ubuntu 20.04 OpenSSL暗号モジュール3966EC2Gitaly、Rails(Puma/Sidekiq)
Ubuntu 20.04 Libgcrypt暗号モジュール3902EC2インスタンス gpg,sshd
Amazon Linux 2 カーネル暗号 API 暗号モジュール3709EKSノードLinuxカーネル
Amazon Linux 2 OpenSSL 暗号モジュール3553EKSノードNGINX
RedHat Enterprise Linux 8 OpenSSL 暗号モジュール4271EKSノードUBIコンテナ:Workhorse、Pages、コンテナレジストリ、Rails (Puma/Sidekiq)、セキュリティアナライザ
RedHat Enterprise Linux 8 Libgcrypt 暗号モジュール3784EKSノードUBIコンテナ:GitLab Shell、gpg

対応オペレーションシステム

対応するハイブリッド・プラットフォームは以下の通りです:

  • Omnibus GitLab: Ubuntu 20.04 LTS
  • クラウドネイティブGitLab:Amazon Linux 2(EKS)

FIPSモードでサポートされていない機能

FIPSモードが有効な場合、一部のGitLab機能は動作しない可能性があります。以下の機能はFIPSモードでは動作しないことが知られています。しかし、ここに挙げられていない機能でもFIPSモードで正しく動作しないものがあるかもしれません:

さらに、これらのパッケージリポジトリはFIPSモードでは無効になります:

GitLab における FIPS 検証

FIPS準拠とは異なり、FIPSバリデーションは認定監査役による正式な準拠宣言です。監査に合格するために必要な要件は、FIPS準拠と同じです。

FIPS検証済みモジュールのリストは、NIST(米国国立標準技術研究所)の暗号モジュール検証プログラムで見ることができます。

FIPS準拠のGitLabインストール

このガイドは、FIPSに準拠したGitLabの本番インスタンスを実行する必要がある公開ユーザーまたはGitLabチームメンバー向けのものです。このガイドでは、OmnibusとクラウドネイティブGitLabインストールの両方の要素を使用したハイブリッドデプロイの概要を説明します。

前提条件

  • Amazon Web Servicesアカウント。最初のターゲット環境はAWS上で動作しており、他のFIPS準拠のAWSリソースを使用しています。
  • GitLab 用に Ubuntu 20.04 マシンを実行する能力。私たちの最初のターゲット環境はハイブリッドアーキテクチャを使用しています。

FIPS対応クラスターのセットアップ

GitLab Environment Toolkitを使って、開発とテストのための FIPS 対応クラスターを立ち上げることができます。前提条件のところで述べたように、この説明ではAmazon Web Services(AWS) を使います。これは最初のターゲット環境だからです。

環境のセットアップ

開始するには、AWSアカウントは、AWS MarketplaceコンソールでFIPS対応のAmazon Machine Image(AMI) をサブスクライブする必要があります。

この例では、Canonical Group Limited によるUbuntu Pro 20.04 FIPS LTS AMI がアカウントに追加されていることを想定しています。このオペレーティングシステムは、Amazon EC2で実行される仮想マシンに使用されます。

Omnibus

FIPS対応のGitLabクラスターを手に入れる最もシンプルな方法は、Omnibusリファレンスアーキテクチャを使うことです。詳しくはGETクイックスタートガイドをご覧ください。以下の手順はクイックスタートに基づいており、クラウド・ネイティブ・ハイブリッドのインストールにも必要です。

Terraformを使用します:FIPS AMI を使う

GitLabチームメンバーはこの内部ハンドブックページでFIPS AMIの使い方を見ることができます:https://internal.gitlab.com/handbook/engineering/fedramp-compliance/get-configure/#terraform---use-fips-ami

AnsibleFIPS Omnibus ビルドの指定

標準のOmnibus GitLabリリースは独自のOpenSSLライブラリをビルドしますが、これはFIPSバリデーションされていません。しかし、Omnibusのナイトリービルドでは、オペレーティングシステムのOpenSSLライブラリとリンクするOmnibusパッケージを作成します。このパッケージを使用するには、Ansiblevars.ymlgitlab_editiongitlab_repo_script_url フィールドを更新します。

GitLabチームのメンバーは、このAnsibleの内部ハンドブックページ(AWS) で詳細を見ることができます:https://internal.gitlab.com/handbook/engineering/fedramp-compliance/get-configure/#ansible-aws

クラウドネイティブハイブリッド

Cloud Native Hybridインストールでは、OmnibusとCloud Native GitLab(CNG) イメージの両方を使用します。これまでの説明でOmnibusの部分はカバーしましたが、CNGでFIPSを有効にするにはさらに2つのステップが必要です:

  1. カスタムAmazon Elastic Kubernetes Service(EKS) AMIを使います。
  2. RedHatのUniversal Base Image(UBI) でビルドしたGitLabコンテナを使用します。
カスタム EKS AMI のビルド

AmazonはまだFIPS対応のAMIを公開していないため、Packerを使って自分でAMIを構築する必要があります。

Amazonは以下のGitリポジトリでカスタムEKS AMIに関する情報を公開しています:

この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 # Be sure to set the region accordingly
    

異なるバージョンの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 ベースのコンテナを使用するには、Ansiblevars.yml を編集してカスタム Chart 変数を使用します:

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

ここで、上記で指定した場所にcharts.yml を作成し、-fips サフィックス付きのタグを指定します。

詳細については、FIPSに関するChartのドキュメントを参照してください。

リリースタグを使うこともできますが、各コンポーネントが独自のバージョン管理スキームを使っている可能性があるため、バージョン管理が厄介です。例えば、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パフォーマンス・ベンチマーク

品質エンジニアリングイネーブルメントチームは、FIPS対応環境がFIPS非対応環境と比較して優れているかどうかを確認することで、これらの取り組みを支援します。

テストでは、Gitaly SSLなどいくつかの場所で影響が見られますが、顧客に影響を与えるほど大きなものではありません。

FIPSパフォーマンス・ベンチマークに関する詳細は、以下のイシューをご覧ください:

FIPS対応開発環境の構築

最も簡単な方法は、Red Hat Enterprise Linux 8 を実行する仮想マシンをセットアップすることです。

Red Hat は開発者に無償のライセンスを提供し、Red Hat 開発者ポータルから CD イメージをダウンロードすることを許可しています。登録が必要です。

仮想マシンのセットアップが完了したら、RHEL 用の高度な手順も含め、GDK のインストール手順に従います。RedHat が提供する Go コンパイラやその他のシステム依存関係を使用することが不可欠なため、依存関係の管理にはasdf を使用しないことに注意してください。

FIPS モードの有効化

GDKとその依存関係がインストールされたら、このコマンドを(rootで)実行し、仮想マシンを再起動します:

fips-mode-setup --enable

このコマンドを実行することで、GDKが有効になったかどうかを確認できます:

fips-mode-setup --check

この環境では、OpenSSL は FIPS 標準で禁止されている暗号オペレーションの実行を拒否します。これにより、FIPS 関連のバグを再現し、修正を検証することができます。

仮想マシン内でウェブブラウザを開き、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には、FIPSに準拠してビルドされたOmnibus GitLabのビルド専用のリポジトリ(gitlab/gitlab-fips)があります。これらのGitLabビルドは、Omnibus組み込みバージョンのOpenSSLではなく、システムのOpenSSLを使うようにコンパイルされています。これらのパッケージは

  • RHEL 8 (および互換)
  • AmazonLinux 2
  • Ubuntu

これらはGitLab Environment Toolkit (GET)によって消費されます。

FIPS ビルドの作成方法のセクションを参照してください。

毎晩の 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は、OpenSSLからフォークされたFIPSバリデーションモジュールであるBoringSSLを静的にリンクできるように、Goコンパイラのdev.boringcrypto ブランチ 。ただし、BoringSSLは公開用ではありません。

私たちはgolang-fips dev.boringcrypto ブランチのフォーク を使って、OpenSSL をdlopen経由で動的にリンクする Go プログラムをビルドしています。これにはいくつかの利点があります:

  • FIPSで検証されたシステムOpenSSLを使うのは簡単です。
  • これはRed Hat の go-toolset パッケージで使用されているソースコードです。
  • go-toolset とは異なり、このフォークは最新の Go リリースに対応しているようです。

ただし、これを動作させるには、CGO_ENABLED=1 を使ってcgo を有効にする必要があります。Cコードに呼び出すとパフォーマンスが低下します。

Linux x86 でgolang-fips を使ってコンパイルされたプロジェクトは、OpenSSL を使用する暗号化ルーチンを自動的にビルドします。boringcrypto ビルド・タグは自動的に存在しますが、実際には追加のビルド・タグは必要ありません。これらの暗号化フックを無効にする特定のビルド・タグがあります。

指定したバイナリがOpenSSLを使用しているかどうかはgo tool nmCfunc__goboringcrypto という名前のシンボルを探すことで確認できます。例えば

$ go tool nm nginx-ingress-controller  | grep Cfunc__goboringcrypto | 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

さらに、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 コンパイラ](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/blob/master/docker/snippets/go_fips)を使用するコンテナイメージ[を使用して作成されます。例えば、このジョブはRHEL 8 用のパッケージのビルドに使用されるregistry.gitlab.com/gitlab-org/gitlab-omnibus-builder/centos_8_fips:3.3.1 イメージを作成しました。

別の Linux ディストリビューション用の新しい FIPS ビルドの追加

まず、目的の Linux ディストリビューション用の Omnibus Builder イメージがあることを確認する必要があります。Omnibus パッケージのビルドに使用されるイメージはOmnibus Builder イメージで作成されます。

このマージリクエストをレビューしてください。新しいイメージを追加するには

  1. サフィックスが_fips の CI ジョブを追加します (例:ubuntu_18.04_fips)。
  2. DockerfileSnippets.new.populate の代わりにSnippets.new(fips: fips).populate を使っていることを確認してください。

この画像にタグを付けたら、Omnibus GitLabに新しいCIジョブを追加します。

クラウドネイティブGitLab(CNG)

Cloud Native GitLab CIパイプラインはいくつかのベースイメージを使ってイメージを生成します:

UBI イメージには、RHEL で使われているものと同じ OpenSSL パッケージが同梱されています。これにより、RHEL を必要とせずに FIPS 準拠のバイナリをビルドすることができます。RHEL 8.2 にはFIPS 検証済みの OpenSSL が同梱されていますが、8.5 では FIPS 検証のためのレビューが行われています。

このマージリクエストはCNG イメージ用の FIPS パイプラインを導入します。FIPS 用にタグ付けされたイメージには-fips という接尾辞が付きます。例えば、webservice コンテナには以下のタグがあります:

  • master
  • master-ubi8
  • master-fips

FIPSパイプラインによるマージリクエストのテスト

パッケージと QA をトリガーできるマージリクエストは、FIPS パッケージとリファレンスアーキテクチャのテストパイプラインをトリガーできます。トリガーに使用されるベースイメージはUbuntu 20.04 FIPSです:

  1. まだトリガーされていない場合は、e2e:package-and-test ジョブをトリガーします。
  2. gitlab-omnibus-mirror 子パイプラインで、手動でTrigger:package:fips をトリガーします。
  3. パッケージジョブが完了したら、手動でRAT:FIPS ジョブをトリガします。