JavaScriptでCloudFrontにACMの証明書を追加する


[JavaScriptでSSL証明書をリクエストする（AWS SDK + Amazon Certificate Manager）](http://qiita.com/motchi0214/items/020b8c430e2138dc2261)の続きです。

ACMのARNとCloudFrontのDistributionIDがあれば、こいつもJavaScriptで一発です。

## コード

```index.js
var AWS = require('aws-sdk');
var cloudfront = new AWS.CloudFront({
	apiVersion: '2016-01-28',
    accessKeyId: "ACCESS_KEY_ID",
    secretAccessKey: "SECRET_ACCESS_KEY"
});

var cfDistributionId = 'YOUR_CLOUDFRONT_DISTRIBUTION_ID';
var acmArn = 'YOUR_ACM_ARN';

var params = {
  Id: cfDistributionId
};

cloudfront.getDistributionConfig(params).promise().then(
	(data) => {
		var ViewerCertificate = {
	      ACMCertificateArn: acmArn,
	      CertificateSource: 'acm',
	      CloudFrontDefaultCertificate: false,
	      MinimumProtocolVersion: 'TLSv1',
		  SSLSupportMethod: 'sni-only'
		}
		data.DistributionConfig.ViewerCertificate = ViewerCertificate;
		var updateParams = {
			DistributionConfig: data.DistributionConfig,
			Id: cfDistributionId,
			IfMatch:  data.ETag
		}
		return cloudfront.updateDistribution(updateParams).promise();
	}
).then(
	(data) => {
		console.log(data);
	}
).catch(
	(err) => {
		console.log(err, err.stack);
	}
);

```

## 非常にざっくりとした説明
まずDestributionIDを使ってACMを設定するCloudFrontの設定情報を取得します。

続いて「ViewerCertificate」という値にSSL設定系の情報を入れるので、ここをACMを適用する形に書き換えます。

あとはupdateDistributionでCloudFrontの設定を更新するだけです。


## 横着しすぎて怒られたやつ

「あれ、ACMのリクエストとCloudFrontの適用両方いけるならpromiseでつなげば一発じゃね？」と思ってこんなの書いてみました。

```unwork.js
// params
var domain = 'YOUR_DOMAIN';
var cfDistributionId = 'YOUR_CLOUDFRONT_DISTRIBUTION_ID';
var acmArn = '';

// Module Setup
var AWS = require('aws-sdk');

// Class Setup
var acm = new AWS.ACM({
	apiVersion: '2015-12-08',
    accessKeyId: "ACCESS_KEY_ID",
    secretAccessKey: "SECRET_ACCESS_KEY",
    region: "REGION"
});
var cloudfront = new AWS.CloudFront({
	apiVersion: '2016-01-28',
    accessKeyId: "ACCESS_KEY_ID",
    secretAccessKey: "SECRET_ACCESS_KEY"
});

var params = {
  DomainName: domain,
  DomainValidationOptions: [
    {
      DomainName: domain,
      ValidationDomain: domain
    },
  ]
};

acm.requestCertificate(params).promise().then(
	(data) => {
		console.log(data);
		acmArn = data.CertificateArn;
		var params = {
		  Id: cfDistributionId
		};
		return cloudfront.getDistributionConfig(params).promise();
	}
).then(
	(data) => {
		var ViewerCertificate = {
			ACMCertificateArn: acmArn,
			CertificateSource: 'acm',
			CloudFrontDefaultCertificate: false,
			MinimumProtocolVersion: 'SSLv3'
		}
		data.DistributionConfig.ViewerCertificate = ViewerCertificate;
		var updateParams = {
			DistributionConfig: data.DistributionConfig,
			Id: cfDistributionId,
			IfMatch:  data.ETag
		}
		return cloudfront.updateDistribution(updateParams).promise();
	}
).then(
	(data) => {
		console.log(data);
	}
).catch(
	(err) => {
		console.log(err, err.stack);
	}
);
```
上の処理を実行すると、「The specified SSL certificate doesn\'t exist, isn\'t valid, or doesn\'t include a valid certificate chain.」と怒られます。「その証明書、ちゃんと認証終わってないから使えないっすわ」ってことですね。

横着せずに、ちゃんと証明書のを有効化させてから適用させましょう。

## $600の恐怖
DistributionConfig.ViewerCertificateのパラメータを以下のようにしていると、CloudFrontが$600もってかれる設定に変更されるので本気で要注意です。

```
ACMCertificateArn: acmArn,
CertificateSource: 'acm',
CloudFrontDefaultCertificate: false,
MinimumProtocolVersion: 'SSLv3'
```