Amazon Inspectorの実行結果をDynamoDBに入れる


cloudpack大阪の佐々木です。

以前、Amazon Inspectorの実行までを書きました。
http://qiita.com/taishin/items/0fa3a24b60ff289aee4d

現状、実行結果がコンソールで見ないといけない、CSVエクスポートはできるけど項目が少ない、通知機能がないとか、使い勝手が悪いので、
実行したら自動でDynamoDBに放り込むようにスクリプトを作りました。

手順

下記を参考に、7.テンプレートまで作成します。
http://qiita.com/taishin/items/0fa3a24b60ff289aee4d

テンプレートのARNを控えます。

スクリプトはこんな感じです。

inspector.rb
require 'aws-sdk'

REGION = 'ap-northeast-1'
DYNAMO_TABLE_NAME = 'Inspector_result'
TEMPLATE_ARN = ARGV[0]

def start_assessment(client, arn, name)
  run_arn = client.start_assessment_run({
    assessment_template_arn: arn,
    assessment_run_name: name,
  }).assessment_run_arn
  return run_arn
end

def put_findings(client, arn, dynamo_client)
  list = client.list_findings({
    assessment_run_arns:[arn],
  })
  desc_finding(client, list.finding_arns, dynamo_client)
  next_token=list.next_token
  while true
    next_list = client.list_findings({
      assessment_run_arns:[arn],
      next_token: next_token
    })
    desc_finding(client, next_list.finding_arns, dynamo_client)
    if next_list.next_token
      next_token = next_list.next_token
    else
      break
    end
  end
end


def desc_finding(client, arns, dynamo_client)
  finds = client.describe_findings({
    finding_arns: arns
  })[0]
  finds.each do |find|
    data = Hash.new
    data["agentId"] = find.asset_attributes.agent_id
    data["assetType"] = find.asset_type
    data["hostname"] = find.asset_attributes.hostname
    data["ipv4Addresses"] = find.asset_attributes.ipv4_addresses[0]
    data["autoScalingGroup"] = find.asset_attributes.auto_scaling_group
    data["createdAt"] = find.created_at.to_s
    data["updatedAt"] = find.updated_at.to_s
    data["severity"] = find.severity
    data["indicatorOfCompromise"] = find.indicator_of_compromise
    data["numericSecerity"] = find.numeric_severity
    data["id"] = find.id
    data["title"] = find.title
    data["description"] = find.description
    data["recommendation"] = find.recommendation
    data["arn"] = find.arn
    data["rulePackageName"] = client.describe_rules_packages({
      rules_package_arns: [find.service_attributes.rules_package_arn]
    }).rules_packages[0].name
    put_into_dynamo(data, dynamo_client)
  end
end

def put_into_dynamo(data, client)
  client.put_item({
    table_name: DYNAMO_TABLE_NAME,
    item: {
      "arn" => data["arn"],
      "agentId" => data["agentId"],
      "assetType" => data["assetType"],
      # "hostname" => data["hostname"],
      # "ipv4Addresses" => data["ipv4Addresses"],
      # "autoScalingGroup" => data["autoScalingGroup"],
      "severity" => data["severity"],
      "indicatorOfCompromise" => data["indicatorOfCompromise"],
      "numericSecerity" => data["numericSecerity"],
      "rulePackageName" => data["rulePackageName"],
      "id" => data["id"],
      "title" => data["title"],
      "description" => data["description"],
      "recommendation" => data["recommendation"],
      "createdAt" => data["createdAt"],
      "updatedAt" => data["updatedAt"]
    }
  })
end

###############



if ARGV.size != 1
  puts "usage: " + $0 + " (Template ARN)"
  exit(1)
end

inspector = Aws::Inspector::Client.new(
  region: REGION
)

dynamo = Aws::DynamoDB::Client.new(
  region: REGION
)

run_name = "inspector_run_" + Time.now.to_s

run_arn = start_assessment(inspector, TEMPLATE_ARN, run_name)

while true
  assess_state = inspector.describe_assessment_runs({
    assessment_run_arns: [run_arn], 
  }).assessment_runs[0].state
  break if assess_state == "COMPLETED"
  sleep(300)
end

put_findings(inspector, run_arn, dynamo)

実行の終了をどうやって判断すればいいか分からなかったので、とりあえず5分ごとにステータスを確認して、COMPLETEDになっているかを確認しています。

テンプレートARNを引数にスクリプトを実行します。

ruby inspector.rb arn:aws:inspector:ap-northeast-1:XXXXXXXXXXXX:target/XXXXXXXXXX/template/XXXXXXXXXXX

うまくいくとこんな感じでインポートされます。

まとめ

Dynamoに入ったらあとはよしなに。
好きなようにデータ引っ張ってこれるし、Lambda使って通知とかいろいろできるのではないかと思います。
なんでRubyなんだ?とか、なんでPythonでLambda化しないんだ?とかいうツッコミはなしでお願いしますw