Amazon S3のARNにある ::: ってなんだろう?と気になったはなし

2022.09.28

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

しばたです。

AWS環境を構築・運用する際は各リソースの識別子となるAmazon Resource Names(ARN)をよく見ることになると思います。
ある日ふとタイトル通りの疑問が湧いたので調べてみることにしました。

Amazon S3のARNにある ::: ってなんだろう?

AWSの識別子であるARNの形式については以下のドキュメントに記載されています。

ドキュメントの内容を一部引用するとARNは一般的に以下の:区切りの形式を採ります。

arn:partition:service:region:account-id:resource-id
arn:partition:service:region:account-id:resource-type/resource-id
arn:partition:service:region:account-id:resource-type:resource-id

各要素はそれぞれ、

  • partition : パーティション(=AWSリージョンのグループ)
    • 通常のAWSリージョン(aws)、中国リージョン(aws-cn)、AWS GovCloudリージョン(aws-us-gov)のいずれかを取ります
  • service : サービス名前空間 (≒サービス名)
    • s3 とかAWSサービスごとに専用のプレフィックスが定義されている
  • region : AWSリージョンコード
    • ap-northeast-1 とかのおなじみのコード
  • account-id : アカウントID
    • 123456789012 とかのハイフン抜きID
  • resource-id : リソース識別子
    • パスの存在するリソースの場合は/区切りで表現される。たとえばEC2インスタンス instance/i-1234567890abcdef0 など
  • resource-type : リソースタイプ
    • 一部のリソースで親子関係やバージョンを表現するために定義される

となります。

例えば東京リージョンにあるALB(ALB名 : my-alb)であれば以下のようになります。

arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:loadbalancer/app/my-alb/xxxxxxxxxxxxxxxx

そして本記事の本題であるS3バケット(バケット名 : my-bucket)の場合は

arn:aws:s3:::my-bucket

と他リソースと異なり:::という区切りになっています。

これが本記事の疑問ではあるのですが、まあ、先にここまでARNの解説を入れてしまうと答えはもはや明白で、S3の場合は単純に

arn:aws:s3:(省略):(省略):my-bucket

とリージョンコードとアカウントIDが省略された形になっているだけでした。
ドキュメントにも

Amazon S3 の ARN では AWS リージョンと名前空間は除外されますが、以下のものが含まれます。
(※S3のドキュメントではアカウントIDの部分が名前空間と表記されている)

とはっきり明記されています。

S3は物理的に配置される場所はリージョン別であるものの、バケット名といったリソースの識別はアカウントやリージョンに依存せず全世界で一意である必要があるためARNの記法でも省略されているのでしょう。

他の非リージョナルなサービスの場合

当初の疑問はあっさり解決しましたが、これだけだと面白くないので他のサービスについても調べてみました。

先に結果から述べておくと、ARNの定義や規約は明確に文書化されていない感じ *1だったのですが、非リージョナルなサービスで省略可能な要素がある場合は省略されるか特別なIDを割り当てられる傾向がありました。

IAM

まずはIAMのARNを調べてみました。

IAMはリージョンに依存しないのでリージョンコードは省略されています。
そしてユーザーが作成するリソースにはアカウントIDが普通につきますが、AWSが管理するマネージドポリシーではアカウントIDがawsと特別な指定になっていました。

# IAMではリージョンコードは省略

# ユーザーが管理するリソースには普通にアカウントIDがつく
arn:aws:iam::123456789012:policy/my-custom-policy
arn:aws:iam::123456789012:role/service-role/Amazon-GlueServiceRoleForSSM

# AWS管理のリソース(マネージドポリシー)はアカウントIDが aws となる
arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess

Route 53

次はRoute 53を調べました。
Route 53は基本ホストゾーンIDといったリソース識別子だけを取り扱い、ARNはIAMポリシーを書くとき位しか使いません。

ドキュメントからARNの記法を確認すると

arn:aws:route53:::hostedzone/hosted zone ID

といった感じでS3と同様の:::な記法でした。

CloudFront

次はCloudFrontです。
CloudFrontのディストリビューションはリージョンコードが省略された記法になっていました。

