リソースベースポリシーの Principal に存在しないプリンシパルを指定すると Invalid principal in policy などのエラーが発生する

Invalid principal(無効なプリンシパル)は、多くの場合「存在しない AWS アカウント」か「存在しない IAM ユーザー/IAM ロール」を指すかと思います。

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

Invalid principal in policy がでた

コンバンハ、千葉(幸)です。

IAM ロールの信頼ポリシーを編集する際に、ダミーの値として存在しない AWS アカウント番号を入れたことがありました。

principal_IAM_Management_Console

↑信頼ポリシーの編集時には IAM Access Analyzer によるポリシー検証が自動で行われますが、そこでは特に指摘事項は検出されていません。

そのままポリシーの更新を実行するとエラーが出ます。

Principal_error_IAM_Management_Console

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:iam::000000000000:root"

「無効なプリンシパルがポリシーに存在する」というエラーのようです。どんな時にこのエラーになるんだろう?というのを少し調べてみました。

まとめ

  • リソースベースポリシーのPrincipalに以下を指定するとエラーが出る
    • 存在しない AWS アカウント
    • 存在しない AWS アカウントを ARN に含むプリンシパル
    • 存在しない IAM ユーザーもしくは IAM ロール
  • 以下は任意のものを指定できる
    • IAM ロールセッションプリンシパルのセッション名
    • フェデレーテッドユーザーセッションのユーザー名
  • リソースベースポリシーによってエラーは微妙に異なる

凡例

このエントリでは、アカウント番号を表す000000000000はそのまま「0 が 12桁の存在しない AWS アカウント番号」表すために用います。普段は実際のアカウント番号をマスクするための置き換えとして使うことが多いですが、このエントリでは異なります。

代わりに、本来の AWS アカウント番号をマスクしたい箇所は〓〓〓〓〓〓で表すことにします。 *1

信頼ポリシーの編集画面で確認

IAM ロール信頼ポリシーの編集画面でいろんなプリンシパルタイプを指定して更新可否を確認していきます。

AWS account and root user

ARN の構文はこちらです。

arn:aws:iam::{Account}:root

冒頭の例の通り、存在しない AWS アカウント番号を指定するとエラーになります。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:iam::000000000000:root"

CloudTrail イベントで確認すると以下のような内容になっていました。MalformedPolicyDocumentExceptionというエラーコードが確認できます。

...
    "eventTime": "2022-12-29T19:25:03Z",
    "eventSource": "iam.amazonaws.com",
    "eventName": "UpdateAssumeRolePolicy",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "AWS Internal",
    "errorCode": "MalformedPolicyDocumentException",
    "errorMessage": "Invalid principal in policy: \"AWS\":\"arn:aws:iam::000000000000:root\"",
    "requestParameters": {
        "roleName": "test-chiba-role",
        "policyDocument": "{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Principal\": {\n\t\t\t\t\"AWS\": \"arn:aws:iam::000000000000:root\"\n\t\t\t},\n\t\t\t\"Action\": \"sts:AssumeRole\"\n\t\t}\n\t]\n}"
    },
    "responseElements": null,
    "requestID": "ebaee4bd-4583-4636-8f2e-d99f27bb4aa6",
    "eventID": "149047dc-7559-42ac-99d1-5d3e82e99719",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
...

↑ 以降の別のプリンシパルタイプで試行した際も、エラーが出た場合の内容は同様でした。

AWS アカウント番号を実在のものに置換すれば正常に更新ができます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::〓〓〓〓〓〓:root"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

000000000000のように明らかにダミーと分かる番号でなく実在する AWS アカウント番号から 1 桁変更した番号でも試してみましたが、エラーになりました。アカウント番号が存在するかどうかチェックするプロセスが入るようです。

IAM Roles

ARN の構文はこちらです。

arn:aws:iam::{Account}:role/{RoleNameWithPath}

やはり ARN に存在しない AWS アカウント番号を指定した場合はエラーに。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:iam::000000000000:role/cm-chiba.yukihiro"

「AWS アカウント番号は実在するがそのアカウントに存在しない IAM ロール」を指定した場合もエラーになりました。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:iam::〓〓〓〓〓〓:role/dummy-role"

Role sessions

ARN の構文はこちら。IAM ロールではなくそれを引き受けたセッションまで指定するパターンです。

arn:aws:sts::{Account}:assumed-role/{RoleName}/{RoleSessionName}

一応確認しますが存在しない AWS アカウント番号を含む場合はもちろんエラーに。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:sts::000000000000:assumed-role/cm-chiba.yukihiro/dummy-session"

実在しない IAM ロール名を含んだ場合もエラーになります。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:sts::〓〓〓〓〓〓:assumed-role/dummy-role/dummy-session"

セッション名は任意のものを指定できました。リソースとして永続的に存在するものではないからかと思います。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:sts::〓〓〓〓〓〓:assumed-role/cm-chiba.yukihiro/dummy-session"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

IAM users

ARN の構文はこちら。

arn:aws:iam::{Account}:user/{UserName}

考え方としては IAM ローの場合と同じでした。

