You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Amplify未授权角色附加的AppConfig策略失效问题求助

问题:未授权IAM角色无法调用AppConfig的StartConfigurationSession接口

使用Amplify Gen.2搭配自定义CDK为Swift iOS应用部署AWS后端,CDK构造中实现了AWS AppConfig服务,并为已授权和未授权IAM角色配置了相同的访问策略(未授权角色已启用)。

iOS应用通过Amplify包及aws-sdk-swift中的AWSAppConfigData模块获取配置,部署过程无报错,用户登录状态下可正常获取AppConfig配置,但未登录时出现如下权限错误:

User: arn:aws:sts::xxx:assumed-role/amplify-xxx-sandbox001-s-amplifyAuthunauthenticate-xxx/CognitoIdentityCredentials is not authorized to perform: appconfig:StartConfigurationSession on resource: arn:aws:appconfig:eu-central-1:xxx:application/xxx/environment/xxx/configuration/xxx because no session policy allows the appconfig:StartConfigurationSession action

在AWS控制台中查看,已授权和未授权角色均附加了相同的策略,且IAM策略模拟器测试两个角色的权限均正常。怀疑存在优先级更高的策略阻止未授权访问,以下是相关代码,寻求排查方向。

相关CDK代码

import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as appconfig from 'aws-cdk-lib/aws-appconfig';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as cdk from 'aws-cdk-lib';

export class AppConfigConstruct extends Construct {
    constructor(scope: Construct, id: string, props: AppConfigConstructProps) {
        super(scope, id);

        /*
        Creating AppConfig ...
        */

        // Creating managed policy
        const appConfigPolicy = new iam.ManagedPolicy(this, `${id}AppConfigPolicy`, {
          statements: [
            new iam.PolicyStatement({
              sid: `StartGetConfiguration`,
              effect: iam.Effect.ALLOW,
              actions: [
                'appconfig:StartConfigurationSession',
                'appconfig:GetLatestConfiguration'
              ],
              resources: [
                `arn:aws:appconfig:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:application/${appConfigAppId}/environment/${appConfigEnvId}/configuration/${appConfigId}`
              ]
            })
          ]
        });

        // Attaching to unauth role
        const unauthenticatedUserIamRole = iam.Role.fromRoleArn(this, 'UnauthRole', props.unauthenticatedUserIamRoleArn);
        unauthenticatedUserIamRole.addManagedPolicy(appConfigPolicy);

        // Attaching to auth role
        const authenticatedUserIamRole = iam.Role.fromRoleArn(this, 'AuthRole', props.authenticatedUserIamRoleArn);
        authenticatedUserIamRole.addManagedPolicy(appConfigPolicy);
    }
}

相关Swift代码

import Amplify
import AWSPluginsCore
import SmithyIdentity
import AWSAppConfigData

final public class Configuration {
    public static let shared = Configuration()
    private init() {}

    private func credentialIdentityResolver() async throws -> StaticAWSCredentialIdentityResolver {

        guard let awsCredentialsProvider = try await Amplify.Auth.fetchAuthSession() as? AuthAWSCredentialsProvider else {
            throw ConfigurationError.noAuthAWSCredentialsProvider
        }

        guard let credentials = try awsCredentialsProvider.getAWSCredentials().get() as? AWSTemporaryCredentials else {
            throw ConfigurationError.noAWSTemporaryCredentials
        }

        let identity = AWSCredentialIdentity(
            accessKey: credentials.accessKeyId,
            secret: credentials.secretAccessKey,
            expiration: .now.addingTimeInterval(.minutes(1)),
            sessionToken: credentials.sessionToken
        )
        return try StaticAWSCredentialIdentityResolver(identity)
    }


    public func setup(applicationIdentifier: String) async {
        do {
            let staticAWSCredentialIdentityResolver = try await credentialIdentityResolver()

            let appConfigDataClientConfiguration = try await AppConfigDataClient.AppConfigDataClientConfiguration(
                awsCredentialIdentityResolver: staticAWSCredentialIdentityResolver,
                region: "eu-central-1"
            )

            let appConfigClient = AppConfigDataClient(
                config: appConfigDataClientConfiguration
            )

            let startConfigurationSessionInput = StartConfigurationSessionInput(
                applicationIdentifier: applicationIdentifier,
                configurationProfileIdentifier: "SSMConfigProfile",
                environmentIdentifier: "ProdEnvironment",
                requiredMinimumPollIntervalInSeconds: nil
            )

            let sessionResponse = try await appConfigClient.startConfigurationSession(
                input: startConfigurationSessionInput
            )

            guard let token = sessionResponse.initialConfigurationToken else {
                throw ConfigurationError.noInitialConfigurationToken
            }

            let configResponse = try await appConfigClient.getLatestConfiguration(
                input: GetLatestConfigurationInput(configurationToken: token)
            )

            guard let configData = configResponse.configuration, !configData.isEmpty,
                  let configString = String(data: configData, encoding: .utf8) else {
                return
            }
        } catch {
            Log.configuration.error("Error - \(error)")
        }
    }
}

排查方向

  • 检查Cognito身份池的未授权角色会话策略:Cognito身份池可能会给临时凭证附加会话策略,该策略优先级高于角色附加的托管/内联策略。进入Cognito控制台→目标身份池→编辑身份池,查看未授权角色的“会话策略”是否存在,若有则确认是否允许appconfig:StartConfigurationSession和appconfig:GetLatestConfiguration动作。
  • 验证CDK中角色ARN准确性:确认props.unauthenticatedUserIamRoleArn指向的是正确的未授权角色,避免CDK附加策略时选错角色。
  • 检查角色的权限边界:如果未授权角色设置了权限边界,即使附加了允许策略,权限边界也会限制实际可执行的动作。进入IAM控制台找到该角色,查看“权限边界”标签,确认边界策略允许AppConfig相关动作。
  • 确认AppConfig资源ARN匹配:CDK中构造的资源ARN是否和报错中的ARN完全一致?比如应用ID、环境ID、配置ID是否正确,避免变量替换错误导致策略资源不匹配。
  • 验证临时凭证关联的角色:在iOS端打印credentials的roleArn字段,确认未登录时的临时凭证确实关联了预期的未授权角色。
  • 检查Amplify Auth未授权配置:确保Amplify Auth已正确启用未授权访问,在amplifyconfiguration.json中检查auth模块的allowGuestAccess是否设为true。

内容的提问来源于stack exchange,提问作者Marco Boerner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 20:53:17