Carpe Diem

備忘録

JWTの署名検証で使う公開鍵をX.509証明書で管理する

概要

JWTをアクセストークンとして利用する場合、署名(秘密鍵)は認証サーバで、署名検証(公開鍵)はリソースサーバで行うのが良いです。

そのため認証サーバは公開鍵をリソースサーバに公開する必要があります。

Googleなどの大規模サービスを見ると、生の公開鍵を公開しているのではなくX.509証明書の形で公開されています。
これは

  • 公開鍵の有効期間が設定できる
  • 公開鍵が改ざんされていない事が分かる
  • なりすましによる公開鍵でないことが分かる
  • 秘密鍵が漏洩した時に失効ができる

といったデジタル署名のメリットを享受できるようにと考えられます。

{
  "4e00e8fe5f2c88cf0c7044f307f7e739788e4f1e": "-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIILnkHftPtFMYwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE\nAxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMjEw\nMzEzMDkyMDE2WhcNMjEwMzI5MjEzNTE2WjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl\nbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAKhhzpJd8Eeu/lCdaA0x2P0gHvVT3aGmH4bxgbVpLjvQDZEr\nDebKhDaMNJDx16MDDJWo7oFzSCLe8humbCKqRymRISD7S2BsUnYBSgShrhkFZ00S\nFxan9znx8sev4sIWaxy0M7FEUVLpKlzcBIVpK5Wpj1P8z1A0lVhd5lj/gHY/WTLv\nNyG1tcajR0nSSygymGlYpfJKWuBjJTQSbhfTujXFaqUGKov6OeRU+7jBTow4M8Cu\nk8a1eohl/2ti5MHjPYtXvhahfDo33uHZ9TTle5NEFZCC2lW8wL4RBvCqhhw2i5EV\nfDuqSw9/G2MHCN5QmFTwNY+LNE2aghLY7kIvQW8CAwEAAaM4MDYwDAYDVR0TAQH/\nBAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ\nKoZIhvcNAQEFBQADggEBAAI6cD9Tx1QSwdUj1k+jkLBor9m6mZHv2cb40jsjiFxo\nYZESNCpLikD7K6pRewbFIrvqnUQDMxNVMlrFCWVm7NqJPJKvdnWEVOHqW5TgoMe3\nHnkzgpjEwREQfWJGJeW6yQbg0t8NW4h8Wi516aL3uNP8pgR7ZSLBwzbnW24SS1Kc\nfOMVLrKYaugvpDHy7TeK4WEilnGV3l2Agwq4cmqqdZscrRKxfrq9leLeNDpFlPLK\nlqrRlsuf5Zo0nOEsQ/+XW0vEsR+3VEGAgKJ4vRJoXsTh2DDp7StfwxXbQNBZ8MdR\nZ65pwGB7HGCXZiCrAo2ZyMGYr91SRgdlXzjRtOiYcX4=\n-----END CERTIFICATE-----\n",
  "48949d7d407fec9b2ac8d635ecba0b7a914ed8fb": "-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIIROeL9MsgVpEwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE\nAxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMjEw\nMzA1MDkyMDE2WhcNMjEwMzIxMjEzNTE2WjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl\nbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAME/0KmvljavWngX6QNm9PeJsSo3QUkoobUvFOBjFkDnDR0F\npa9bv5dQxpMr+TFvSvMIBLKENde1hD9q8dgN9WXpa++XxEKbdAx86nhjVLYzDm0O\nsMyonvddF0kPvTOKD2SGof2uoceeDu6AJnymM0EO5lpj15Bz8FThm9NDOM1mElA+\nmuhNAdgyIjVNRSDyFSE177DqoHJ7hVYsHW1Pvyrfkh0CtHV73XQsxT4xJdXGPJxf\nC3g0NsUVRMpcJzqMZm42QTwdXIIsQE7GWRZVzcNayyccHu7MEafH5zNaQYpUHnio\nj2KZJ1AxTERECoUa6VGLWttTVW34YKqK5Dv7qQMCAwEAAaM4MDYwDAYDVR0TAQH/\nBAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ\nKoZIhvcNAQEFBQADggEBALDDPZJiCZiCF5kq3C0jKrZeg0TXNzsnnicbXxQMhefz\nQeRfD3M0wnuTqLtCYgqSs3jWUZTMkXP3vaYnDbr+Wk1uHzIuX4GLzqqNrkJzVAfm\nC2ashKj+4PwcSPa9hfRXh/GAgtCOE9FJOOD0bRQKnSowSY3B8ZftkGpMOD//hYJK\nIFl05d9Cu2rCkdg6Trgx1GrpszSHU0WP2TFRZApuWpAogPpAPBMIDaEaZ8YYgMed\nBJkDGaJaHP6wwD1WISYJ8JownG5rHLEGsCrPAUzFaURT+z1LkuE4flCIxErl8gO9\ndTw/jtB1GXqbU/O8/d0uHiEsL6Kp9b/JgINIh730dK8=\n-----END CERTIFICATE-----\n"
}

