> For the complete documentation index, see [llms.txt](https://hayashier.gitbook.io/article/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hayashier.gitbook.io/article/aws/aws-misc.md).

# AWS Misc

## AWS Misc

## CodeCommitで突然403

KeyChain Accessのアプリを開き、codecommitで検索。アクセス制御でURLをマイナスで削除。

<http://docs.aws.amazon.com/ja\\_jp/codecommit/latest/userguide/troubleshooting.html#troubleshooting-macoshttps>

## Apache Spark

Exception in thread "main" java.lang.IllegalArgumentException: Field "x" does not exist.

sourceのcsvの先頭が

```
x,y
0.0,0.00112248
```

で始めないといけない。`x,y`の行が必要。

## `cfn_flip`コマンド

CloudFormationでJSONとYAMLを変換

<http://dev.classmethod.jp/cloud/aws/using-cloudformation-converting-tool-developed-by-aws/>

確認

```
$ aws dynamodb create-table --endpoint-url http://localhost:8000 --profile private --table-name sample_table \
 --attribute-definitions AttributeName=key,AttributeType=S \
 --key-schema AttributeName=key,KeyType=HASH \
 --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/sample_table",
        "AttributeDefinitions": [
            {
                "AttributeName": "key",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 1,
            "LastIncreaseDateTime": 0.0,
            "ReadCapacityUnits": 1,
            "LastDecreaseDateTime": 0.0
        },
        "TableSizeBytes": 0,
        "TableName": "sample_table",
        "TableStatus": "ACTIVE",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "key"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1488946192.292
    }
}
```

```
$ aws dynamodb describe-table --table-name sample_table --endpoint-url http://localhost:8000 --profile private
{
    "Table": {
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/sample_table",
        "AttributeDefinitions": [
            {
                "AttributeName": "key",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 1,
            "LastIncreaseDateTime": 0.0,
            "ReadCapacityUnits": 1,
            "LastDecreaseDateTime": 0.0
        },
        "TableSizeBytes": 0,
        "TableName": "sample_table",
        "TableStatus": "ACTIVE",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "key"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1488946192.292
    }
}
```

## JSからS3に直接画像のアップロード

S3のCORSの設定で以下のように記述する。

```
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://sample.jp</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>http://localhost</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
```

## 利用料金をSlackに毎日通知

1.アカウント > 設定 から `請求アラートを受け取る` を選択して請求額通知を有効化する。\
2.SlackをHookするURLを取得する。\
3.LambdaでCron設定で毎日回して以下のコードとライブラリをzipにしてアップロードする。

```
var aws = require('aws-sdk');
var url = require('url');
var https = require('https');
var hookUrl, slackChannel;
var cloudwatch = new aws.CloudWatch({region: 'us-east-1', endpoint: 'http://monitoring.us-east-1.amazonaws.com'});

hookUrl = 'https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
slackChannel = 'charge_infra';

var postMessage = function(message, callback) {
    var body = JSON.stringify(message);
    var options = url.parse(hookUrl);
    options.method = 'POST';
    options.headers = {
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(body),
    };

    var postReq = https.request(options, function(res) {
        var chunks = [];
        res.setEncoding('utf8');
        res.on('data', function(chunk) {
            return chunks.push(chunk);
        });
        res.on('end', function() {
            var body = chunks.join('');
            if (callback) {
                callback({
                    body: body,
                    statusCode: res.statusCode,
                    statusMessage: res.statusMessage
                });
            }
        });
        return res;
    });

    postReq.write(body);
    postReq.end();
};

exports.handler = function(event, context) {
    console.log('Start checking cloudwatch billing info.');

    var startDate = new Date();
    startDate.setDate(startDate.getDate() - 1);

    var params = {
        MetricName: 'EstimatedCharges',
        Namespace: 'AWS/Billing',
        Period: 86400 * 31,
        StartTime: new Date(new Date().setDate(1)),
        EndTime: new Date(),
        Statistics: ['Maximum'],
        Dimensions: [
            {
                Name: 'Currency',
                Value: 'USD'
            }
        ]
    };
    cloudwatch.getMetricStatistics(params, function(err, data) {
        if (err) {
            console.error(err, err.stack);
            context.fail("Failed to get billing metrics.");
        } else {
            console.dir(data);
            var datapoints = data['Datapoints'];
            if (datapoints.length < 1) {
                console.error("There is no billing info.");
                context.fail("There is no billing info.");
            }

            var latestData = datapoints[datapoints.length - 1];
            console.log(latestData);

            var dateString = [startDate.getFullYear(), startDate.getMonth() + 1, startDate.getDate()].join("/");
            var statusColor = "#439FE0";
            var price = Number(latestData['Maximum']);
            if (price > 70) {
                statusColor = "danger";
            } else if (price > 50) {
                statusColor = "warning";
            } else if (price > 30) {
                statusColor = "good";
            }

            var slackMessage = {
                channel: slackChannel,
                attachments: [
                    {
                        color:statusColor,
                        text:"AWS 利用料金(現在): $" + String(price)
                    }
                ]
            };

            postMessage(slackMessage, function(response) {
                if (response.statusCode < 400) {
                    console.info('Message posted successfully');
                    context.succeed();
                } else if (response.statusCode < 500) {
                    console.error("Error posting message to Slack API: " + response.statusCode + " - " + response.statusMessage);
                    context.succeed();
                } else {
                    context.fail("Server error when processing message: " + response.statusCode + " - " + response.statusMessage);
                }
            });
        }
    });
};
```

### 参考

* <http://docs.aws.amazon.com/ja\\_jp/AmazonCloudWatch/latest/monitoring/monitor\\_estimated\\_charges\\_with\\_cloudwatch.html>
* <http://qiita.com/saku/items/fc6b70a420a5c510de2b>

## AWSシークレットキーをcommitするのを防止

```
git secrets --install /path/to/project --register-aws
```

## Basic認証下のHealth checkが401が返る

2通りの方法\
1.Health check用のURLを設定\
2.PingプロトコルをTCPへ変更

```nginx.conf
  location @app {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_redirect off;

    proxy_pass http://aokiji_svr;
  }

  location = /healthcheck.txt {
    access_log off;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_pass http://aokiji_svr/healthcheck;
  }
```

```httpd.conf
<Files healthcheck.txt>
    Satisfy Any
    Allow from all
</Files>
```

<http://stackoverflow.com/questions/23921370/aws-load-balancer-with-no-health-check-or-make-it-work-with-non-200-response\\>
<http://5net.com/blog/2010/12/elb-healthcheck-with-apache-basicauth.html>

## IAMユーザで請求書が見れない

### IAMポリシーの設定

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "aws-portal:*",
            "Resource": "*"
        }
    ]
}
```

### AWS ウェブサイトへのアクセスのアクティベート

routeアカウントで、\[IAM User Access to Billing Information] の横にある \[Edit] を押してIAMユーザによる請求書情報ページへのアクティベートをする。\
<https://docs.aws.amazon.com/ja\\_jp/awsaccountbilling/latest/aboutv2/grantaccess.html>

## KMSで暗号化時にS3からダウンロードするとエラー

```bash
download failed: s3://kms-test-865011514531/test.txt to ./test_downloaded.txt An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4. You can enable AWS Signature Version 4 by running the command: 
aws configure set s3.signature_version s3v4
```

AWS Signature Version 4を有効にする

```bash
aws configure set s3.signature_version s3v4
```

## 構成図 自動作成

Hava\
<http://dev.classmethod.jp/cloud/aws/generate-aws-architecture-diagrams-automatically-with-hava/>

Cloudcraft Live\
<http://dev.classmethod.jp/cloud/cloudcraft-live/>

## SESの承認メールの送り先のメールが操作できない時

<http://dev.classmethod.jp/cloud/aws/acm-verifydomain-ses/>

* Rule setを有効化しないといけない

## S3で静的ホスティングをする場合の注意点

ホスト名とバケット名を一致させる\
バケットの作成はバケット名はAWS全てのバケット内で一意のものでないと上手くいかない

```
404 Not Found

