Rails + AWSで雑にhttps を立てたいと思い
CloudFront(https) => EC2(Railsアプリ/http)
という構成でアプリを作ると、 GET 以外のリクエストを投げるとこんなエラーが出る
HTTP Origin header (https://xxx.cloudfront.net) didn't match request.base_url (http://xxx.cloudfront.net)
ApplicationController で適当にリクエストヘッダーを出力してあーでもないこーでもないとこねくり回してみたのだが・・・
class ApplicationController < ActionController::Base
before_action :env_log
private
def env_log
request.headers.sort.reject { |k, _| k.to_s.include?('.') }.each { |k, v| logger.info "#{k}:#{v}" }
end
end
自前でリバースプロキシをする時は、 X-Forward-Proto に https を設定するのが定石だが、CloudFront で動かしてみるとどうも X-Forward-Proto だけがうまく設定されない
例えば
- ヘッダー名: Hoge
- 値: Piyo
みたいな設定は動くけど、X-Forward-Proto だけが消去される
CloudFront には CloudFront-Forwarded-Proto という独自ヘッダーがあるらしく、
ビヘイビア側の設定で、Cloudfront-Forwarded-Protoを飛ばすように設定すると、そこにはhttpsが入ってくる。
Rack Middleware でCloudFront-Forwarded-Proto を X-Forward-Proto に置換するというのも見つけたけど、
https://aknep.hatenablog.com/entry/2017/09/17/230405
アプリを書き換えるのは嫌だなーと思っていたところ
https://mikamisan.hatenablog.com/entry/2017/09/28/230215
こちらで、Railsは X-Forwarded-SSLというフラグを見ているという記事を発見した
ソース:
https://github.com/rack/rack/blob/rack-1.5/lib/rack/request.rb#L73
ということで、X-Forward-Protoの設定は諦めて、X-Forwarded-SSL:on という設定を利用したら上手に動作した。
しかし、X-Forward-Proto がなぜ勝手に消されるのかは不明。
以下CloudFormation
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names
Type: String
VPC:
Type: AWS::EC2::VPC::Id
Description: Choose which VPC the security groups should be deployed to
DefaultTTL:
Description: The default cache time in seconds
Type: Number
Default: 86400 # 24hrs
MaxTTL:
Description: The maximum cache time in seconds
Type: Number
Default: 604800 # 168hrs
MinTTL:
Description: The minimum cache time in seconds
Type: Number
Default: 60 # 1 minute
ErrorCacheTTL:
Description: The Error cache time in seconds
Type: Number
Default: 60 # 1 minute
EndpointName:
Description: ELB Ref
Type: String
Default: ''
TargetOriginId:
Type: String
Description: target id
Default: 's3-bucket'
DefaultCachePolicyId:
Description: Cache Policy Id. (Default policy is ManagedCachingDisabled)
Type: String
Default: '4135ea2d-6df8-44a3-9df3-4b5a84be39ad'
AllowedPattern: '[-\.a-z0-9]*'
# ManagedCachingOptimized https://docs.amazonaws.cn/en_us/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html
DefaultOriginRequestPolicyId:
Description: Origin request Policy Id. (Default policy is AllViewer)
Type: String
Default: '216adef6-5c7f-47e4-b989-5492eafa07d3'
AllowedPattern: '[-\.a-z0-9]*'
Resources:
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
DefaultCacheBehavior:
TargetOriginId: WebSiteOrigin
AllowedMethods: [GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE]
OriginRequestPolicyId: !Ref DefaultOriginRequestPolicyId
CachePolicyId: !Ref DefaultCachePolicyId
ViewerProtocolPolicy: allow-all
Enabled: true
Origins:
- DomainName: !Ref EndpointName
Id: WebSiteOrigin
CustomOriginConfig:
OriginProtocolPolicy: 'http-only'
OriginKeepaliveTimeout: 60
OriginCustomHeaders:
- HeaderName: "X-Forwarded-SSL"
HeaderValue: "on"
Outputs:
CloudFrontEndpoint:
Description: address for the cloudfront
Value: !GetAtt Distribution.DomainName