ref: https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com

今回はその場合の署名検証の実装を説明します。

続きを読む

OpenSSLコマンド備忘録

概要

よく忘れるので備忘録として。

環境

  • macOS v11.2.3
  • OpenSSL v1.1.1

秘密鍵、公開鍵

基本的にgenpkeyで作れるが、RSA、EC系は他のコマンドの方が短い記述で生成できる。

RSA

RSA秘密鍵を生成

$ openssl genrsa -out key.pem 4096

秘密鍵から公開鍵の生成

$ openssl rsa -in key.pem -pubout -out pubkey.pem
続きを読む

etcdを使った分散ロック

概要

前回のRedisを使った分散ロックでは、正確なロックを取るためにはZookeeperやetcdを使うと良い、とまとめていました。

なので今回はetcdを用いて分散ロックを実現します。

環境

  • etcd v3.4.15
  • pkg.go.dev/go.etcd.io/etcd v3.5.0
  • go 1.16.0

事前知識

分散ロックに必要なもの

分散ロックマネージャには以下の機能が必要です。

  • 自動リース機能
  • CAS
  • フェンシングトークンを発行する機能

1つ1つ説明していきます。

続きを読む

Redisを使った分散ロック (SETNX, Redlock)

概要

分散システムにおいて同じリソースにアクセスする際にロック(排他制御)する仕組みを分散ロックといいます。

ロックを用いる背景としては主に2つあり、

目的 説明 具体例
効率 同じ作業を不必要に複数回行わないため キャッシュのOriginへのリクエストを抑制したい(Cache stampede対策)
正確性 データの不整合が起きないようにするため トランザクション

Redisを分散ロックに使う場合は主に前者のケースにおいて推奨されます。

環境

  • Redis 6.2.0
続きを読む

NEG(Network Endpoint Group)を使った負荷分散

概要

従来のGKEのロードバランサーはNodeに到達後iptablesで再度負荷分散するという2段階ロードバランシングでした。
これによりレイテンシの増加、分散のばらつきといった問題が生じていました。

f:id:quoll00:20210222013932g:plain

ref: Google Cloud Blog - News, Features and Announcements

しかしNEG(Network Endpoint Group)という機能を使うことで直接Pod宛てに負荷分散を行うことができ、上記の問題を低減することが可能となっています。

f:id:quoll00:20210222014123g:plain

ref: Google Cloud Blog - News, Features and Announcements

続きを読む

セキュアなトークン管理方法

概要

クライアント↔サーバ間の認証・認可情報としてのトークン管理はWebサービスとしては必ずつきまとうものですが、一方できちんと実装しないとセキュアに管理はできません。

今回はそのトークン管理方法の一例を紹介します。

要件

今回の主な要件は以下です。

  • AuthサーバとResourceサーバは別で管理する(負荷特性が異なるので)
  • 認証するとAuthサーバはrefresh tokenとaccess tokenを返す
  • access tokenはJWT形式
  • access tokenはクライアントのオンメモリで管理する
  • access tokenの期限は短く(1時間以内)
  • refresh tokenを使ってaccess tokenを発行できる
  • refresh tokenはrevoke可能である
    • 認証情報に変更があれば(パスワード変更など)refresh tokenをrevokeできる
  • Resourceサーバは起動時などにAuthサーバから公開鍵を取得し、access tokenの署名検証に使用する

ネイティブクライアントの場合

ネイティブクライアントの場合、keychainなどセキュアな管理ストレージがあるためrefresh tokenを保存することができます。

続きを読む

デッドロックとその対策

概要

複数のトランザクションが共通のリソースにアクセスする際に気をつけるものとしてデッドロックがあります。

例えばこのように一方はResource1, Resource2とロックしてアクセスし、もう一方はResource2, Resource1とロックしてアクセスする場合、うまく行けば両方とも成功しますが、

f:id:quoll00:20210207152617p:plain

ロックのタイミングによっては一方がロックできず、またアンロックもできない状態(=デッドロック)に陥ります。

続きを読む