存在しない AWS アカウントの場合はエラー。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:iam::000000000000:user/Test-User"

実在しない IAM ユーザー名もエラーです。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:iam::〓〓〓〓〓〓:user/dummy-User"

もちろん実在する IAM ユーザー名の場合は更新できます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::〓〓〓〓〓〓:user/Test-User"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

Federated user sessions

プリンシパルがフェデレーテッドユーザーセッションの場合です。フェデレーテッドユーザーセッションとは、GetFederationTokenで取得した一時的な認証情報を利用するセッションのことです。

ARN の構文はこちら。(なのですが、iamの部分はポリシーとして保存されたあとはstsに置き換えられます。)

arn:aws:iam::{Account}:federated-user/{UserName}

存在しない AWS アカウント番号を含めた場合にエラーになるのはいつもの通り。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "AWS":"arn:aws:iam::000000000000:federated-user/dummy-user"

フェデレーテッドユーザー名はロールセッションと同じように任意のものを指定できます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::〓〓〓〓〓〓:federated-user/dummy-user"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

↑上記のポリシーで更新はできるのですが、改めてポリシーを確認するとiamの部分がstsに置き換えられていました。

AWS services

ちょっと例外的ですが AWS サービスをプリンシパルに指定する場合も確認しておきます。

ARN ? の形式はこちら

{ServiceName}.amazonaws.com

基本的には以下ページから確認できるサービス名を指定してあげればよさそうです。

いくつかピックアップして、以下は正常に更新できることを確認しました。

- "Service": "rbin.amazonaws.com"
- "Service": "bugbust.amazonaws.com"
- "Service": "a4b.amazonaws.com"
- "Service": "migrationhub-orchestrator.amazonaws.com"

すべてが対応しているかというとそういうわけではなさそうで、以下を指定したときは更新に失敗しました。

- "Service": "signin.amazonaws.com"
- "Service": "signin.aws.amazonaws.com"

また、ページに載っていないサービスも対応していなさそうです。試しにoam(Amazon CloudWatch Observability Access Manager)を指定してみるとエラーになりました。

信頼ポリシーを更新できませんでした。

Invalid principal in policy: "SERVICE":"oam.amazonaws.com"

S3 バケットポリシーの編集画面でも確認

ここまで確認してきた内容が信頼ポリシー特有のものでないかの確認のため、S3 バケットポリシーでも試してみます。

結論から言うと信頼ポリシーの場合と同じ結果になりました。

S3 コンソールで無効なプリンシパルを指定してポリシーの保存を試みた場合のエラーはこんな感じ。

S3_bucket_policy_principal

不明なエラー

予期しないエラーが発生しました。API レスポンスInvalid principal in policy

↑「無効なプリンシパル」の内訳の表示はしてくれないようです。

CloudTrail イベントの内訳はこんな感じです。

...
    "eventTime": "2022-12-29T19:57:33Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "PutBucketPolicy",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "xx.xx.xx.xx",
    "userAgent": "[S3Console/0.4, aws-internal/3 aws-sdk-java/1.11.1030 Linux/5.10.157-122.673.amzn2int.x86_64 OpenJDK_64-Bit_Server_VM/25.352-b08 java/1.8.0_352 vendor/Oracle_Corporation cfg/retry-mode/standard]",
    "errorCode": "MalformedPolicy",
    "errorMessage": "Invalid principal in policy",
    "requestParameters": {
        "bucketPolicy": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Principal": {
                        "AWS": "arn:aws:iam::000000000000:root"
                    },
                    "Effect": "Allow",
                    "Action": "s3:ListBucket",
                    "Resource": "arn:aws:s3:::chibayuki-hoge-hoge"
                }
            ]
        },
        "bucketName": "chibayuki-hoge-hoge",
        "Host": "s3.ap-northeast-1.amazonaws.com",
        "policy": ""
    },
    "responseElements": null,
...

AWS CLI で試してみる

ここまで確認してきた結果がマネジメントコンソール特有の挙動でないかを確認するため、AWS CLI でも同様の操作を試してみます。

結論から言うとコンソールの場合と同じ結果になりました。

IAM ロール信頼ポリシー

存在しない AWS アカウント番号を含むポリシーで編集を試みた場合の結果はこんな感じ。

% policy=$(cat <<EOM
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS":"arn:aws:iam::000000000000:root"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOM
)

% aws iam update-assume-role-policy --role-name test-chiba-role --policy-document "$policy"

An error occurred (MalformedPolicyDocument) when calling the UpdateAssumeRolePolicy operation: Invalid principal in policy: "AWS":"arn:aws:iam::000000000000:root"

存在しない IAM ロール名を指定した場合の結果は以下のとおりです。

% aws iam update-assume-role-policy --role-name test-chiba-role --policy-document "$policy2"

An error occurred (MalformedPolicyDocument) when calling the UpdateAssumeRolePolicy operation: Invalid principal in policy: "AWS":"arn:aws:iam::〓〓〓〓〓〓:role/dummy-role"

