[APIGateway.2] API ゲートウェイRESTAPIステージは、バックエンド認証にSSL証明書を使用するように設定する必要があります を CloudFormation Guard でチェックする
こんにちは!クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。
みなさん CloudFormation テンプレートをデプロイする前に、 Security Hub の検知項目に引っかかっていないか、チェックしたいなぁと思ったことはありますでしょうか。
そういった時に、役に立つのが CloudFormation Guard や cfn-nag、Trivy、Snyk IaC などです。
AWS Foundational Security Best Practices v1.0.0 (FSBP) 標準に準拠したいケースもあるのではないでしょうか。(私です。)
そこで、今回は API ゲートウェイRESTAPIステージは、バックエンド認証にSSL証明書を使用するように設定する必要があります
を CloudFormation Guard で表現してみます。
コントロールについて
今回のコントロールは REST API のステージに、クライアント証明書を設定しているかどうかをチェックするコントロールです。
設定することで、バックエンドでは API Gateway からのリクエストであるかどうかをクライアント証明書から判断できます。
個人的には少し大掛かりな気がしますが、業界や求められるセキュリティレベルによっては必要になるケースもあるのではないでしょうか。
このコントロールは、Amazon API Gateway RESTAPIステージにSSL証明書が設定されているかどうかを確認します。バックエンドシステムは、これらの証明書を使用して、受信リクエストが API Gateway からのものであることを認証します。
API ゲートウェイRESTAPIステージは、バックエンドシステムがリクエストが API Gateway から発信されたことを認証SSLできるように証明書で設定する必要があります。
作成したコード
作成したコードは以下になります。
#################################################
# API Gateway.02
#################################################
# [APIGateway.2] API Gateway REST API stages should be configured to use SSL certificates for backend authentication
# Control URL: https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html#apigateway-2
#
# Category: Protect > Data Protection > Encryption of data-in-transit
# Severity: Medium
# Resource type: AWS::ApiGateway::Stage
# AWS Config rule: api-gw-ssl-enabled
# Config Rule URL: https://docs.aws.amazon.com/config/latest/developerguide/api-gw-ssl-enabled.html
let api_gw_ssl_enabled = Resources.*[ Type == 'AWS::ApiGateway::Stage'
Metadata.guard.SuppressedRules not exists or
Metadata.guard.SuppressedRules.* != "API_GW_SSL_ENABLED"
]
# AWS::ApiGateway::Stage
rule api_gw_ssl_enabled_check when %api_gw_ssl_enabled !empty {
%api_gw_ssl_enabled.Properties {
# ClientCertificateId が存在するかチェック
ClientCertificateId exists
<<
RuleID: APIGateway.2
Category: Protect > Data Protection > Encryption of data-in-transit
Severity: Medium
Resource type: AWS::ApiGateway::Stage
Description: This control checks whether Amazon API Gateway REST API stages have SSL certificates configured. Backend systems use these certificates to authenticate that incoming requests are from API Gateway.
>>
# ClientCertificateId が存在し、文字列が設定されているかチェック
when ClientCertificateId exists {
ClientCertificateId is_string
<<
RuleID: APIGateway.2
Category: Protect > Data Protection > Encryption of data-in-transit
Severity: Medium
Resource type: AWS::ApiGateway::Stage
Description: This control checks whether Amazon API Gateway REST API stages have SSL certificates configured. Backend systems use these certificates to authenticate that incoming requests are from API Gateway.
>>
}
}
}
証明書の設定について
クライアント証明書の設定は AWS::ApiGateway::Stage
の ClientCertificateId
で行います。
Resources:
Prod:
Type: AWS::ApiGateway::Stage
Properties:
StageName: Prod
Description: Prod Stage
RestApiId: !Ref MyRestApi
DeploymentId: !Ref TestDeployment
DocumentationVersion: !Ref MyDocumentationVersion
ClientCertificateId: !Ref ClientCertificate
Variables:
Stack: Prod
MethodSettings:
- ResourcePath: /
HttpMethod: GET
MetricsEnabled: 'true'
DataTraceEnabled: 'false'
- ResourcePath: /stack
HttpMethod: POST
MetricsEnabled: 'true'
DataTraceEnabled: 'false'
ThrottlingBurstLimit: '999'
- ResourcePath: /stack
HttpMethod: GET
MetricsEnabled: 'true'
DataTraceEnabled: 'false'
ThrottlingBurstLimit: '555'
そのため、AWS::ApiGateway::Stage
の ClientCertificateId
が存在するか、存在している場合、求められている型と一致するかどうかがチェックロジックになります。(非常にシンプルですね。)
# AWS::ApiGateway::Stage
rule api_gw_ssl_enabled_check when %api_gw_ssl_enabled !empty {
%api_gw_ssl_enabled.Properties {
# ClientCertificateId が存在するかチェック
ClientCertificateId exists
<<
RuleID: APIGateway.2
Category: Protect > Data Protection > Encryption of data-in-transit
Severity: Medium
Resource type: AWS::ApiGateway::Stage
Description: This control checks whether Amazon API Gateway REST API stages have SSL certificates configured. Backend systems use these certificates to authenticate that incoming requests are from API Gateway.
>>
# ClientCertificateId が存在し、文字列が設定されているかチェック
when ClientCertificateId exists {
ClientCertificateId is_string
<<
RuleID: APIGateway.2
Category: Protect > Data Protection > Encryption of data-in-transit
Severity: Medium
Resource type: AWS::ApiGateway::Stage
Description: This control checks whether Amazon API Gateway REST API stages have SSL certificates configured. Backend systems use these certificates to authenticate that incoming requests are from API Gateway.
>>
}
}
}
テストしてみる
次のテストコードを用意してみました。
# api-gw-ssl-enabled.yaml
---
# テストケース1: 空のテンプレート
# 期待値: SKIP - リソースが存在しないため、ルールはスキップされる
- name: Empty template
input: {}
expectations:
rules:
api_gw_ssl_enabled_check: SKIP
# テストケース2: 空のリソースセクション
# 期待値: SKIP - 評価対象のリソースが存在しないため、ルールはスキップされる
- name: Empty resources
input:
Resources: {}
expectations:
rules:
api_gw_ssl_enabled_check: SKIP
# テストケース3: 有効なClientCertificateId設定
# 期待値: PASS - ClientCertificateIdが有効な文字列として設定されているため
- name: Valid ClientCertificateId
input:
Resources:
MyApiStage:
Type: AWS::ApiGateway::Stage
Properties:
ClientCertificateId: "abc123"
RestApiId: !Ref MyRestApi
StageName: prod
expectations:
rules:
api_gw_ssl_enabled_check: PASS
# テストケース4: ClientCertificateId未設定
# 期待値: FAIL - 必須のClientCertificateIdが設定されていないため
- name: Missing ClientCertificateId
input:
Resources:
MyApiStage:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId: !Ref MyRestApi
StageName: prod
expectations:
rules:
api_gw_ssl_enabled_check: FAIL
# テストケース5: ルール抑制設定
# 期待値: SKIP - Metadataでルールが明示的に抑制されているため
- name: Rule suppressed
input:
Resources:
MyApiStage:
Type: AWS::ApiGateway::Stage
Metadata:
guard:
SuppressedRules:
- "API_GW_SSL_ENABLED"
Properties:
RestApiId: !Ref MyRestApi
StageName: prod
expectations:
rules:
api_gw_ssl_enabled_check: SKIP
# テストケース6: 数値型のClientCertificateId
# 期待値: FAIL - ClientCertificateIdは文字列型である必要があるため
- name: Non-string ClientCertificateId
input:
Resources:
MyApiStage:
Type: AWS::ApiGateway::Stage
Properties:
ClientCertificateId: 12345
RestApiId: !Ref MyRestApi
StageName: prod
expectations:
rules:
api_gw_ssl_enabled_check: FAIL
# テストケース7: 複数のステージ(混在)
# 期待値: FAIL - 1つでも非準拠のステージが存在するため、全体としてFAIL
- name: Multiple stages with mixed compliance
input:
Resources:
CompliantStage:
Type: AWS::ApiGateway::Stage
Properties:
ClientCertificateId: "abc123"
RestApiId: !Ref MyRestApi1
StageName: prod
NonCompliantStage:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId: !Ref MyRestApi2
StageName: dev
expectations:
rules:
api_gw_ssl_enabled_check: FAIL
# テストケース8: 配列型のClientCertificateId
# 期待値: FAIL - ClientCertificateIdは単一の文字列である必要があるため
- name: Array type ClientCertificateId
input:
Resources:
MyApiStage:
Type: AWS::ApiGateway::Stage
Properties:
ClientCertificateId: ["cert1", "cert2"]
RestApiId: !Ref MyRestApi
StageName: prod
expectations:
rules:
api_gw_ssl_enabled_check: FAIL
# テストケース9: オブジェクト型のClientCertificateId
# 期待値: FAIL - ClientCertificateIdは文字列型である必要があるため
- name: Object type ClientCertificateId
input:
Resources:
MyApiStage:
Type: AWS::ApiGateway::Stage
Properties:
ClientCertificateId:
id: "cert123"
RestApiId: !Ref MyRestApi
StageName: prod
expectations:
rules:
api_gw_ssl_enabled_check: FAIL
うまくテストケース通り通過していますね。
takakuni@ rules % cfn-guard test -r api_gateway/api-gw-ssl-enabled.guard -t api_gateway/tests/api_gateway/api-gw-ssl-enabled.yaml
Test Case #1
Name: Empty template
PASS Rules:
api_gw_ssl_enabled_check: Expected = SKIP
Test Case #2
Name: Empty resources
PASS Rules:
api_gw_ssl_enabled_check: Expected = SKIP
Test Case #3
Name: Valid ClientCertificateId
PASS Rules:
api_gw_ssl_enabled_check: Expected = PASS
Test Case #4
Name: Missing ClientCertificateId
PASS Rules:
api_gw_ssl_enabled_check: Expected = FAIL
Test Case #5
Name: Rule suppressed
PASS Rules:
api_gw_ssl_enabled_check: Expected = SKIP
Test Case #6
Name: Non-string ClientCertificateId
PASS Rules:
api_gw_ssl_enabled_check: Expected = FAIL
Test Case #7
Name: Multiple stages with mixed compliance
PASS Rules:
api_gw_ssl_enabled_check: Expected = FAIL
Test Case #8
Name: Array type ClientCertificateId
PASS Rules:
api_gw_ssl_enabled_check: Expected = FAIL
Test Case #9
Name: Object type ClientCertificateId
PASS Rules:
api_gw_ssl_enabled_check: Expected = FAIL
まとめ
以上、「[APIGateway.2] API ゲートウェイRESTAPIステージは、バックエンド認証にSSL証明書を使用するように設定する必要があります
を CloudFormation Guard でチェックする」でした。
昨日、 API Gateway.01 を出してみたのですが、いよいよシリーズ化しそうです。
少しずつ積み重なって、完成したら嬉しいですね。
クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!