# 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hayashier.gitbook.io/article/aws/aws-misc.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
