AWSCodePipelineを用いたインフラDevSecOpsについて

####やりたいこと
・AWS CloudformationをS3にアップロードすると、CI/CDパイプラインを通じてデプロイを行う。
・CI/CDパイプラインは、AWSCodePipelineとAWSLambdaで構築する。
・LambdaでEBボリュームが暗号化されているのかのチェックと
　リリースする前に、人間系の承認工程(Human Approval)を設けてDevSecOpsの環境を整備する。
※AWS Adding Security into DevOpsワークショップを参考

####構成
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/7df547cf-7151-76b6-6aab-eca74e729fb8.png">

####流れ
1.Cloudformationの開発環境としてCloud9を用意する。
2.CodePiplineを構築する。パイプライン上にセキュリティチェックと人間系の承認工程を挟む。
3.Cloud9で編集したCloudformationのテンプレートをS3バケットに投入し、パイプライン上に流す。

####前提
・AWS Account, Admin IAM Userが利用できること
・us-west-2 (Oregon) リージョンで実施

####Cloud9の用意
us-west-2 (Oregon) リージョンでCloud9を作成。
特に設定は変更せず、デフォルトのまま作成。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/0685499c-76e2-d3a7-0350-51f27e69ed4e.png">
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/b03ec12d-d701-dc8f-0724-2e7c4e0570c4.png">
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/27ba512b-edbd-7501-ddd7-cfe181d6079a.png">

起動を確認する。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/00835e93-0893-74c2-9494-69e1d3570f20.jpeg">

ワークショップで提供されているgitをcloneする。

```bash:bash
 git clone https://github.com/aws-samples/secure-pipelines-in-aws-workshop.git
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/d0b36788-31c8-4755-fd06-c6dcaf5f62ef.jpeg">

cloneできたことを確認する。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/fb1501cd-fb03-d5d9-7d0a-c264a79e9d2c.jpeg">

####S3バケットの用意
US-West-2オレゴンリージョンにs3バケットを作成する。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/5891be00-ff28-bd0e-e2a6-01c8bc7130eb.jpeg">

作成できたことを確認。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/585ad539-04b3-879e-6923-0257fc9a8333.jpeg">

git cloneでDLした２つのファイルをアップロードする。
・codepipe-AWS-devsecops.zip
・SecGuardRails.zip

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/11eb3f90-8504-9aca-668f-9778833aa05e.jpeg">

####CodePipline構築
git cloneでDLした「Pipeline.yml」を用いてCFNからCodePiplineを構築する。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/1de48448-9be8-00de-29d3-37fe016c261d.jpeg">

任意の名前をつけて、S3bucketに用意したバッケット名「devsecops-20211002」を入れる。
オプションは設定せずそのまま作成。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/0bbb55bb-373a-41d3-16aa-d0b6442ee214.jpeg">

作成後、CFNの画面からパイプラインが作成されたことを確認する。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/213a5e66-46ef-175d-56a3-6ba33950044b.jpeg">

CodePiplineを確認するとパイプラインが失敗している。S3バケットからの取得に失敗している様子。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/bdb8b72b-cb8a-0a01-fc83-611098f94ea2.jpeg">

CFNで作成されたS3バケットに「codepipe-AWS-devsecops.zip」が無いことが原因。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/a6140169-a623-3ce5-6d43-4063b3cd7b2c.jpeg">

ファイルをアップロードして、CodePiplineを確認する。成功しているのでOK。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/55404235-470a-e9c3-14fe-4e79633d557e.jpeg">

ところが、StaticCodeAnalysisが成功しているのでおかしい。パイプラインに流したEBSボリュームは暗号化されていないので、StaticCodeAnalysisのチェックに引っかかり失敗になるはず。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/0fbce5e2-49a4-56c6-8b13-4369c311cf28.jpeg">

CodePiplineを停止させる。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/01188922-2a37-b9db-1963-e58bdfd94759.jpeg">

StaticCodeAnalysisで利用するLamdaのプログラムを見ると'ruledata'の項目が機能していない様子。

```python:cfn_validate_lambda.py（変更前）
    client.put_item(
        TableName=logTable,
        Item={
            'rule' : {'S': "VolumesNotEncrypted"},
            'category' : {'S': "Volume"},
            'ruletype' : {'S': "regex"},
            'ruledata' : {'S': "^.*Encrypted.?\s*:\s*u?.?false"},
            'riskvalue' : {'N': "90"},
            'active' : {'S': "Y"}
        }
    )
