はじめに

Okta Customer Identity Cloud(powered by Auth0)は、開発者が認証機能を実装するには非常に簡単なツールではありますが、Okta CICの構築において忘れられがちなのは運用後の設計です。

Auth0は認証に関するログや管理者の操作などのログをAuth0内で管理してくれますが(参考)、プランによってログの保管期間が決まっています(参考)。エンタープライズプランであっても30日が保存の上限期間となっているため、30日を超える期間ログを保存しておきたい場合にはLog Streaming機能を使うことで(Essentialプラン以上が必要です)、AWS S3に格納するなどのことが必要です。前回はその設定をTerraformで実施する内容をご紹介しました(参考:「TerraformでAuth0のログをAWS S3に出力するようにしてみる」)

今回はCloudWatch Logsを活用したAuth0のログ監視方法の例についてご紹介します。前回同様Terraformを使って構築していきます。

前回はS3に出力していましたが、今回はCloudWatch Logsに出力するようにしてみます。

CloudWatch Logsに出力することで、ログの内容によって簡単にフィルタリングが可能です。S3より高価になっているので、保管だけしたい場合はS3をご利用ください。

以下がCloudWatch Logsに出力するためのTerraformのコードです。

前回作成したkinesisとs3リソースを削除し、置換してください。

resource "aws_cloudwatch_event_bus" "auth0" {
 name              = auth0_log_stream.eventbridge.sink[0].aws_partner_event_source
 event_source_name = auth0_log_stream.eventbridge.sink[0].aws_partner_event_source
}


resource "aws_cloudwatch_event_rule" "auth0" {
 name           = "auth0"
 description    = "auth0"
 event_bus_name = aws_cloudwatch_event_bus.auth0.name


 event_pattern = <<EOF
{
 "source": [{
   "prefix": "aws.partner/auth0.com"
 }]
}
EOF
}


resource "aws_cloudwatch_event_target" "auth0" {
 rule           = aws_cloudwatch_event_rule.auth0.name
 target_id      = "Auth0"
 arn            = aws_cloudwatch_log_group.auth0.arn
 event_bus_name = aws_cloudwatch_event_bus.auth0.name
}


resource "aws_cloudwatch_log_group" "auth0" {
 name              = "/auth0/tenant/logs"
 retention_in_days = 365
}

考え方

Auth0はログごとにイベントコードが割り振られており、これらをフィルタリングすることでエラーか否かを判別するようにします。

https://auth0.com/docs/deploy-monitor/logs/log-event-type-codes

実装例1

特定のイベントコードをCloudwatch metric filterにより検知した場合にCloudWatch Alarmを起動させます。

`fsa = Failed Silent Auth`はクリティカルなエラーではなく、Auth0を使っていればよく起きるエラーなので除外させ、それ以外の`f`および`limit`を含むイベントコードが出力された場合、つまりサイレント認証時のエラーを除く、何かしらのエラー、またはRate Limit超過時のみ検知させ、SNSへ通知するようにします。

resource "aws_cloudwatch_log_metric_filter" "error" {
  name           = "auth0-ErrorCount"
  log_group_name = aws_cloudwatch_log_group.auth0.id
  pattern        = "{ ($.detail.data.type = \"f*\" || $.detail.data.type = \"*limit*\" ) && $.detail.data.type != \"fsa\" }"
  metric_transformation {
    namespace     = "Auth0"
    name          = "ErrorCount"
    value         = "1"
    default_value = "0"
  }
}

resource "aws_cloudwatch_metric_alarm" "error_alarm" {
  alarm_name          = "auth0-Error"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 1
  metric_name         = ErrorCount
  namespace           = Auth0
  period              = 300
  statistic           = Sum
  threshold           = 1
  alarm_description   = "This metric checks error log count in the Auth0 log group"
  alarm_actions       = var.sns_topic_arns
  treat_missing_data  = "notBreaching"
}

これでエラーログが出た場合にSNSへ通知できる仕組みが完成しました。

