dogwood008の開発メモ!

最近のマイブームは機械学習, Ruby on Rails。中でも機械学習を使った金融商品の自動取引に興味があります。

【JavaScript】console.log の他にも、console.warn や console.error がある

要旨

console.log('log')
console.warn('warn')
console.error('error')

それぞれの見た目
それぞれの見た目

詳細

主要なブラウザは、全て対応している。 console.log() では埋もれてしまうくらい沢山の出力がある際、特定の出力を目立たせる時に便利。

参考

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

【EKS】502が出る原因の一つ:ACMの証明書のARNが間違い

要旨

AWS Load Balancer Controller で指定するACMのARNが誤っていると、構成によっては502が返る。

これは、ALBのホスト名に対し直接httpsで繋ぎに行くと、ブラウザのアドレスバーからたどれる証明書を見ることで確認できる。

背景

Route 53 + WAF + CloudFront + ALB + EKSという構成でアプリケーションをホストしていたところ、あらゆるPathで502が表示され、その原因がわからないということがあった。

AWS公式で、502の対処方法が書かれているが、今回の原因は該当するものが無く解決に苦戦したので、誰かの役に立てばと思いその記録をしておくものである。

aws.amazon.com

用語

  • Route 53 ... AWSのDNS
  • WAF ... Web Application Firewall
  • CloudFront , CF ... CloudFront AWSのCDN
  • ALB ... Application Load Balancer
  • EKS ... Amazon EKS (Elastic Kubernetes Service)
  • ACM ... AWS Certification Manager
  • ARN ... Amazon Resource Name

詳細

実際に502が出ていたのは、Route 53 でレコードが割り当てられているホスト名に対し、httpsで接続しに行った時である。例えば、test.example.com に対し、203.0.113.1 が割り振られているとき、 https://test.example.com にアクセスした際に502がレスポンスとして返る、という状況である。

なお、Route 53では test.example.com から CF に対して Alias A & AAAA レコードが張ってある。また、 CF からはオリジンとして ALB を参照するようになっていた。ALBの後ろにはEKSが居て、サブドメインを見ながら到達させるPodをKubernetesが判断する、という構成になっていた。

詳しくは覚えていないが、https://test.example.com にブラウザでアクセスした際に表示された502は、ALBではなくCFが返していたように記憶している。つまり、CFとオリジン(=ALB)間で、不都合な通信が行われていたということが推測できる。

ここから、動作確認のため、 CFではなくALBが発行するホスト名(下図, albname-012.AWS_REGION.elb.amazonaws.com)に対し、httpsで接続した。この時、ブラウザはGoogle Chromeを使用していたので、アドレスバーから割り当てられている証明書を確認することができた。表示された証明書は *.cloudfront.net ではなく、ACMで発行したものであった。ここで気付いたのが、*.example.com のものを期待していたのに、例えば *.debug.example.com のように、本来期待していたものと異なる証明書が表示されていた。

ALBに割り当てられたホスト名
ALBに割り当てられたホスト名

ここでAWS Load Balancer Controller の Ingress を確認してみると、 metadata.annotations の項目の、 alb.ingress.kubernetes.io/certificate-arn で指定するARNが本来設定しないといけないものと異なっていたことがわかった。

その後、正しいARNを設定したところ、期待動作をするようになった。つまり、Route 53からCFに割り当てたホスト名 test.example.com でhttpsでリクエストすると、正常系のレスポンスが返るようになった。 

【Ruby】正規表現マッチには、^ と $ ではなく \A と \z を使おう

要旨

^$ の場合

[1] pry(main)> regex = /^https:\/\/.+$/
=> /^https:\/\/.+$/
[2] pry(main)> 'javascript:exploitcode() /*
https://safesite.example.com
*/'.scan(regex)
=> ["https://safesite.example.com"]

rubular.com

\A\z の場合

[3] pry(main)> regex2 = /\Ahttps:\/\/.+\z/
=> /\Ahttps:\/\/.+\z/
[4] pry(main)> 'javascript:exploitcode() /*
https://safesite.example.com
*/'.scan(regex2)
=> []

rubular.com

詳細

詳細は下記の記事に譲る。かいつまむと、Rubyはデフォルトで複数行マッチなので、 ^ $ だと文中の行頭・行末もマッチしてしまう。

blog.tokumaru.org

【Python】ロガーとハンドラをログレベルで制御して、表示のオンオフを管理する

要旨

とりあえずここに書いてあることを真似しておけばOK。

詳細

詳細はまた別の日に記載するとして、ひとまずコードだけを置いておく。個人的には非常に便利に使用しているので、きちんと使用方法やTipsを話をまとめ直したい。

import sys
from logging import Logger, Handler, getLogger, StreamHandler, Formatter, DEBUG, INFO, WARN, ERROR

logger_name = __name__
logger_level = WARN
logger = getLogger(logger_name)
logger.setLevel(logger_level)
logger.propagate = False

handler_loglevel = WARN
handler = StreamHandler(sys.stdout)
handler.setLevel(handler_loglevel)
handler.setFormatter(
    Formatter('[%(levelname)s] %(message)s'))

logger.addHandler(handler)
msg = 'WARNレベルだと、同レベルなので表示される'
loglevel = WARN
logger.log(loglevel, msg)
# => [WARNING] WARNレベルだと、同レベルなので表示される
msg = 'ERRORレベルだと、WARNよりレベルが上なので表示される'
loglevel = ERROR
logger.log(loglevel, msg)
# => [ERROR] ERRORレベルだと、WARNよりレベルが上なので表示される
msg = 'DEBUGレベルだと、WARNよりレベルが下なので表示されない'
loglevel = DEBUG
logger.log(loglevel, msg)
# => (何も表示されない)