SCSKã®çã§ãã åŒç€Ÿ AWS ç°å¢ã§éçºããã¢ããªã±ãŒã·ã§ã³ãã客ããã® AWS ç°å¢ã«ç§»è¡ããã®ã§ãããç§»è¡åœåã¯æ£åžžåäœããªãã£ããããåå åãåãã®ããã«ã¿ã€ãã«ã®å
容ã詊ããŸããããšããå
容ãšãªããŸãã èæ¯ ã客ããã® AWS ç°å¢ïŒAWSãããžã¡ã³ãã³ã³ãœãŒã«ïŒäžããå®è¡ã§ãããªãã¬ãŒã·ã§ã³ã IAM æš©éã«ããéå®ãããŠããããšãã話㯠ååã®ãšã³ã㪠ã§ã説æããéããªã®ã§ãããæ§ç¯ãå®è£
ã«äœ¿çšãã倿Žé¢é£ã®æš©éã ãã§ãªããåç
§é¢é£ã®æš©éã«ã€ããŠãä»äžå¯Ÿè±¡ãçµãããŠããŸããããã®1ã€ãšã㊠ãIAM ããŒã«/ããªã·ãŒã«å²ãåœãŠãããŠãã IAM æš©éã確èªã§ããªãã ãšããå¶éããããŸããã å
ã
ãã®ã客ããã® AWS ç°å¢ã¯éå»ãã§ãŒãºã®æ¡ä»¶ãå«ããŠæ°å¹Žåãã䜿çšããŠããã®ã§ãããåœå㯠StepFunctions ã Lambda ã䜿çšã㊠Redshift ã«ããŒã¿ãæå
¥ããããã® ETL/ELT ãå®è£
ãããããªå
容ãã¡ã€ã³ã§ãããå
ã
ããã¯ãšã³ãåŽã®éçºã¯ããã³ããšã³ãåŽãšæ¯èŒããŠææ
£ããŠããããšãããšã©ãŒçºçæã«ãŸã確èªãã¹ã CloudWatchLogs ã«ã¯åç
§æš©éããã£ãããããã®å¶éããã£ãŠããããŸã§åé¡ãæããŠããŸããã§ãããïŒãã¡ãããããåå ã§ãšã©ãŒã®åãåãã«èŠåŽããããšãéå»ãããŸãããã»ã»ïŒãŸããåãåãã®çµæ IAM æš©éã®åé¡ãçãããå Žåã«èšå®å
容ã®é瀺ã远å èšå®ããé¡ãããããšã¯åé¡ãããŸããã§ããã ãã ãæ¬æ¡ä»¶äºäŸã«ãŠå®è£
ããã¢ããªã±ãŒã·ã§ã³ã¯ãããŸã§ãšç°ãªãããã³ããšã³ã/ããã¯ãšã³ãäž¡æ¹ã®éçºèŠçŽ ãå«ãã§ããããã€äœ¿çšãããµãŒãã¹ãå€ãããããããŸã§ãšæ¯èŒããŠãšã©ãŒçºçæã®åå åãåããç©¶æã«æéåã£ãŠããŸãããšããããŸããã仿¯ãè¿ããšãä»ååãäžããå
容ããã®å»¶é·ç·äžã«ãã£ãã®ã ãªãšæããŸããã»ã» ã¢ããªã±ãŒã·ã§ã³ç§»è¡åŸã®åäœç¢ºèªäžã«ãšã©ãŒçºç åé ã§èšèŒããéããåŒç€Ÿ AWS ç°å¢ã§éçºããã¢ããªã±ãŒã·ã§ã³ãã客ããã® AWS ç°å¢ã«ç§»è¡ããåŸã®åäœç¢ºèªäžã«ãCognito ãŠãŒã¶èªèšŒåŸã«ã¯ã©ã€ã¢ã³ãåŽãã AppSync API ãå©ããã¿ã€ãã³ã°ã§ä»¥äžã®ãããªãšã©ãŒãçºçããŸããã { message: "Unauthorized", recoverySuggestion: `If you're calling an Amplify-generated API, make sure to set the "authMode" in generateClient({ authMode: '...' }) to the backend authorization rule's auth provider ('apiKey', 'userPool', 'iam', 'oidc', 'lambda')` } å
ã«ãšã©ãŒçºçã®åå ã«ã€ããŠãã¿ã°ããããŠããŸããšãåçŽã« Cognito ID ããŒã«ã®ãèªèšŒãããããŒã«ãçµç±ã§ä»äžããã IAM ããªã·ãŒã«ããã appsync:graphql æš©éã® resource å¥ãæ£ããèšå®ãããŠããªãã£ãããšã«ãããçµæãšããŠå IAM æš©éãäžè¶³ããŠããããšã«ãããã®ã§ãããïŒæ¬æ¡ä»¶äºäŸã«ããã AppSync ã® èªå¯æ¹åŒã«ã€ããŠã¯ã ãã®ãšã³ã㪠ã®å
容ããåç
§ãã ããïŒ ãšããããäžèšã¢ããªã±ãŒã·ã§ã³åŽã®ãã°ããã ãã§ã¯åœååå ãæŽããŸããã§ããã message ã®å
容ã¯ãUnauthorizedããšããåèªã®ã¿ãªã®ã§åå ç©¶æã«ã¯äžååã§ãããã〠Cognito ãŠãŒã¶èªèšŒåŸã« AppSync API ãå©ããŠããä»¥äž Unauthorized ãšå€å®ãããŠããçç±ããããŠããããè¯ãåãããªãã recoverySuggestion ã®å
容㯠Amplify ã®ã¹ããŒãå®çŸ©ã«ããã @auth å¥ã®èšå®ã«é¢ããå
å®¹ãšæãããããããåŒç€Ÿç°å¢ã«ãããŠã¯åãèšå®ã§åé¡ãªãåäœããŠãã以äžãèšå®å€æŽããŠãæ¬è³ªçãªè§£æ±ºã«ç¹ãããªãããšãæšæž¬ãããã®ã§ãã¡ããæ
å ±ãšããŠã¯åèã«ãªããªããšå€æã ã§ã¯ AppSync ã®ãã°ã«äœãããåºãŠããã®ã§ã¯ïŒãšèã㊠CloudWatchLogs ãèŠãŠã¿ãã®ã§ããã»ã» { "logType": "RequestSummary", "requestId": "eafb8d66-f76c-4100-a836-e860dbca1808", "graphQLAPIId": "<graphQLAPIId>", "statusCode": 401, "latency": 63460261 } bd4f8c67-6eb0-4c98-8c6a-432e6f9f57dd Response Headers: {x-amzn-ErrorType=UnauthorizedException} 以äžã®ããã«ãã»ãŒã¢ããªã±ãŒã·ã§ã³åŽã®ãã°ãšåãçšåºŠã®æ
å ±éãããªãã£ããããåããåèã«ãªããã ãªããæ¬ãšã³ããªã®äœæã«ãããæå
ã®ç°å¢ã§åçŸè©Šéšã宿œããŠã¿ãã®ã§ãããAppSync ã®ãã°ã¬ãã«ãããã¹ãŠãã«èšå®å€æŽããŠããã°ã®æ
å ±éã¯ç¹ã«å€ãããŸããã§ãããã ã¯ã©ã€ã¢ã³ããã AppSync API ãå©ããŠããã¿ã€ãã³ã°ã§ãšã©ãŒãçºçããŠãã以äžãçŸæç¹ã§ã¯ãã以äžã®ãã°æ
å ±ãåºåãããŠããªãããšãããæ¹ããŠãã®ãUnauthorizedããšããã¡ãã»ãŒãžããåå ãèããŠã¿ãã®ã§ããã Cognito ã®ãèªèšŒãããããŒã«ãã§æå®ããŠãã IAM ããŒã«/ããªã·ãŒã« appsync:graphql æš©éãä»äžãããŠããªã Cognito ã§ã®ãŠãŒã¶èªèšŒåŸããèªèšŒãããããŒã«ãã§æå®ããŠãã IAM ããŒã«ãäœããã®åå ã§æ£åžžã« AssumeRole ãããŠããªã ã®ã©ã¡ããã§ã¯ãªãããšèããŸãããçç±ã¯ä»¥äžã®éãã§ãã å
è¿°ããéã Cognito ãŠãŒã¶èªèšŒã«ã€ããŠã¯æåããŠããããŠãŒã¶æªèªèšŒã®ç¶æ
ã§å®è¡ããããšã¯èããããã ãããããŠãŒã¶æªèªèšŒã§ã¯ã¢ããªã±ãŒã·ã§ã³äžãã AppSync API ãå®è¡ããç»é¢ã«é·ç§»ããªãã ã€ãŸãèããããå¯èœæ§ã¯ãæ£åžžã«ãèªèšŒãããããŒã«ãã§æå®ããŠãã IAM ããŒã«ã AssumeRole ãããªãã£ãããAssumeRole ããããã®ã® IAM æš©éãäžè¶³ããŠããããã®ã©ã¡ãããšæšæž¬ã ããã¯ãšã³ãçšã® Lambda ãã㯠AppSync API ãæ£åžžã«å®è¡ã§ããŠããããšãããAppSync åŽã®èšå®ã«ã€ããŠã¯äžæŠèæ
®å€ã å³å¯ã«ã¯åã
ã®ã¹ããŒã/ãªãŸã«ã/颿°å®çŸ©ãªã©ã誀ã£ãŠããå¯èœæ§ã¯ãããããããã AppSync API ã®å®è¡ããã§ããªãããšãéã¿ããšãã以åã®åé¡ãšå€æã ãã®å
ã1.ã«ã€ããŠã¯å
è¿°ãã ãIAM ããŒã«/ããªã·ãŒã«å²ãåœãŠãããŠãã IAM æš©éã確èªã§ããªãã å¶éãããããšããçŽæ¥ IAM ããŒã«/ããªã·ãŒã®èšå®ç¢ºèªãã§ããªãã£ããããåŒç€Ÿç°å¢ã§åçŸè©Šéšã宿œãããšããåããããªãšã©ãŒã¡ãã»ãŒãžãçºçããããšã確èªã§ããŸããã2.ã«ã€ããŠã¯ä»¥äžã®çç±ããå¯èœæ§ã¯äœããšèããããããã1.ã®å¯èœæ§ãæ¿åãšããçµè«ã«ãªããŸããã ãèªèšŒãããããŒã«ãã«æå®ãã IAM ããŒã«ãèšå®ãããŠããããšãã客ããã® AWS ç°å¢äžã§ç¢ºèªã§ããŠããã äžèšãèžãŸãããšãæ£åžžã« AssumeRole ã§ããªãåå 㯠IAM ããŒã«ã«èšå®ããCognito ID ããŒã«ãšã®ä¿¡é Œé¢ä¿èšå®çšåºŠããæãä»ããªãã£ãããåŒç€Ÿç°å¢ã§æå³çã«èšå®ãééããå Žåã¯ä»¥äžã®ããã«å¥ã®ãšã©ãŒãçºçããããšãåãã£ããããã®å¯èœæ§ã¯ãªãããšãããšä»ã®å¯èœæ§ãæãæµ®ãã°ãªããã InvalidIdentityPoolConfigurationException: Invalid identity pool configuration. Check assigned IAM roles for this pool. ãã ãããã«ããã£ãŠãã®äºè±¡ãçºçããã¿ã€ãã³ã°ãã ã客ãããããèªèšŒãããããŒã«ãã«èšå®ããŠãã IAM ããŒã«/ããªã·ãŒã®èšå®ïŒä¿®æ£ïŒãå®äºãããšé£çµ¡ãåããçŽåŸ ã ã£ãã®ã§ãããã»ã»ãçµç·¯ãšããŠãå
ã
ãã¡ãããèšå®äŸé Œãã IAM ããŒã«/ããªã·ãŒã®å
容ãäžéšäžæ£ç¢ºã ã£ãããä¿®æ£ãäŸé ŒããŠããã®ã§ããããã®å¯Ÿå¿ãã客ãããå®äºãããšèšã£ãŠããåŽããèšå®å
容ã®é瀺ãåä¿®æ£ãå床ãé¡ããããšããã®ã¯ãã客ããã«å¯Ÿã㊠ããšã©ãŒåºãŠããã ãã©æ¬åœã«ã§ããŠããã§ãããïŒå€§äžå€«ã§ããïŒã ã¿ãããªãã¥ã¢ã³ã¹ãèšå€ã«å«ãã§ãããšæããããããªããšææ
®ããŠããŸãã»ã»å
éšã§çžè«ãããšããã念ã®ããããå°ãè£åãããŠããæèšºããããšããæ¹åæ§ã«ãªããŸããã ãã¡ãããã客ããïŒããã³ãïŒãšã¯ããçšåºŠãã©ã³ã¯ã«ã³ãã¥ãã±ãŒã·ã§ã³ãåãããããªé¢ä¿æ§ã¯ããã®ã§ãããå³å¯ã«ã¯ã客ããã® AWS ç°å¢ã管çããŠããã®ã¯ã客ããïŒããã³ãïŒãšã¯å¥ã®çµç¹ã§ãã£ãããšããããã®ããããèæ
®ãããšããå°ãæ
éã«é²ããæ¹ãè¯ããªãšã»ã» å
·äœçã«ã¯ã2.ã®å¯èœæ§ã®æç¡ïŒïŒAssumeRole èªäœãæ£åžžã«åäœããŠãããã©ããïŒãŸã§ãã客ãã AWS ç°å¢ã§ç¢ºèªããŠããã察象 IAM ããŒã«/ããªã·ãŒã®èšå®å
容ã®é瀺ãåä¿®æ£ããé¡ãããããšã«ããŸãããã客ãã AWS ç°å¢äžã®æš©éäžè¶³ã§ç¢ºèªã§ããªãå Žåã¯äžæŠè«Šããä»ãªãã§ãããæèšºããåã«ã§ããããšã¯ãã£ãŠããããšããããšã§ã æ¬é¡ ãšããããšã§ããããæ¬é¡ã§ãã調ã¹ããšãããAssumeRole ã®ãã°ã¯ CloudTrail ã«åºåããããšã®ããšã§ãã客ãã AWS ç°å¢ã§ CloudTrail ãéãããšããåé¡ãªãäžèº«ãèŠãããã®ã§ããã°ã®ç¢ºèªãé²ããŸããã AWS CloudTrail による IAM および AWS STS の API コールのログ記録 - AWS Identity and Access Management AWS STS ã«ãã IAM ããã³ AWS CloudTrail ã®ãã°èšé²ã«ã€ããŠèª¬æããŸãã docs.aws.amazon.com å
·äœçã«ã¯ãäžèš URL ã«ããã ãAssumeRoleWithWebIdentityã ã€ãã³ãã該åœããŸãããã£ãŠãã客ãã AWS ç°å¢ã®ã¢ããªã±ãŒã·ã§ã³ããæå³çã«ãšã©ãŒãçºçãããäžã§ãåæå»ååŸã«ãAssumeRoleWithWebIdentityãã€ãã³ããçºçããŠãããã©ããã確èªããŸããã ãã®çµæã以äžã¹ã¯ãªãŒã³ã·ã§ããã®ãããªãAssumeRoleWithWebIdentityãã€ãã³ããçºçããŠãããã°ã確èªã§ããŸããããŸãããåç
§ããããªãœãŒã¹ãã®é»å¡ãããŠãããªãœãŒã¹åããCognito ID ããŒã«ã®ãèªèšŒãããããŒã«ãã«èšå®ããŠãã IAM ããŒã«ãšåäžã§ããããã£ãŠãã¢ããªã±ãŒã·ã§ã³ãã AppSync API ãå®è¡ããããšããæã«ãæ³å®éãã® IAM ããŒã«ã Cognito ID ããŒã« çµç±ã§ AssumeRole ãããŠããããšã確èªã§ããŸããã ãã£ãŠãå
è¿°ã®æ¹ééã Cognito ID ããŒã«ã®ãèªèšŒãããããŒã«ãã«èšå®ããŠãã IAM ããŒã«/ããªã·ãŒã®èšå®ã誀ã£ãŠããå¯èœæ§ãé«ããšå€æãã客ããã«èšå®å
容ã®é瀺åã³ãäŸé Œãããšãããåé ã«èšèŒããéã appsync:graphql æš©éã® resource å¥ãæ£ããèšå®ãããŠããªãã£ãããšã倿ãããããåä¿®æ£ãäŸé ŒããŠç¡äºã¯ããŒãºãšçžæããŸããã 以äžã® CloudTrail ã¹ã¯ãªãŒã³ã·ã§ããããã°ã¯åŒç€Ÿç°å¢ã§åçŸãããã®ã§ãããäºæ¿ãã ããã ã¡ãªã¿ã«ãJSON 圢åŒã® CloudTrail ãã°ãåç»é¢ãã以äžã®ããã«ç¢ºèªã§ããŸããä»å確èªãããã£ã芳ç¹ã¯äžèšç»é¢ãã確èªã§ããããã詳现ã«ã€ããŠã¯æ¬ãšã³ããªã§ã¯çç¥ããŸãã { "eventVersion": "1.08", "userIdentity": { "type": "WebIdentityUser", "principalId": "cognito-identity.amazonaws.com:<COGNITO_APP_ID>:<COGNITO_APP_USR_NAME>", "userName": "<COGNITO_APP_USR_NAME>", "identityProvider": "cognito-identity.amazonaws.com" }, "eventTime": "2025-02-24T14:15:12Z", "eventSource": "sts.amazonaws.com", "eventName": "AssumeRoleWithWebIdentity", "awsRegion": "ap-northeast-1", "sourceIPAddress": "<SOURCE_IP_ADDRESS>", "userAgent": "aws-internal/3 aws-sdk-java/1.12.780 Linux/4.14.355-275.582.amzn2.x86_64 OpenJDK_64-Bit_Server_VM/25.432-b06 java/1.8.0_432 kotlin/1.3.72 vendor/Oracle_Corporation cfg/retry-mode/standard cfg/auth-source#imds", "requestParameters": { "roleArn": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/service-role/<COGNITO_ROLE_NAME>", "roleSessionName": "CognitoIdentityCredentials" }, "responseElements": { "credentials": { "accessKeyId": "ASIA5NBR5LH3GUDX65GT", "sessionToken": "<ENCODED_SESSION_ROKEN_BLOB>", "expiration": "Feb 24, 2025, 3:15:12 PM" }, "subjectFromWebIdentityToken": "<COGNITO_APP_USR_NAME>", "assumedRoleUser": { "assumedRoleId": "AROA5NBR5LH3HYAQNDM6Y:CognitoIdentityCredentials", "arn": "arn:aws:sts::<AWS_ACCOUNT_ID>:assumed-role/<COGNITO_ROLE_NAME>/CognitoIdentityCredentials" }, "provider": "cognito-identity.amazonaws.com", "audience": "<COGNITO_APP_ID>" }, "additionalEventData": { "identityProviderConnectionVerificationMethod": "IAMTrustStore", "RequestDetails": { "endpointType": "regional", "awsServingRegion": "ap-northeast-1" } }, "requestID": "ef3bb0c4-ed23-472e-9a93-3377cd9928dc", "eventID": "93c286a7-1732-4428-93e5-15875fa6b2a3", "readOnly": true, "resources": [ { "accountId": "<AWS_ACCOUNT_ID>", "type": "AWS::IAM::Role", "ARN": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/service-role/<COGNITO_ROLE_NAME>" } ], "eventType": "AwsApiCall", "managementEvent": true, "recipientAccountId": "<AWS_ACCOUNT_ID>", "eventCategory": "Management", "tlsDetails": { "tlsVersion": "TLSv1.3", "cipherSuite": "TLS_AES_128_GCM_SHA256", "clientProvidedHostHeader": "sts.ap-northeast-1.amazonaws.com" } } ãŸãšã ã€ãã€ãæžããŠããããæ¬é¡ããåæ®µã®è©±é¡ã§ããèæ¯ããšã©ãŒçºçæã®åå åãåãã®å
å®¹ã®æ¹ãé·ããªã£ãŠããŸããŸããããã¿ãŸããããã ãã客ããã® AWS ç°å¢ãžã®ã¢ããªã±ãŒã·ã§ã³ç§»è¡ã«é¢ããŠã¯ããã¡ãã®ãšã³ããªã§èšèŒããå
容ãå«ãæçµçã«æ£åžžã«çšŒåããããŸã§çµæ§ãªåŽåãèŠããã®ã§ãåå¿ããŠãå¿ããªãå
ã«ãŸãšããŠããããã£ããã§ããããåŸãå
·äœçãªè§£æ±ºçã«ã€ããŠèšèŒããã®ã¯ãã¡ãããããã«è³ããŸã§ã®æèã®ããã»ã¹ãåãããŠãŸãšããŠãããæ¹ããå°ãªããšãèªåã«ãšã£ãŠã¯ããææçŸ©ãªèšé²ã«ãªããšããã®ããããŸãã ãããã«ãããæ¬èšäºãã©ãªããã®åœ¹ã«ç«ãŠã°å¹žãã§ãã