こんにちは。SCSKのふくちーぬです。
2024/6/26時点で、Amazon InspectorのLambdaコードスキャンがPython3.12のランタイムでも動作確認できたので紹介します。
Amazon Inspector とは
Amazon Inspector は、ソフトウェアの脆弱性やネットワークの接続性について AWS ワークロード(Amazon EC2,Amazon ECR,AWS Lambda)を継続的にスキャンする脆弱性管理サービスです。
Lambda スキャンについて
種類 | 説明 |
Lambda 標準スキャン | Lambda 関数とそのレイヤー内のアプリケーションの依存関係をスキャンして、パッケージ脆弱性がないか調べます。 |
Lambda コードスキャン | 関数やレイヤー内のカスタムアプリケーションコードをスキャンして、コードの脆弱性がないか調べます。 |
検証
今回は、Lambdaコードスキャンに着目して脆弱性の検出及び修正を実施します。
Amazon Inspector の有効化
以下手順に従って、有効化しておいてください。
15日間の無料トライアル期間があります。料金は、スキャンした回数に応じて課金されますのでご留意ください。
AWS CloudFormation テンプレート
以下のテンプレートをデプロイしてください。
ここでは、脆弱性を持つコードとして機密情報をハードコーディングしています。
AWSTemplateFormatVersion: 2010-09-09
Description: For Lambda Code Scan
Parameters:
ResourceName:
Type: String
Resources:
# ------------------------------------------------------------#
# Lambda
# ------------------------------------------------------------#
Function:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub ${ResourceName}-lambda-function
Role: !GetAtt LambdaRole.Arn
Runtime: python3.12
Handler: index.lambda_handler
# Environment:
# Variables:
# AWS_SECRET_ACCESS_KEY: '{{resolve:secretsmanager:aws_secret_access_key:SecretString:sample_key::}}'
Code:
ZipFile: !Sub |
import boto3
import os
import json
def create_session_noncompliant():
import boto3
# Noncompliant: uses hardcoded secret access key.
sample_key = "AjWnyxxxxx45xxxxZxxxX7ZQxxxxYxxx1xYxxxxx"
boto3.session.Session(aws_secret_access_key=sample_key)
#def create_session_compliant():
# import boto3
# # Compliant: uses environment variable for secret access key.
# sample_key = os.environ.get("AWS_SECRET_ACCESS_KEY")
# boto3.session.Session(aws_secret_access_key=sample_key)
def lambda_handler(event, context):
create_session_noncompliant()
# create_session_compliant()
return {
'statusCode': 200,
'body': json.dumps('Hello form Lambda')
}
# ------------------------------------------------------------#
# Log Group
# ------------------------------------------------------------#
FunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/lambda/${Function}"
# ------------------------------------------------------------#
# IAM Role
# ------------------------------------------------------------#
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${ResourceName}-lambda-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
脆弱性の検出
パスワードやアクセス キーなどのアクセス資格情報を、ソース コードにハードコードしたため、脆弱性が検出されました。
ディテクターの名前を押下すると、以下のリンクに飛びます。
脆弱性が発生した箇所もピンポイントで示してくれます。
内部で生成AIが利用され自動推論と機械学習を使用してコードを評価してくれるおかげで、修復方法も一目瞭然です。
ランタイムPython3.12でも検出されることを確認できました。
提案された修正コードを利用して、Lambdaを更新していきます。
AWS Secrets Manager の作成
機密情報をテンプレート内に記載するのではなく、AWS Secrets Manager から読み取るために事前にSecretを作成しておきます。
脆弱性を持つコードの修正
以下のテンプレートを使用して、スタックを更新します。
AWSTemplateFormatVersion: 2010-09-09
Description: For Lambda Code Scan
Parameters:
ResourceName:
Type: String
Resources:
# ------------------------------------------------------------#
# Lambda
# ------------------------------------------------------------#
Function:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub ${ResourceName}-lambda-function
Role: !GetAtt LambdaRole.Arn
Runtime: python3.12
Handler: index.lambda_handler
Environment:
Variables:
SAMPLE_SECRET_ACCESS_KEY: '{{resolve:secretsmanager:aws_secret_access_key:SecretString:sample_key::}}'
Code:
ZipFile: !Sub |
import boto3
import os
import json
# def create_session_noncompliant():
# import boto3
# # Noncompliant: uses hardcoded secret access key.
# sample_key = "AjWnyxxxxx45xxxxZxxxX7ZQxxxxYxxx1xYxxxxx"
# boto3.session.Session(aws_secret_access_key=sample_key)
#def create_session_compliant():
import boto3
# Compliant: uses environment variable for secret access key.
sample_key = os.environ.get("SAMPLE_SECRET_ACCESS_KEY")
boto3.session.Session(aws_secret_access_key=sample_key)
def lambda_handler(event, context):
# create_session_noncompliant()
create_session_compliant()
return {
'statusCode': 200,
'body': json.dumps('Hello form Lambda')
}
# ------------------------------------------------------------#
# Log Group
# ------------------------------------------------------------#
FunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/lambda/${Function}"
# ------------------------------------------------------------#
# IAM Role
# ------------------------------------------------------------#
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${ResourceName}-lambda-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Amazon Inspector の確認
Amazon Inspector の検出結果画面にて、該当のLambdaが表示されていません。
無事コード脆弱性に対処することができました。
まとめ
・実環境でPython3.12についてもLambdaコードスキャンの対象として動作を確認しました。
日本語ドキュメントでは、Python3.12はサポートされていないと記述されておりますが、英語ドキュメントではサポートしている旨が記述されています。
※2024/2/21時点では、日本語ドキュメント及び英語ドキュメント双方ともPython3.11までしかサポートしておりませんでした。実環境においてもPython3.12を検証したところ、スタータス欄に”サポートされていないランタイム”と表示され、コードスキャンの対象外であることを確認済みでした。
他のランタイムについては、本検証では未確認となりますので、Amazon Inspector 及び AWS Lambda 導入時にはご自身で検証の上ご利用ください。
最後に
いかがだったでしょうか。
公式ドキュメントを英語で読むこと、きちんと動作検証をすることが重要であることを実感する良い機会になりました。
本記事が皆様のお役にたてば幸いです。
ではサウナラ~🔥