フィールドレベル暗号化を使用した機密データの保護
Amazon CloudFront では、HTTPS を使用して、オリジンサーバーへの安全なエンドツーエンド接続を強制できます。フィールドレベル暗号化では、セキュリティのレイヤーが追加されます。これにより、システムの処理中に特定のデータに特定のアプリケーションのみがアクセスできるように、そのデータを保護できます。
フィールドレベル暗号化により、ユーザーが機密情報をウェブサーバーに安全にアップロードできるようになります。ユーザーから提供される機密情報は、ユーザー近くのエッジで暗号化され、アプリケーションスタック全体で暗号化された状態が維持されます。この暗号化により、データを必要としており、復号するための認証情報を持つアプリケーションだけが暗号化できるようになります。
フィールドレベル暗号化を使用するには、CloudFront ディストリビューションの設定で、暗号化する POST リクエストの一連のフィールドと、それらの暗号化に使用するパブリックキーを指定します。リクエストの最大 10 個のデータフィールドを暗号化できます (フィールドレベル暗号化を使用して、リクエストのすべてのデータをまとめて暗号化することはできません。暗号化する個々のフィールドを指定する必要があります)。
フィールドレベル暗号化を含む HTTPS リクエストがオリジンに転送され、リクエストがオリジンアプリケーションまたはサブシステム全体にルーティングされても、機密データは暗号化されたままです。それにより、機密データの漏洩や偶発的な損失のリスクが軽減されます。クレジット番号へのアクセスを必要とする支払い処理システムなど、ビジネス上の理由で機密データにアクセスする必要のあるコンポーネントは、適切なプライベートキーを使用してデータを復号化し、そのデータにアクセスできます。
注記
フィールドレベル暗号化を使用するには、オリジンがチャンクエンコードをサポートしている必要があります。
CloudFront のフィールドレベル暗号化では、非対称暗号化 (パブリックキー暗号化とも呼ばれる) が使用されます。CloudFront にパブリックキーを渡すと、指定したすべての機密データが自動的に暗号化されます。CloudFront に渡したキーは、暗号化された値の復号化には使用できません。この目的で使用できるのはプライベートキーのみです。
フィールドレベル暗号化の概要
以下に示しているのは、フィールドレベル暗号化の設定手順の概要です。この手順の詳細については、「フィールドレベル暗号化を設定する」を参照してください。
-
パブリックキーとプライベートキーのペアを取得する。CloudFront でフィールドレベル暗号化を設定する前に、パブリックキーを取得して追加する必要があります。
-
フィールドレベル暗号化のプロファイルを作成する。CloudFront で作成するフィールドレベル暗号化のプロファイルで、暗号化するフィールドを定義します。
-
フィールドレベル暗号化の設定を作成する。設定では、特定のデータフィールドの暗号化に使用するプロファイル (リクエストのコンテンツタイプまたはクエリ引数に基づく) を指定します。また、さまざまなシナリオで必要なリクエスト転送動作オプションを選択することもできます。例えば、リクエスト URL のクエリ引数で指定されたプロファイル名が CloudFront に存在しない場合の動作を設定できます。
-
キャッシュ動作にリンクする。設定をディストリビューションのキャッシュ動作にリンクして、いつ CloudFront がデータを暗号化するかを指定します。
フィールドレベル暗号化を設定する
フィールドレベル暗号化を使用するには、以下の手順に従います。フィールドレベル暗号化のクォータ (以前は制限と呼ばれていました) の詳細については、「クォータ」を参照してください。
ステップ 1: RSA キーペアを作成する
開始するには、パブリックキーとプライベートキーを含む RSA キーペアを作成する必要があります。パブリックキーにより CloudFront がデータを暗号化できるようになり、プライベートキーによりオリジンのコンポーネントが暗号化されたフィールドを復号できるようになります。OpenSSL または別のツールを使用してキーペアを作成できます。キーのサイズは 2,048 ビットであることが必要です。
たとえば、OpenSSL を使用する場合、次のコマンドを使用して 2048 ビット長のキーペアを生成し、private_key.pem
ファイルに保存できます。
openssl genrsa -out private_key.pem 2048
生成されるファイルには、パブリックキーとプライベートキーの両方が含まれます。そのファイルからパブリックキーを抽出するには、次のコマンドを実行します。
openssl rsa -pubout -in private_key.pem -out public_key.pem
公開キーファイル (public_key.pem
) には、次のステップで貼り付けるエンコードされたキー値が含まれています。
ステップ 2: パブリックキーを CloudFront に追加する
RSA キーペアを取得したら、パブリックキーを CloudFront に追加します。
パブリックキーを CloudFront に追加するには (コンソール)
AWS Management Consoleにサインインし、https://console.aws.amazon.com/cloudfront/v4/home
で CloudFront コンソールを開きます。 -
ナビゲーションペインで、[Public key (パブリックキー)] を選択します。
-
[Add public key (パブリックキーを追加)] を選択します。
-
[Key name (キー名)] にキーの一意の名前を入力します。キー名にはスペースを使用できません。英数字、アンダースコア (_)、ハイフン (-) のみを使用できます。最大長は 128 文字です。
-
[Key value (キー値)] に、
-----BEGIN PUBLIC KEY-----
および-----END PUBLIC KEY-----
行を含む、パブリックキーのエンコードされたキー値を貼り付けます。 -
[Comment (コメント)] で、オプションのコメントを追加します。たとえば、パブリックキーの有効期限を含めることができます。
-
[追加] を選択します。
CloudFront で使用するキーを追加するには、このステップの手順を繰り返します。
ステップ 3: フィールドレベル暗号化のプロファイルを作成する
1 つ以上のパブリックキーを CloudFront に追加した後、CloudFront にどのフィールドを暗号化するかを指示するプロファイルを作成します。
フィールドレベル暗号化のプロファイルを作成するには (コンソール)
-
ナビゲーションペインで、[Field-level encryption (フィールドレベル暗号化)] を選択します。
-
[Create profile (プロファイルの作成)] を選択します。
-
以下のフィールドに入力します。
- Profile name
-
プロファイルの一意の名前を入力します。キー名にはスペースを使用できません。英数字、アンダースコア (_)、ハイフン (-) のみを使用できます。最大長は 128 文字です。
- Public key name
-
ドロップダウンリストから、ステップ 2 で CloudFront に追加したパブリックキーの名前を選択します。CloudFront では、このプロファイルで指定したフィールドの暗号化に、このキーが使用されます。
- Provider name
-
キーを識別するのに役立つフレーズ (キーペアを取得したプロバイダーなど) を入力します。この情報は、プライベートキーと共に、アプリケーションがデータフィールドを復号化するときに必要になります。プロバイダー名にはスペースを使用できません。英数字、コロン (:)、アンダースコア (_)、ハイフン (-) のみを使用できます。最大長は 128 文字です。
- Field name pattern to match
-
CloudFront で暗号化するデータフィールドの名前、またはリクエスト内のデータフィールド名を識別するパターンを入力します。+ オプションを選択して、このキーで暗号化するすべてのフィールドを追加します。
フィールド名パターンには、データフィールドの名前全体を入力するか (DateOfBirth など)、ワイルドカード文字 (*) を使用して名前の最初の部分のみを入力します (CreditCard* など)。フィールド名パターンには、オプションのワイルドカード文字 (*) に加えて、英数字、角かっこ ([ および ])、ピリオド (.)、アンダースコア (_)、ハイフン (-) のみを含める必要があります。
異なるフィールド名パターンに重複する文字を使用しないでください。たとえば、ABC * というフィールド名パターンがある場合、AB * という別のフィールド名パターンを追加することはできません。また、フィールド名は大文字と小文字が区別され、最大長は 128 文字です。
- コメント
-
(オプション) このプロファイルに関するコメントを入力します。最大長は 128 文字です。
-
フィールドに入力した後、[Create profile (プロファイルの作成)] を選択します。
-
さらにプロファイルを追加する場合は、[Add profile (プロファイルの追加)] を選択します。
ステップ 4: 設定を作成する
1 つ以上のフィールドレベル暗号化のプロファイルを作成した後、リクエストのコンテンツタイプを指定する設定を作成します。この設定には、暗号化するデータ、暗号化に使用するプロファイル、および CloudFront による暗号化の処理方法を指定するその他のオプションが含まれます。
たとえば、CloudFront がデータを暗号化できないときに、CloudFront が以下のシナリオでリクエストをブロックするかオリジンに転送するかを指定できます。
-
リクエストのコンテンツタイプが設定にない場合 – コンテンツタイプが設定に追加されていない場合に、CloudFront がそのコンテンツタイプのリクエストをデータフィールドの暗号化なしでオリジンに転送するか、ブロックしてエラーを返すかを指定できます。
注記
コンテンツタイプを設定に追加していても、そのタイプで使用するプロファイルを指定していない場合、そのコンテンツタイプのリクエストは、CloudFront により常にオリジンに転送されます。
-
クエリ引数で指定したプロファイル名が不明な場合 –
fle-profile
クエリ引数で、ディストリビューションに存在しないプロファイル名が指定されている場合に、CloudFront がリクエストをデータフィールドの暗号化なしでオリジンに送るか、リクエストをブロックしてエラーを返すかを指定できます。
設定で、URL でクエリ引数としてプロファイルを提供するかどうかを指定して、そのクエリのコンテンツタイプにマッピングしたプロファイルを上書きすることもできます。デフォルトでは、CloudFront では、コンテンツタイプにマッピングしたプロファイル (指定してある場合) が使用されます。これにより、デフォルトで使用されるプロファイルを提供できますが、特定のリクエストに使用される別のプロファイルを指定することもできます。
たとえば、使用するクエリ引数プロファイルとして (設定で) SampleProfile
を指定できます。さらに、https://d1234.cloudfront.net?fle-profile=SampleProfile
の代わりに URL https://d1234.cloudfront.net
を使用できます。これにより、CloudFront がこのリクエストに、リクエストのコンテンツタイプ用に設定したプロファイルではなく SampleProfile
を使用できるようになります。
1 つのアカウント用に最大 10 個の設定を作成し、いずれかの設定をそのアカウントの任意のディストリビューションのキャッシュ動作に関連付けることができます。
フィールドレベル暗号化の設定を作成するには (コンソール)
-
[Field-level encryption (フィールドレベル暗号化)] ページで、[Create configuration (設定の作成)] を選択します。
注意: プロファイルを 1 つ以上作成していない場合、設定を作成するオプションは表示されません。
-
以下のフィールドに入力して、使用するプロファイルを指定します (一部のフィールドは変更できません)。
- Content type (変更不可)
-
コンテンツタイプは
application/x-www-form-urlencoded
に設定されており、変更することはできません。 - Default profile ID (オプション)
-
ドロップダウンリストから、[Content type (コンテンツタイプ)] フィールドでコンテンツタイプにマッピングするプロファイルを選択します。
- Content format (変更不可)
-
コンテンツ形式は
URLencoded
に設定されており、変更することはできません。
-
以下のオプションに対する CloudFront のデフォルト動作を変更する場合は、該当するチェックボックスをオンにします。
- Forward request to origin when request's content type is not configured
-
リクエストのコンテンツタイプに使用するプロファイルを指定していないときに、リクエストをオリジンに転送させる場合は、このチェックボックスをオンにします。
- Override the profile for a content type with a provided query argument
-
クエリ引数で指定したプロファイルによって、コンテンツタイプ用に指定したプロファイルを上書する場合は、このチェックボックスをオンにします。
-
このチェックボックスをオンにして、クエリ引数によってデフォルトプロファイルが上書きされるようにした場合は、設定で以下の追加フィールドを入力する必要があります。クエリで使用するこれらのクエリ引数マッピングは最大 5 つ作成できます。
- Query argument
-
fle-profile
クエリ引数の URL に含める値を入力します。CloudFront は、このクエリ引数の値に関連付けられたプロファイル ID (次のフィールドで指定) をこのクエリのフィールドレベル暗号化に使用します。最大長は 128 文字です。値にはスペースを含めることはできません。英数字、ダッシュ (-)、ピリオド (.)、アンダースコア (_)、アスタリスク (*)、プラス記号 (+)、パーセント (%) のみを使用する必要があります。
- Profile ID
-
ドロップダウンリストから、[Query argument (クエリ引数)] に入力した値に関連付けるプロファイルを選択します。
- Forward request to origin when the profile specified in a query argument does not exist
-
クエリ引数で指定したプロファイルが CloudFront で定義されていないときに、リクエストがオリジンに転送されるようにするには、このチェックボックスをオンにします。
ステップ 5: キャッシュ動作に設定を追加する
フィールドレベル暗号化を使用するには、設定 ID をディストリビューション用の値として追加して、ディストリビューションのキャッシュ動作に設定をリンクします。
重要
フィールドレベルの暗号化設定をキャッシュ動作にリンクするには、常に HTTPS を使用し、ビューワーからの HTTP POST
および PUT
リクエストを受け入れるようにディストリビューションを設定する必要があります。つまり、以下が満たされている必要があります。
-
キャッシュ動作の [ビューワープロトコルポリシーは] が [HTTP を HTTPS にリダイレクト] または [HTTPS のみ] に設定されている必要があります。(AWS CloudFormation または CloudFront API で、
ViewerProtocolPolicy
はredirect-to-https
またはhttps-only
に設定されている必要があります)。 -
キャッシュ動作の [Allowed HTTP Methods] (許可された HTTP メソッド) が、[GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE] に設定されている必要があります。(AWS CloudFormation または CloudFront API では、
AllowedMethods
がGET
、HEAD
、OPTIONS
、PUT
、POST
、PATCH
、DELETE
に設定されている必要があります。これらは任意の順序で指定できます)。 -
オリジン設定の [オリジンプロトコルポリシー] が [ビューワーに合わせる] または [HTTPS のみ] に設定されている必要があります。(AWS CloudFormation または CloudFront API で、
OriginProtocolPolicy
はmatch-viewer
またはhttps-only
に設定されている必要があります)。
詳細については、「ディストリビューション設定リファレンス」を参照してください。
オリジンでデータフィールドを復号する
CloudFront は AWS Encryption SDK を使用してデータフィールドを暗号化します。データはアプリケーションスタック全体で暗号化されたままであり、復号化するための認証情報のあるアプリケーションによってのみアクセスできます。
暗号化の後、暗号テキストは base64 でエンコードされます。アプリケーションがオリジンでテキストを復号化するときには、まず暗号テキストをデコードしてから、AWS Encryption SDK を使用してデータを復号化する必要があります。
以下のサンプルコードでは、アプリケーションがオリジンでデータを復号化する方法を示しています。次の点に注意してください。
-
わかりやすい例になるように、このサンプルは作業ディレクトリのファイルからパブリックキーとプライベートキー (DER 形式) を読み込みます。実際には、オフラインのハードウェアセキュリティモジュールなどの安全なオフラインの場所にプライベートキーを保存し、開発チームにパブリックキーを配布します。
-
CloudFront はデータの暗号化時に特定の情報を使用します。データの復号化には、オリジンで同じ一連のパラメータを使用する必要があります。以下に示しているのは、MasterKey の初期化時に CloudFront が使用するパラメータです。
-
PROVIDER_NAME: フィールドレベル暗号化のプロファイルを作成したときにこの値を指定しました。同じ値をここで使用します。
-
KEY_NAME: パブリックキーを CloudFront にアップロードしたときに作成し、プロファイルで指定したキー名です。同じ値をここで使用します。
-
ALGORITHM: CloudFront では暗号化アルゴリズムとして
RSA/ECB/OAEPWithSHA-256AndMGF1Padding
が使用されるため、データの復号化には同じアルゴリズムを使用する必要があります。
-
-
暗号テキストを入力として以下のサンプルプログラムを実行すると、復号化されたデータがコンソールに出力されます。詳細については、 Encryption SDK の「Java サンプルコードAWS」を参照してください。
サンプルコード
import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Base64; import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoResult; import com.amazonaws.encryptionsdk.jce.JceMasterKey; /** * Sample example of decrypting data that has been encrypted by CloudFront field-level encryption. */ public class DecryptExample { private static final String PRIVATE_KEY_FILENAME = "private_key.der"; private static final String PUBLIC_KEY_FILENAME = "public_key.der"; private static PublicKey publicKey; private static PrivateKey privateKey; // CloudFront uses the following values to encrypt data, and your origin must use same values to decrypt it. // In your own code, for PROVIDER_NAME, use the provider name that you specified when you created your field-level // encryption profile. This sample uses 'DEMO' for the value. private static final String PROVIDER_NAME = "DEMO"; // In your own code, use the key name that you specified when you added your public key to CloudFront. This sample // uses 'DEMOKEY' for the key name. private static final String KEY_NAME = "DEMOKEY"; // CloudFront uses this algorithm when encrypting data. private static final String ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"; public static void main(final String[] args) throws Exception { final String dataToDecrypt = args[0]; // This sample uses files to get public and private keys. // In practice, you should distribute the public key and save the private key in secure storage. populateKeyPair(); System.out.println(decrypt(debase64(dataToDecrypt))); } private static String decrypt(final byte[] bytesToDecrypt) throws Exception { // You can decrypt the stream only by using the private key. // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); // 2. Instantiate a JCE master key final JceMasterKey masterKey = JceMasterKey.getInstance( publicKey, privateKey, PROVIDER_NAME, KEY_NAME, ALGORITHM); // 3. Decrypt the data final CryptoResult <byte[], ? > result = crypto.decryptData(masterKey, bytesToDecrypt); return new String(result.getResult()); } // Function to decode base64 cipher text. private static byte[] debase64(final String value) { return Base64.decodeBase64(value.getBytes()); } private static void populateKeyPair() throws Exception { final byte[] PublicKeyBytes = Files.readAllBytes(Paths.get(PUBLIC_KEY_FILENAME)); final byte[] privateKeyBytes = Files.readAllBytes(Paths.get(PRIVATE_KEY_FILENAME)); publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(PublicKeyBytes)); privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes)); } }