[JAWS-UG CLI] #91 Amazon Inspector入門 (9) : Inspector実行用Lambda function作成


AWS CLIを利用して、Inspectorを定期実行するLambda functionを作成して実行します

# 本記事について
本記事はJAWS-UG CLI専門支部の実施する予定だったハンズオン手順書です。
Lambdaでスケジュール実行するための手順でしたが、CloudWatch Eventから直接スケジュール実行が可能になったためこちらは廃止としました。

最新の全工程については下記総合案内をご確認ください。
[#91 Amazon Inspector 入門 (CloudWatch Eventで定期診断編)](http://qiita.com/tcsh/items/b55eee599ae2c8806e4f#91-inspector-%E5%85%A5%E9%96%80-cloudwatch-event%E3%81%A7%E5%AE%9A%E6%9C%9F%E8%A8%BA%E6%96%AD%E7%B7%A8)

前提条件
========


Lambdaへの権限
-----------

Lambdaに対してフル権限があること。


AWS CLIのバージョン
-------------------

以下のバージョンで動作確認済

- AWS CLI 1.11.122

```bash:コマンド:
aws --version
```

結果(例):

     aws-cli/1.11.122 Python/2.7.10 Linux/4.1.27-25.49.amzn1.x86_64 botocore/1.5.85

バージョンが古い場合は最新版に更新しましょう。

```bash:コマンド:
sudo -H pip install -U awscli
```


0. 準備
=======

まず変数の確認をします。

```bash:変数の確認:
cat << ETX

        AWS_DEFAULT_PROFILE: (0.1) ${AWS_DEFAULT_PROFILE}
        IAM_ROLE_NAME        (0.2) ${IAM_ROLE_NAME}
        IAM_ROLE_ARN         (0.3) ${IAM_ROLE_ARN}

ETX
```

結果(例):

        AWS_DEFAULT_PROFILE: (0.1) 
        IAM_ROLE_NAME        (0.2) lambda_inspector_role
        IAM_ROLE_ARN         (0.3) arn:aws:iam::xxxx:role/lambda_inspector_role

変数が入っていない、適切でない場合は、それぞれの手順番号について作業を
行います。


0.1. プロファイルの指定
-----------------------

プロファイルの一覧を確認します。

```bash:コマンド:
cat ~/.aws/credentials \
       | grep '\[' \
       | sed 's/\[//g' | sed 's/\]//g'
```

結果(例):

      iamFull-prjz-mbpr13
      <IAMのフル権限を許可されたプロファイル>

```bash:変数の設定:
export AWS_DEFAULT_PROFILE='<IAMのフル権限を許可されたプロファイル>'
```


0.2. IAMロール名の指定
----------------------

```bash:変数の設定:
IAM_ROLE_NAME='inspector_role'
```


0.3. IAMロールARNの指定
----------------------------

IAMロールのARN確認
---------------
```bash:コマンド:
IAM_ROLE_ARN=$( \
        aws iam get-role \
          --role-name ${IAM_ROLE_NAME} \
          --query 'Role.Arn' \
          --output text \
) \
        && echo "${IAM_ROLE_ARN}"
```

結果(例):

     arn:aws:iam::xxxxx:role/lambda_inspector_role



最終確認
--------------

```bash:変数の確認:
cat << ETX

        AWS_DEFAULT_PROFILE: (0.1) ${AWS_DEFAULT_PROFILE}
        IAM_ROLE_NAME        (0.2) ${IAM_ROLE_NAME}
        IAM_ROLE_ARN     　  (0.3) ${IAM_ROLE_ARN}

ETX
```

結果(例):

        AWS_DEFAULT_PROFILE: (0.1) 
        IAM_ROLE_NAME        (0.2) lambda_inspector_role
        IAM_ROLE_ARN         (0.3) arn:aws:iam::5xxxxx:role/lambda_inspector_role


 本作業
===========
1.1.lambdafunction名指定
-----------------------

```bash:コマンド:
LAMBDA_FUNC_NAME='inspector-lambda'
FILE_LAMBDA_FUNC="${LAMBDA_FUNC_NAME}.js"
```

結果:

      (戻り値なし)


1.2.lambdafunction名確認
-----------------------
```bash:コマンド:
cat << ETX

  FILE_LAMBDA_FUNC:        ${FILE_LAMBDA_FUNC}
　ASSESSMENT_TEMPLATE_ARN: ${ASSESSMENT_TEMPLATE_ARN}

ETX

```

結果(例):

      FILE_LAMBDA_FUNC:        inspector-lambda.js
    　ASSESSMENT_TEMPLATE_ARN: arn:aws:inspector:ap-northeast-1:xxxxxxx:target/0-ZVbpDP3K/template/0-YZMRHdpp

1.3.lambdafunctionファイル設定

```bash:コマンド:
cat << EOF > ${FILE_LAMBDA_FUNC}
'use strict';
const AWS = require('aws-sdk');

const inspector = new AWS.Inspector();

const params = {
    assessmentTemplateArn: "${ASSESSMENT_TEMPLATE_ARN}",
};

exports.handler = (event, context, callback) => {
    try {
        // Inspector.StartAssessmentRun response will look something like:
        // {"assessmentRunArn":"${ASSESSMENT_TEMPLATE_ARN}"
        inspector.startAssessmentRun(params, (error, data) => {
            if (error) {
                console.log(error, error.stack);
                return callback(error);
            }

            console.log(data);
            return callback(null, data);
        });
    } catch (error) {
        console.log('Caught Error: ', error);
        callback(error);
    }
};
EOF

cat ${FILE_LAMBDA_FUNC}
```

結果(例):

     'use strict';
     const AWS = require('aws-sdk');
     
     const inspector = new AWS.Inspector();
     
     const params = {
         assessmentTemplateArn: "arn:aws:inspector:ap-northeast-1:549352348160:target/0-ZVbpDP3K/template/0-YZMRHdpp",
     };
     
     exports.handler = (event, context, callback) => {
         try {
             // Inspector.StartAssessmentRun response will look something like:
             // {"assessmentRunArn":"arn:aws:inspector:ap-northeast-1:549352348160:target/0-ZVbpDP3K/template/0-YZMRHdpp"
             inspector.startAssessmentRun(params, (error, data) => {
                 if (error) {
                     console.log(error, error.stack);
                     return callback(error);
                 }
     
                 console.log(data);
                 return callback(null, data);
             });
         } catch (error) {
             console.log('Caught Error: ', error);
             callback(error);
         }
     };


```bash:コマンド:
zip ${LAMBDA_FUNC_NAME}.zip ${FILE_LAMBDA_FUNC}
```

結果(例):

       adding: inspector-lambda.js (deflated 56%)


2.1.lambdafunction用変数指定
------------------------

```bash:コマンド:
LAMBDA_FUNC_DESC='Schedules a recurring Amazon Inspector assessment run'
LAMBDA_RUNTIME='nodejs4.3'
LAMBDA_HANDLER="${LAMBDA_FUNC_NAME}.handler"
FILE_LAMBDA_ZIP="${LAMBDA_FUNC_NAME}.zip"
```

2.2.設定用変数の確認
-------------------

```bash:コマンド:
cat << ETX

        LAMBDA_FUNC_NAME:  ${LAMBDA_FUNC_NAME}
        LAMBDA_FUNC_DESC:  "${LAMBDA_FUNC_DESC}"
        LAMBDA_RUNTIME:    ${LAMBDA_RUNTIME}
        IAM_ROLE_ARN:      ${IAM_ROLE_ARN}
        LAMBDA_HANDLER:    ${LAMBDA_HANDLER}
        FILE_LAMBDA_ZIP    ${FILE_LAMBDA_ZIP}

ETX
```

結果(例):

        LAMBDA_FUNC_NAME:  inspector-lambda
        LAMBDA_FUNC_DESC:  "Schedules a recurring Amazon Inspector assessment run"
        LAMBDA_RUNTIME:    nodejs4.3
        IAM_ROLE_ARN:      arn:aws:iam::549352348160:role/lambda_inspector_role
        LAMBDA_HANDLER:    inspector-lambda.handler
        FILE_LAMBDA_ZIP    inspector-lambda.zip


2.3.lambdafunction作成
-------------------

```bash:コマンド:
aws lambda create-function \
        --function-name ${LAMBDA_FUNC_NAME} \
        --description "${LAMBDA_FUNC_DESC}" \
        --zip-file fileb://${FILE_LAMBDA_ZIP} \
        --runtime ${LAMBDA_RUNTIME} \
        --role ${IAM_ROLE_ARN} \
        --handler ${LAMBDA_HANDLER}
```

結果(例):

       {
           "TracingConfig": {
               "Mode": "PassThrough"
           },
           "CodeSha256": "FvWrbSR1JNa3VXNC2uB3ibyjimxxxxxxx",
           "FunctionName": "inspector-lambda",
           "CodeSize": 567,
           "MemorySize": 128,
           "FunctionArn": "arn:aws:lambda:ap-northeast-1:xxxx:function:inspector-lambda",
           "Version": "$LATEST",
           "Role": "arn:aws:iam::549352348160:role/lambda_inspector_role",
           "Timeout": 3,
           "LastModified": "2017-07-24T06:47:34.517+0000",
           "Handler": "inspector-lambda.handler",
           "Runtime": "nodejs4.3",
           "Description": "Schedules a recurring Amazon Inspector assessment run"
       }


2.3.lambdafunction確認
-------------------

```bash:コマンド:
aws lambda get-function \
        --function-name ${LAMBDA_FUNC_NAME}
```

結果(例):

     {
         "Code": {
             "RepositoryType": "S3",
             "Location": "https://awslambda-ap-nxxxxxxxxxxxx"
         },
         "Configuration": {
             "TracingConfig": {
                 "Mode": "PassThrough"
             },
             "Version": "$LATEST",
             "CodeSha256": "FvWrbSR1JNa3VXNC2uB3ibyjimWyEzzzzzzzz",
             "FunctionName": "inspector-lambda",
             "MemorySize": 128,
             "CodeSize": 567,
             "FunctionArn": "arn:aws:lambda:ap-northeast-1:5493xxxx:function:inspector-lambda",
             "Handler": "inspector-lambda.handler",
             "Role": "arn:aws:iam::54935x2xxxxxxxx:role/lambda_inspector_role",
             "Timeout": 3,
             "LastModified": "2017-07-24T06:47:34.517+0000",
             "Runtime": "nodejs4.3",
             "Description": "Schedules a recurring Amazon Inspector assessment run"
         }
     }


```bash:コマンド:
aws lambda get-function-configuration \
        --function-name ${LAMBDA_FUNC_NAME}
```

結果(例):

     {
         "TracingConfig": {
             "Mode": "PassThrough"
         },
         "CodeSha256": "FvWrbSR1JNa3VXNC2uB3ibyjimWyE4r+gPvFtI1R1jQ=",
         "FunctionName": "inspector-lambda",
         "CodeSize": 567,
         "MemorySize": 128,
         "FunctionArn": "arn:aws:lambda:ap-northeast-1:54xxxxx:function:inspector-lambda",
         "Version": "$LATEST",
         "Role": "arn:aws:iam::549352348160:role/lambda_inspector_role",
         "Timeout": 3,
         "LastModified": "2017-07-24T06:47:34.517+0000",
         "Handler": "inspector-lambda.handler",
         "Runtime": "nodejs4.3",
         "Description": "Schedules a recurring Amazon Inspector assessment run"
     }

2.3.lambdafunction手動実行用変数設定
-------------------

```bash:コマンド:
FILE_OUTPUT_LAMBDA="${LAMBDA_FUNC_NAME}-out.txt" \
        && echo ${FILE_OUTPUT_LAMBDA}
```

```bash:コマンド:
cat << ETX

        LAMBDA_FUNC_NAME:   ${LAMBDA_FUNC_NAME}
        FILE_OUTPUT_LAMBDA: ${FILE_OUTPUT_LAMBDA}

ETX
```

結果(例):

        LAMBDA_FUNC_NAME:   inspector-lambda
        FILE_OUTPUT_LAMBDA: inspector-lambda-out.txt


```bash:コマンド:
FILE_LOG_LAMBDA="${LAMBDA_FUNC_NAME}-$(date +%Y%m%d%H%M%S).log" \
        && echo ${FILE_LOG_LAMBDA}

```

2.4.lambdafunction手動実行
-------------------
他の診断が実行中の場合、エラーとなりますので必ずInspectorno実行状況を確認してから実行してください。

```bash:コマンド:
aws lambda invoke \
        --function-name ${LAMBDA_FUNC_NAME} \
        --log-type Tail \
        ${FILE_OUTPUT_LAMBDA} \
        > ${FILE_LOG_LAMBDA} \
```
```bash:コマンド:
cat ${FILE_LOG_LAMBDA} \
   | jp.py 'StatusCode'
```

結果(例):

       200

200が出ていれば成功


2.6.lambdafunctionの実行結果の確認
-------------------

```bash:コマンド:
cat ${FILE_OUTPUT_LAMBDA}
```

結果(例):

     {"assessmentRunArn":"arn:aws:inspector:ap-northeast-1:549352348160:target/0-ZVbpDP3K/template/0-YZMRHdpp/run/0-9wd6AT8V"}

2.7.lambdafunctionののログの確認
-------------------

```bash:コマンド:
cat ${FILE_LOG_LAMBDA} \
        | jp.py 'LogResult' \
        | sed 's/\"//g' \
        | base64 --decode
```

結果(例):

     START RequestId: a411c2f7-703e-11e7-9f55-d756e6d26920 Version: $LATEST
     2017-07-24T07:06:41.612Z        a411c2f7-703e-11e7-9f55-d756e6d26920    { assessmentRunArn: 'arn:aws:inspector:ap-northeast-1:xxxxxxxx:target/0-ZVbpDP3K/template/0-YZMRHdpp/run/0-9wd6AT8V' }
     END RequestId: a411c2f7-703e-11e7-9f55-d756e6d26920
     REPORT RequestId: a411c2f7-703e-11e7-9f55-d756e6d26920  Duration: 1452.50 ms    Billed Duration: 1500 ms        Memory Size: 128 MB     Max Memory Used: 43 MB

2.7.Inspectorの実行結果の確認
-------------------
```bash:コマンド:
ASSESSMENT_RUN_ARN=`cat ${FILE_OUTPUT_LAMBDA}|awk -F\" '{print $4}'`
aws inspector describe-assessment-runs \
   --assessment-run-arns ${ASSESSMENT_RUN_ARN}
```

結果(例):

     {
         "failedItems": {},
         "assessmentRuns": [
             {
                 "dataCollected": true,
                 "name": "template-security-15m/2017-07-24T07:06/zcoQ",
                 "completedAt": 1500880986.637,
                 "userAttributesForFindings": [],
                 "stateChanges": [
                     {
                         "state": "CREATED",
                         "stateChangedAt": 1500880001.32
                     },
                     {
                         "state": "START_DATA_COLLECTION_PENDING",
                         "stateChangedAt": 1500880001.428
                     },
                     {
                         "state": "START_DATA_COLLECTION_IN_PROGRESS",
                         "stateChangedAt": 1500880001.502
                     },
                     {
                         "state": "COLLECTING_DATA",
                         "stateChangedAt": 1500880001.617
                     },
                     {
                         "state": "STOP_DATA_COLLECTION_PENDING",
                         "stateChangedAt": 1500880901.809
                     },
                     {
                         "state": "DATA_COLLECTED",
                         "stateChangedAt": 1500880965.342
                     },
                     {
                         "state": "START_EVALUATING_RULES_PENDING",
                         "stateChangedAt": 1500880965.55
                     },
                     {
                         "state": "EVALUATING_RULES",
                         "stateChangedAt": 1500880966.067
                     },
                     {
                         "state": "COMPLETED",
                         "stateChangedAt": 1500880986.637
                     }
                 ],
                 "createdAt": 1500880001.32,
                 "findingCounts": {
                     "High": 0,
                     "Medium": 1,
                     "Informational": 0,
                     "Low": 0
                 },
                 "notifications": [],
                 "state": "COMPLETED",
                 "stateChangedAt": 1500880986.637,
                 "durationInSeconds": 900,
                 "rulesPackageArns": [
                     "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq"
                 ],
                 "startedAt": 1500880001.617,
                 "assessmentTemplateArn": "arn:aws:inspector:ap-northeast-1:549352348160:target/0-ZVbpDP3K/template/0-YZMRHdpp",
                 "arn": "arn:aws:inspector:ap-northeast-1:549352348160:target/0-ZVbpDP3K/template/0-YZMRHdpp/run/0-9wd6AT8V"
             }
         ]
     }

stateがCOMPLETEDに変わっていたら完了

2.8.診断レポートの確認
-------------------
stateがCOMPLETEDに変わってから実行します

```bash:コマンド:
aws inspector get-assessment-report \
   --assessment-run-arn ${ASSESSMENT_RUN_ARN}
   --report-file-format HTML \
   --report-type FINDING
```

結果(例):

     {
         "status": "COMPLETED",
         "url": "https://inspector-temp-reports-prod-ap-northeast-1.s3-ap-northeast-1.amazonaws.comxxxxxx"
     }

ブラウザでURLにアクセスすると診断レポートを閲覧できます