arn:aws:cloudfront::123456789012:distribution/XXXXXXXXXXXXX

AWS WAF

続けてAWS WAFです。
AWS WAFはCloudFrontに紐づけるグローバルな場合と、ALBなどのリージョナルサービスと紐づく場合の2パターン存在します。

ARNの記法を確認するとリージョンコードは省略されず、CloudFrontと紐づける場合は北米リージョン(us-east-1)扱いにするルールとなっていました。
加えてリソース識別子の先頭にスコープとしてregionalglobalのどちらかを記載する様になっています。

# ABLなどと紐づける場合は対象リージョンをそのまま記載する
# スコープは regional
arn:aws:wafv2:ap-northeast-1:123456789012:regional/webacl/my-web-acl/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

# CloudFrontと紐づける場合は北米リージョン扱いにする
# スコープは global
arn:aws:wafv2:us-east-1:123456789012:global/webacl/my-web-acl/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

AWS Health Dashboard (Health API)

ちょっと変わったところでAWS Health Dashboardで通知される各イベントにもARNは存在します。

基本は対象リージョンのリージョンコードがそのまま使われ、グローバルな通知に関してはglobalという専用コードが使われる様です。
アカウント固有のものではないのでアカウントIDは省略されています。

# AWS CLIからイベント情報を取得

# リージョン別の通知は対象リージョンがそのまま使われる
$ aws health describe-events --filter 'regions=ap-northeast-1' --query 'events[0]'
{
    "arn": "arn:aws:health:ap-northeast-1::event/ACM/AWS_ACM_OPERATIONAL_NOTIFICATION/AWS_ACM_OPERATIONAL_NOTIFICATION_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "service": "ACM",
    "eventTypeCode": "AWS_ACM_OPERATIONAL_NOTIFICATION",
    "eventTypeCategory": "accountNotification",
    "region": "ap-northeast-1",
    "startTime": "2022-09-20T10:10:00+09:00",
    "lastUpdatedTime": "2022-09-21T16:05:22.801000+09:00",
    "statusCode": "open",
    "eventScopeCode": "ACCOUNT_SPECIFIC"
}

# リージョンコードが global になる通知もある
$  aws health describe-events --filter 'regions=global' --query 'events[0]'
{
    "arn": "arn:aws:health:global::event/ACM/AWS_ACM_OPERATIONAL_NOTIFICATION/AWS_ACM_OPERATIONAL_NOTIFICATION_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
    "service": "ACM",
    "eventTypeCode": "AWS_ACM_OPERATIONAL_NOTIFICATION",
    "eventTypeCategory": "accountNotification",
    "region": "global",
    "startTime": "2022-09-16T12:20:00+09:00",
    "lastUpdatedTime": "2022-09-20T06:55:02.182000+09:00",
    "statusCode": "open",
    "eventScopeCode": "ACCOUNT_SPECIFIC"
}

補足 : リソース識別子とARN

AWSのサービスではリソースの特定にARNを必要とするものとリソース識別子だけで特定可能なものが分かれています。

一番わかりやすい例はEC2で、EC2の特定は基本的にインスタンスIDだけで済みARNを意識することはほとんどないはずです。
対してEC2の仲間であるELBではリソースの特定にARNが必要です。

# AWS CLI(ほぼREST API)でリソースを特定する例

# EC2を特定するにはリソース識別子(インスタンスID)だけで良い
aws ec2 describe-instances --instance-ids i-1111111111111111

# ELBを特定するにはARNが必要
aws elbv2 describe-load-balancers --load-balancer-arns arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:loadbalancer/app/my-alb/xxxxxxxxxxxxxxxx

いくつかのサービスを調べてみましたが両者を分ける明確な基準は無い様です。
単純に各サービス毎の設計思想の違いがそのまま現れている模様でした。

最後に

以上となります。

ふとした疑問からARNについていろいろ調べてみました。
特にオチのない話でしたがちょっとした雑学くらいにはなるかなって思います。

脚注

  1. もちろんAWS内部的には存在するのでしょうがパブリックに公開されたドキュメントからは見つけることができませんでした...