```

```python:cfn_validate_lambda.py（変更後）
    client.put_item(
        TableName=logTable,
        Item={
            'rule' : {'S': "VolumesNotEncrypted"},
            'category' : {'S': "Volume"},
            'ruletype' : {'S': "regex"},
            'ruledata' : {'S': "Encrypted":"false"},
            'riskvalue' : {'N': "90"},
            'active' : {'S': "Y"}
        }
    )
```
Lamdaの画面で「Deploy」しないと反映されないので注意。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/475fba4f-0bf7-c62b-4fe3-46022295b2f1.jpeg">

再度実行すると、「StaticCodeAnalysis」で失敗となり想定通り。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/b85abc2c-064e-6976-f9c9-0be288048514.jpeg">

エラー内容(Function exception: Failed filters['VolumesNotEncrypted'])も良さそう。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/59b7c78d-6cc5-872e-196f-dc43e82fd1a1.jpeg">

codepipe-AWS-devsecopsにあるresources.jsonを修正する。"Encrypted"をfalseからtrueに変更。

```json:resources.json（変更前）
    "EC2Volume" : {
      "Type" : "AWS::EC2::Volume",
      "Properties" : {
        "Size" : "8",
        "Encrypted" : "false",
        "AvailabilityZone" : {
            "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]
              },
        "Tags" : [
          {"Key": "Name", "Value": "AWS"},
          {"Key": "LOB", "Value": "SecurityJam"}
        ]
      }
    },
```

```json:resources.json（変更後）
    "EC2Volume" : {
      "Type" : "AWS::EC2::Volume",
      "Properties" : {
        "Size" : "8",
        "Encrypted" : "true",
        "AvailabilityZone" : {
            "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]
              },
        "Tags" : [
          {"Key": "Name", "Value": "AWS"},
          {"Key": "LOB", "Value": "SecurityJam"}
        ]
      }
    },
```

Cloud9のイメージ。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/49a74ded-1b77-f11f-7c65-653b5b7e93e9.jpeg">

変更後、odepipe-AWS-devsecopsフォルダをzip化してS3バケットに再度アップロードする。
CodePiplineを見ると、TestDeploymentでエラーが発生して止まっている。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/03aecc93-bf7b-37d3-c028-47232dfaff02.jpeg">

CFNのスタック（AWS-devsecops-TestStack）がロールバックしている様子。ただ、理由が不明。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/7f484ab4-0db0-115e-e725-8dbc46c17599.jpeg">

CFNを見ると、ステータスが"UPDATE_ROLLBAK_COMPLETE"になっている。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/9c651ee5-514c-8611-c0a9-0726ce3f7961.jpeg">

ログで詳細を見ると
>Volume properties other than AutoEnableIO, type, size, and IOPS cannot be updated. Change the properties back to previous values and update the stack again.

とあり、すでに作成されたボリュームについて変更できない箇所がある旨エラーがでていた。
なので、ロールバックしているスタック（AWS-devsecops-TestStack）を削除。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/3de2f4d8-4d8b-620a-db3d-f4af24ab99e2.jpeg">

CodePiplineに戻りパイプラインを再実行すると、承認工程（ApprovalTestStack）までパイプラインが流れており良さそう。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/6b65098d-4905-16ef-48a5-eb63f69aa2a6.jpeg">

承認してパイプラインを流すと今度はProductionDeploymentでエラー発生。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/50ebc67a-ba8c-f202-7ad2-bb64f4eceadb.jpeg">

エラーを見ると、CFNが怪しい。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/ecac765d-e15b-eada-a455-18f963c39bea.jpeg">

以前、作成した同名のスタック（AWS-devsecops-ProdStack）が残っていたので削除。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/6db166bc-e964-e3d5-476c-e39e3787aa05.jpeg">

CodePiplineに戻りパイプラインを再実行すると、今度は全てのパイプラインが流れて無事成功(^ω^；)
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/a7463725-8bc0-e044-8c80-0198186662e6.jpeg">

CFNからスタックが作成されていることを確認。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/14e239e8-3fbe-1ba0-3f8e-64edac4aa38f.jpeg">

EBSボリュームもちゃんと暗号化されている。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/55edcb14-0f3a-1add-bd66-ae7e23e13ac6.jpeg">

####まとめ
AWSCodePipelineとAWSLambdaを用いたパイプライン内にセキュリティ観点のチェック工程を入れることでDecSecOpsのパイプラインを構築できた。エラー対応が多かった・・・（汗


####参考
https://devops.awssecworkshops.com/