この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
西澤です。先日のre:Invent 2015で発表されたAWS Config Rules。Preview申し込みも通ったので、ドキュメントで紹介されていたサンプルを試してみました。下記記事もぜひ合わせてご覧ください。
- 【速報】「AWS Config Rules」がリリースされました!!!! #reinvent
- (レポート) SEC314: AWS Configによる設定の完全な可視化と制御/NEW LAUNCH! AWS Config Rules #reinvent
- AWS Configの拡張機能「AWS Config Rules」の要素を確認してみた #reinvent
- AWS Config Rulesのマネージドルールを試してみた。 #reinvent
やってみた内容
下記ドキュメントにサンプルが紹介されていましたので、まずはこの通りやってみました。注意事項などを整理しながらご紹介したいと思います。
Getting Started with Custom Rules (Node.js)
- カスタムルール用のLambdaファンクションを作成
- AWS Configにカスタムルールを作成
カスタムルール用のLambdaファンクションを作成
サンプルコード
まずは、下記ページからzipファイルをそのままダウンロードしてきます。
- samples/InstanceTypeCheck_ConfigRuleSample.zip
- config-2014-11-12.normal.json
- InstanceTypeCheck.js
中に謎のjsonファイルが含まれています。どうやらAWS Config APIを利用する為に必要となるLibrary情報等が定義されている必須のファイルのようで、zipに含めてアップロードする必要があります。今後SDKがバージョンアップされれば不要となるのかもしれません。
InstanceTypeCheck.js
が、Lambdaから実行される実体のコードですので、こちらを覗いてみます。
var aws = require('aws-sdk');
// Include the Pre-release SDK explicitly. Once this is released into the AWS SDK, this step is not required
var config = new aws.Service({
apiConfig: require('./config-2014-11-12.normal.json'),
region: 'us-east-1'
});
// This is where its determined whether the resource is compliant or not.
// In this example, we simply decide that the resource is compliant if is an Instance and its type matches the type specified as the desired type
// If the resource is not an Instance, then we deem this resource to not be applicable (if the scope of the rule is specified to only include
// Instances, this rule would never have been invoked )
function evaluateCompliance(configurationItem, ruleParameters) {
if(configurationItem.resourceType !== 'AWS::EC2::Instance')
return 'NOT_APPLICABLE';
if(configurationItem.configuration.instanceType === ruleParameters.desiredInstanceType)
return 'COMPLIANT';
else return 'NON_COMPLIANT';
}
// Check whether the we're being invoked for this resource because its been deleted. If it has, then its not applicable to be evaluated
function isApplicable(configurationItem) {
var status = configurationItem.configurationItemStatus;
return status === 'OK' || status === 'ResourceDiscovered';
}
// This is the handler that's invoked by Lambda
// Most of this code is boiler-plate, use as is
exports.handler = function(event, context) {
var invokingEvent = JSON.parse(event.invokingEvent);
var ruleParameters = JSON.parse(event.ruleParameters);
var compliance = 'NOT_APPLICABLE';
if (isApplicable(invokingEvent.configurationItem))
compliance = evaluateCompliance(invokingEvent.configurationItem, ruleParameters, context); // Invoke the compliance checking function.
// Put together the request that reports the evaluation status
// Note that we're choosing to report this evaluation against the resource that was passed in.
// You can choose to report this against any other resource type, as long as it is supported by ConfigRules
var putEvaluationsRequest = {
Evaluations: [
{
ComplianceResourceType: invokingEvent.configurationItem.resourceType,
ComplianceResourceId: invokingEvent.configurationItem.resourceId,
ComplianceType: compliance,
OrderingTimestamp: invokingEvent.configurationItem.configurationItemCaptureTime
}
],
ResultToken: event.resultToken
};
// Invoke the Config API to report the result of the evaluation
config.putEvaluations(putEvaluationsRequest, function (err, data) {
if (err) {
context.fail(err);
} else {
context.succeed(data);
}
});
};
カスタムルールを開発していく上で、共通部分となるところはconfig.putEvaluations
で、各設定がcompliant(ルールに即した設定となっている)かどうかを判定した結果を返す処理になります。今回は、EC2インスタンスのインスタンスタイプがcompliantであるかどうかを判定するサンプルになります。
Lambdaファンクション作成
ドキュメントの通りにLambdaファンクションを作成します。
Lambda実行用IAMロール作成
Lambdaファンクション作成の際に、割り当てるIAMロールを作成します(事前作成も可能ですが)。通常のLambda用に最低限定義されている"Basic execution role"に加えて、config:PutEvaluations
の権限が追加で必要となる点にご注意ください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"config:PutEvaluations"
],
"Resource": "*"
}
]
}
Lambdaの実行テスト
ドキュメントでは、Input sample eventも用意されていました。自分で開発したときは、これを用意するのがなかなか大変だったりしたので、なんて親切なんだ!と思って実行してみたのですが。。。
真っ赤な文字だらけ。AWS Configから実行された場合だけ成功するので、InvalidResultTokenException
で良いそうです。"not authorized to perform: config:PutEvaluations."が出たら、権限不足とのことなので、これを信じて先に進みましょう。
LambdaファンクションへのAWS Configからの実行権限付与
Lambdaファンクションにリソースベースで権限を付ける必要があるとのこと。AWS Management Consoleでは見当たらなかったので、Lambdaファンクションに権限を付けて制御できることは、ここで初めて知りました。AWS ConfigがこのLambdaファンクションを実行できるように設定しておきます。
$ aws lambda add-permission \
--function-name InstanceTypeCheck \
--statement-id "AddConfigPermission" \
--action lambda:InvokeFunction \
--principal config.amazonaws.com
{ "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-1:<AWS ACCOUNT ID>:function:InstanceTypeCheck\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"config.amazonaws.com\"},\"Sid\":\"AddConfigPermission\"}],\"Id\":\"default\"}" }
$ aws lambda get-policy \
--function-name InstanceTypeCheck
{ "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-1:<AWS ACCOUNT ID>:function:InstanceTypeCheck\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"config.amazonaws.com\"},\"Sid\":\"AddConfigPermission\"}],\"Id\":\"default\"}" }
AWS Configにカスタムルールを作成
こちらもドキュメントの通りにやってみましょう。
ここで、Lambdaに登録したスクリプト内にある外部パラメータを指定して、判定を行っています。
- Key=desiredInstanceType
- Value=t2.micro
AWS Configの作成はとてもシンプルですね。
テスト
いよいよテストです。試しに、t2.microとt2.smallをそれぞれ1台ずつ起動してみました。
1台が"Compliant"、もう1台が"Noncopliant"で画面表示されました!
まとめ
今回はサンプルを利用してAWS Config Rulesのカスタムルールを試してみました。CloudTrailとごちゃ混ぜになってしまっていたのですが、AWS Configの武器は過去の状態を追跡できること、ということを再認識しました。あとLambdaももっとトレーニングを積まないといけないですね。
今後もAWS Configの特徴を生かしたカスタムルールを考えて行きたいと思います。AWS Config Rulesの正式リリースが待たれます。