しかしこれではノイズが多くアラートが鳴り続けてしまうので、適宜フィルターを追加する必要があります。

実装例2

アラートが起こるたびにフィルターのメンテナンスをするのは大変ですね。

次に異常な挙動をした=エラー率が跳ね上がった場合のみ検知する方法をご紹介します。

正常ログ・異常ログを識別し、エラー率が特定の割合まで上昇した場合のみエラーとして通知します。

resource "aws_cloudwatch_log_metric_filter" "error" {
  name           = "auth0-ErrorCount"
  log_group_name = aws_cloudwatch_log_group.auth0.id
  pattern        = "{ ($.detail.data.type = \"f*\" || $.detail.data.type = \"*limit*\" ) && $.detail.data.type != \"fsa\" }"
  metric_transformation {
    namespace     = "Auth0"
    name          = "ErrorCount"
    value         = "1"
    default_value = "0"
  }
}

resource "aws_cloudwatch_log_metric_filter" "total" {
  name           = "auth0-TotalCount"
  log_group_name = aws_cloudwatch_log_group.auth0.id
  pattern        = "{ $.version = \"*\" }"
  metric_transformation {
    namespace     = "Auth0"
    name          = "TotalCount"
    value         = "1"
    default_value = "0"
  }
}

resource "aws_cloudwatch_metric_alarm" "auth0_error" {
  alarm_name          = "Auth0-log-SuccessPercent"
  comparison_operator = "LessThanThreshold"
  evaluation_periods  = "2"
  datapoints_to_alarm = "2"
  threshold           = "90"
  treat_missing_data  = "ignore"

  metric_query {
    id          = "e1"
    expression  = "(m2-m1)/m2*100"
    label       = "SuccessPercent"
    return_data = "true"
  }

  metric_query {
    id     = "m1"
    period = 0
    metric {
      dimensions  = {}
      metric_name = "ErrorCount"
      namespace   = "Auth0"
      period      = 300
      stat        = "Sum"
    }
  }

  metric_query {
    id     = "m2"
    period = 0
    metric {
      dimensions  = {}
      metric_name = "TotalCount"
      namespace   = "Auth0"
      period      = 300
      stat        = "Sum"
    }
  }

  alarm_actions = var.sns_topics_arn
}

すべてのログの数をカウントするフィルターを追加します。

このフィルターと、先ほど追加したエラーのみをカウントするフィルターと組み合わせることで成功率の算出をします。

今回は、90%を切った場合のみアラートされるようになっています。利用者数が少ない状況だと一度のエラーが成功率を引き下げることになるので、その場合はthresholdの値を定義下げるようにしてください。

おわりに

アラート通知ルールは、利用するシステムの特性や非機能要件によって変化します。今回ご紹介したものを直接活用するのではなく、あくまで参考としてご活用ください。

また、Auth0のLog Streams機能はAWS以外にもDatadogやSplunkなどのインテグレーションもサポートしています。詳細は公式ドキュメントを参照ください。

https://auth0.com/docs/customize/log-streams

ソリューションサービスのご紹介

TC3はOkta CIC(Customer Identity Cloud)を代表とするIDaaSを活用したデジタルサービス開発のプロフェッショナルです(Customer Identity Cloudの認定も取得しています)。

すでに実践的に設計・実装された基盤サービスとして2024年5月末に、「Tactna Identity Platform」を発表しました!このサービスを活用いただくことで、事業部やサービス間の調整を減らし、リリースまでの期間を早め、ユーザー体験を向上させるといったメリットの多い開発プランをご提供します。

サービス紹介サイト

トライアル・MVP開発の段階から、どのようにIDaaS/CIAMを導入するかについてもサポートさせていただきますので、お気軽にお問い合わせください。

Tactna Identity Platformに関する詳細のご紹介資料は以下からダウンロードいただけます!

ひとまず情報のキャッチアップだけしておきたいという方は、こちらからニュースレターの購読ができます。