CloudTrail イベントに記録された内容も、コンソールから実行した場合と同様でした。(もちろん userAgent などの周辺情報は異なります。)

そのほかのパターンの試行は割愛しましたが、状況から見て同じ結果になることが予想されます。

S3 バケットポリシー

S3 バケットポリシーの場合も同様です。

存在しない AWS アカウント番号を指定した場合のエラー。

% policy=$(cat <<EOM
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::000000000000:root"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::chibayuki-hoge-hoge"
        }
    ]
}
EOM
)

% aws s3api put-bucket-policy --bucket chibayuki-hoge-hoge --policy "$policy"

An error occurred (MalformedPolicy) when calling the PutBucketPolicy operation: Invalid principal in policy

存在しない IAM ロールを指定した場合のエラーはこちらです。

% policy2=$(cat <<EOM
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS":"arn:aws:iam::〓〓〓〓〓〓:role/dummy-role"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::chibayuki-hoge-hoge"
        }
    ]
}
EOM
)

% aws s3api put-bucket-policy --bucket chibayuki-hoge-hoge --policy "$policy2"

An error occurred (MalformedPolicy) when calling the PutBucketPolicy operation: Invalid principal in policy

おまけ:他のリソースベースポリシーでも試してみる

信頼ポリシーと S3 バケットポリシーでもサンプルは十分かと思いましたが、せっかくなのでもう 2 つくらい試してみます。

SNS トピックポリシー

既存の SNS トピックポリシーを以下の内容に更新を試みました。

{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "SNS:Publish",
        "SNS:RemovePermission",
        "SNS:SetTopicAttributes",
        "SNS:DeleteTopic",
        "SNS:ListSubscriptionsByTopic",
        "SNS:GetTopicAttributes",
        "SNS:AddPermission",
        "SNS:Subscribe"
      ],
      "Resource": "arn:aws:sns:us-east-1:〓〓〓〓〓〓:test",
      "Condition": {
        "StringEquals": {
          "AWS:SourceOwner": "〓〓〓〓〓〓"
        }
      }
    },
    {
      "Sid": "__console_pub_0",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::000000000000:root"
      },
      "Action": "SNS:Publish",
      "Resource": "arn:aws:sns:us-east-1:〓〓〓〓〓〓:test"
    }
  ]
}

更新が失敗し、以下エラーが記録されました。

トピックアクセスポリシーを設定できませんでした。

エラーコード: InvalidParameter - エラーメッセージ: 属性 アクセスポリシー の設定中にエラーが発生しました。 Invalid parameter: Policy Error: PrincipalNotFound

CloudTrail イベントの内訳はこんな感じ。

...
    "eventTime": "2022-12-29T20:46:19Z",
    "eventSource": "sns.amazonaws.com",
    "eventName": "SetTopicAttributes",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "AWS Internal",
    "errorCode": "InvalidParameterException",
    "errorMessage": "Invalid parameter: Policy Error: PrincipalNotFound",
...

微妙にエラーメッセージやエラーコードが異なりますね。

KMS キーポリシー

以下のキーポリシーを持つ KMS キーの作成を試みました。

{
    "Id": "key-consolepolicy-3",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::〓〓〓〓〓〓:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::000000000000:root"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::000000000000:root"
            },
            "Action": [
                "kms:CreateGrant",
                "kms:ListGrants",
                "kms:RevokeGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }
    ]
}

キーの作成は失敗し、以下メッセージが表示されました。

  • CreateKey リクエストが失敗しました

    MalformedPolicyDocumentException - Policy contains a statement with one or more invalid principals.

ここでもエラーメッセージが少し異なりますね。なお、CloudTrail イベントは確認できませんでした。

まとめ(再掲)

  • リソースベースポリシーのPrincipalに以下を指定するとエラーが出る
    • 存在しない AWS アカウント
    • 存在しない AWS アカウントを ARN に含むプリンシパル
    • 存在しない IAM ユーザーもしくは IAM ロール
  • 以下は任意のものを指定できる
    • IAM ロールセッションプリンシパルのセッション名
    • フェデレーテッドユーザーセッションのユーザー名
  • リソースベースポリシーによってエラーは微妙に異なる

終わりに

リソースベースポリシーの Principal に存在しないプリンシパルを指定するとエラーになる、という話でした。エラーでは「無効なプリンシパル」と表示されるだけなので、具体的にどのように無効かまではカスタマー側で確認する必要がありそうです。

ポリシーの設定時にプリンシパルの存在を判定してくれているのは便利といえば便利ですね。一方で、構築時などは順序を意識してあげる必要があります。例えば「特定の IAM ロールからのアクセスのみ許可する S3 バケット」を構築する場合、先に IAM ロールから作らないといけない、ということです。

また、総当たりで試行すれば「存在する AWS アカウント番号」「特定の AWS アカウントに存在する IAM ユーザー/IAM ロール」の特定までできてしまうのでは、と思いましたが、それはまた別の話にします。

以上、 チバユキ (@batchicchi) がお送りしました。

参考

脚注

  1. ゲタ記号です。チョイスは何となくです。