Lambda@Edgeを利用してすべてのSet-CookieにSecureとHttpOnlyを付ける

2019.09.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

最近会社においてあるグランツーリスモをやっているもこ@札幌オフィスです。

Lambda@Edgeを利用してオリジンから送られる Set-Cookie を書き換えて、送信されるCookie全てにSecure属性とHttOnlyを付けてみました。

コード

今回利用したコードはこんな形になっています。

exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
for (const cookie of response.headers['set-cookie']) {
cookie.value += "; Secure; HttpOnly"
}
callback(null, response);
}

利用方法

オリジンから送信されてくる情報を書き換える必要があるため、CloudFrontイベントは"オリジンレスポンス"を利用します。

また、CloudFrontの設定、「Forward Cookies」をAllなどに変更する必要があります。(キャッシュのヒット率は下がります。)

関数を作成し

上記コードを貼り付け

ロールを作成し、保存します。

上のアクションから「Lambda@Edgeへのデプロイ」を選択し、

デプロイ先のCloudFrontを選択し、CloudFrontイベントををオリジンレスポンスに変更します。

User <-> CloudFront(Lambda@Edge) <-> ALB <-> EC2 のような環境を作成し、

適当なCookieを投げるようなアプリケーションを作り、EC2上に起動しました。

const express = require('express')

const app = express();

app.get('/', (req, res) => {
res
.cookie('hoge', 'hoge')
.cookie('test', 'test')
.status(200).send('OK');
})

app.listen(80)

ALBを叩いてSet-Cookieヘッダーが追加されているのを確認します。

$ curl -I xxxxx-xxxxxxxxx.ap-northeast-1.elb.amazonaws.com
HTTP/1.1 200 OK
Date: Fri, 20 Sep 2019 8:14:32 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 2
Connection: keep-alive
X-Powered-By: Express
Set-Cookie: hoge=hoge; Path=/
Set-Cookie: test=test; Path=/
ETag: W/"2-nOO9QiTIwXgNtWtBJezz8kv3SLc"

Lambda@EdgeのCloudFrontへのデプロイが終わり、curlで叩いてみると、正常に ; Secure; HttpOnly が追加されているのを確認出来ます。

$ curl -I http://xxxxx.cloudfront.net
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 2
Connection: keep-alive
Server: CloudFront
Date: Fri, 20 Sep 2019 8:12:23 GMT
X-Powered-By: Express
Set-Cookie: hoge=hoge; Path=/; Secure; HttpOnly
Set-Cookie: test=test; Path=/; Secure; HttpOnly
ETag: W/"2-nOO9QiTIwXgNtWtBJezz8kv3SLc"
X-Cache: Miss from cloudfront
Via: 1.1 171d3bd7ed02f868a62075a1caaa7993.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRT53
X-Amz-Cf-Id: Fm3nsyZ2_N7viWjvfQ_DSjz9B9lR45Rz0JHQBrAgg3qHBmZtSIf9Ag==

また、HttpOnlyの効果により document.cookieの取得も出来なくなっているのが確認できます。

まとめ

CloudFrontのオリジンレスポンスを利用すると、アプリケーション側ではなくLambda@Edge側で強制的にヘッダーを書き換えることが出来るので、とても便利です。

Lambda@Edgeの使い方次第ではサーバーレスではない環境に対してもサーバーレスチックな使い方が出来ると思います。

誰かのお役に立てれば幸いです。