Code: NoSuchKey
Message: The specified key does not exist.
Key: already.html
RequestId: 643FE9E94482BB5B
HostId: qcuzLKNL/XXRnOsH1pwrMaUIVR0BW1pudcV4jl6G7OE/ZwqGYLK95HCaf3R2DrtqvXCTr7DW+rQ=
An Error Occurred While Attempting to Retrieve a Custom Error Document

Code: NoSuchKey
Message: The specified key does not exist.
Key: error.html
```

## MFAデバイスを紛失した場合

AWSアカウントの場合→サポートセンターに連絡\
IAMユーザーの場合→管理者に連絡して、MFAデバイスの無効化をしてもらう

デバイスが正常に動いているようでもAWSリソースにアクセスできない場合→同期できていない可能性があるので同期し直す

### 参考

<http://docs.aws.amazon.com/ja\\_jp/IAM/latest/UserGuide/id\\_credentials\\_mfa\\_lost-or-broken.html>

## FlyData

AWS Kinesisへのエージェント型ログ収集ツール(Fluentdみたいなかんじ)\
<http://www.flydata.com/ja/resources/flydata-sync/getting-started-sync/>

## Lambdaでzipでアップロードするときの注意点

ライブラリのinstallのし忘れに注意する(※アップロードするディレクトリ内に含める)

```bash
$ pip install requests -t .
```

(参考)<http://qiita.com/Hironsan/items/0eb5578f3321c72637b4>

zip化してアップロードする

```bash
$ zip -r upload.zip *
```

### 確認方法

以下のコマンドを入力する

```bash
$ python
Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:38:48) [MSC v.1900 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from lambda_function import lambda_handler
>>> lambda_handler(None,None)
```

### 依存ライブラリの管理方法

```bash
$ cat requirements.txt
requests
$ pip install -r requirements.txt ( -t . )
```

(参考)<http://dev.classmethod.jp/cloud/deploy-aws-lambda-python-with-lambda-uploader/>

## EC2上で169.254.169.254にアクセスして、IPやホスト名、VPC情報などを取得

### インスタンスIDを取得

```bash
$ curl 169.254.169.254/latest/meta-data/instance-id/
i-577f7355
```

### 取得情報一覧

```bash
$ curl http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
hostname
instance-action
instance-id
instance-type
kernel-id
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
```

### 参考

<http://lance104.hatenablog.jp/entry/2014/03/09/235221>

## AWS CodeDeploy + AutoScale 注意点

### EC2インスタンスへのタグの付与タイミングとCodeDeployエージェントの起動順序の考慮

```bash
#!/bin/bash

## Role タグと Env タグを付与
aws ec2 create-tags \
  --resources $(wget -q -O - http://169.254.169.254/latest/meta-data/instance-id) \
  --tags Key=Role,Value=api Key=Env,Value=production

## プロビジョニングする (Chef, Puppet, Ansible, Itamae)
aws s3 sync s3://itamae-repo/ /path/to/itamae-repo/ --delete
cd /path/to/itamae-repo && itamae local bootstrap.rb --ohai

## CodeDeploy Agent は最後に起動する
service codedeploy-agent start
```

### 参考

<http://blog.takus.me/2015/12/03/aws-codedeploy-and-auto-scaling/\\>
<https://blogs.aws.amazon.com/application-management/post/Tx1NRS217K1YOPJ/Under-the-Hood-AWS-CodeDeploy-and-Auto-Scaling-Integration> (AWS公式ブログ)

## AWS EC2でELB配下のどれか１台でのみ実行

```check.sh
#!/bin/bash

LOAD_BALANCER_NAME="[ロードバランサ名]"

# Get self instance id and ip address.
MY_INSTANCE=`curl -s 169.254.169.254/latest/meta-data/instance-id/`


# ロードバランサ配下の有効なインスタンスの一覧を取得
INSTANCE_LIST=`aws elb describe-instance-health \
  --load-balancer-name ${LOAD_BALANCER_NAME} \
  --region ap-northeast-1 \
  --query 'InstanceStates[?State==\`InService\`].InstanceId' | jq -r '.[]'`

IS_ACTIVE=0

for INSTANCE in ${INSTANCE_LIST}
do
    if [ ${INSTANCE} = ${MY_INSTANCE} ]; then
        IS_ACTIVE=1
        continue
    fi

    if [ ${INSTANCE} \< ${MY_INSTANCE} ]; then
        exit 1
    fi
done

if [ ${IS_ACTIVE} -eq 1 ]; then
    exit 0
else
    exit 1
fi
```

```bash
#!/bin/bash

check.sh
IS_RUN=$?

if [ $IS_RUN -eq 0 ]; then
    [バッチの実行]
fi
```

### 参考

<http://qiita.com/idaaki/items/a356d1785a59d4150358>
