jcode Phone-Server AWS IAM 最小权限设计:从 AdministratorAccess 到三平面角色与防锁死迁移
jcode Phone-Server AWS IAM 最小权限设计从 AdministratorAccess 到三平面角色与防锁死迁移【免费下载链接】jcodeThe most RAM efficient harness项目地址: https://gitcode.com/GitHub_Trending/jcod/jcode本文基于 jcode 仓库中 Phone-Server IAM 最小权限评估文档 展开讲解如何把一条长期持有AdministratorAccess的部署凭据拆解为「日常操作 / 重建供应 / 紧急管理」三个互不越权的权限平面并完整覆盖各运行时角色的 IAM 策略、只读盘点命令、防锁死迁移步骤与验收标准。读完后你将掌握如何依据真实 API 调用证据为 EC2、Lambda、API Gateway、Bedrock 编写最小权限策略以及如何在不锁死账号的前提下安全移除管理员权限并轮换凭据。背景一个部署凭据持有 AdministratorAccess 意味着什么jcode 的 phone-server 是一个自管理的 AWS 云主机一台 EC2 实例运行jcode serveWebSocket 网关手机iOS 应用或 SSH 客户端无需笔记本中转即可驱动 jcode 会话。部署位于 AWS 账号302154194530、区域us-east-1实例i-08214cf66cd3f80c7弹性 IP54.196.207.97见 部署说明。该部署的 IAM 评估起始于一次设计评审评估日期为 2026-07-12。评估文档的核心结论是部署用户jade-deploy不应保留AdministratorAccess——一条被泄露的长期部署凭据当前可以修改身份、关闭成本护栏、外泄数据、创建任意基础设施并在账号任何位置建立持久化。文档同时说明了一个务实的现状实际加固详见 README 的 Live deployment 章节已经落地并验证唯一有意保留的缺口是jade-deploy上的AdministratorAccess它在一条独立的 root/MFA 恢复登录路径被验证之前不会被移除。目标架构是用「只能 assume-role 的主体 三个独立权限平面」替换现状JcodePhoneOperator日常部署与现有栈的维护JcodePhoneProvisioner低频的重建操作受 MFA 门禁、限时最长会话 1 小时、限定us-east-1与jcode-phone-*资源、并受运行时边界约束独立的紧急管理员路径受 MFA 保护、绝不被自动化使用用于在移除现有管理员挂载时避免锁死。另外实例角色上的AmazonBedrockFullAccess也应替换为仅推理权限——从源码看Bedrock provider 只做模型目录发现和流式对话ConverseStream并不需要 Bedrock 管理权限。证据链策略必须匹配真实的 API 调用最小权限策略的前提是精确知道每个组件实际调用了哪些 AWS API。评估文档给出的仓库证据如下均可在当前仓库中逐一验证组件实际调用的 AWS API源码依据Wake Lambdaec2:DescribeInstances、ec2:StartInstanceswake-lambda.py 中ec2.describe_instances(...)与ec2.start_instances(InstanceIds[INSTANCE_ID])Wake LambdaSSM 配对路径ssm:DescribeInstanceInformation、ssm:SendCommandAWS-RunShellScript文档、ssm:GetCommandInvocationwake-lambda.py 的ssm_online()与fetch_pair_code()Breaker Lambdaec2:DescribeInstances、ec2:StopInstances、sns:Publish至arn:aws:sns:us-east-1:302154194530:jcode-guard-warnbreaker-lambda.pyEC2 实例上的 Bedrock providerListFoundationModels、ListInferenceProfiles、流式 Converse由bedrock:InvokeModelWithResponseStream授权jcode-provider-bedrock/src/lib.rs 的目录刷新逻辑与 流式调用Wake Lambda 的 SSM 配对流程值得细看因为它决定了权限要放大到什么程度fetch_pair_code()通过ssm.send_command(InstanceIds[INSTANCE_ID], DocumentNameAWS-RunShellScript, ...)在目标实例上以ec2-user身份执行jcode pair随后轮询ssm.get_command_invocation直到命令进入终态再从输出中用正则提取 6 位配对码并生成jcode://pair?...深链。评估文档因此明确提示ssm:SendCommand应被视为「特权远程代码执行」必须严格限定到该唯一实例和 AWS 托管文档。Bedrock 侧还有一个细节provider 中由环境变量JCODE_BEDROCK_VALIDATE_STS控制的 STS 身份校验validate_credentials_if_requested默认关闭正常路径不需要额外服务权限——这正是评估文档中「provider 的可选 STS 身份校验不需要额外服务权限」这一说法的源码依据。同时当 AWS 拒绝请求时provider 会直接提示需要bedrock:InvokeModel、bedrock:InvokeModelWithResponseStream、bedrock:ListFoundationModels、bedrock:ListInferenceProfiles四类权限错误提示与本文给出的策略语句一一对应。声明的命名资源清单类型资源EC2 实例arn:aws:ec2:us-east-1:302154194530:instance/i-08214cf66cd3f80c7弹性 IP54.196.207.97分配 ID 需另行盘点Lambdajcode-phone-wakeLambdajcode-guard-breakerAPI Gateway v28c3wp4cbagSNSjcode-guard-stop与jcode-guard-warnCloudWatch 告警jcode-bedrock-tokens-warn、jcode-bedrock-tokens-stop无效的账单告警已被 Budget/SNS 熔断路径替代Budgetjcode-dev-monthly-costBedrock 模型路由us.anthropic.claude-opus-4-6-v1实态核查结果评估完成后账号已通过jcode-bedrockprofile 做了全面盘点运行时角色名、Lambda 角色、EC2 实例与安全组、弹性 IP、Budget 订阅者、CloudWatch 告警、日志保留、API Gateway stage、S3/DynamoDB 资源、访问密钥元数据均直接验证过。当前实态为Wake Lambda 已改用 SSM 配对所有公网入站 EC2 端口已关闭根 EBS 卷已加密CloudTrail 与 Access Analyzer 已启用旧的部署密钥处于停用状态。这与 README 安全说明 中「实例角色为推理权限 SSM 受管实例访问」「7644 端口不再公开、legacy pair 服务已停用」的描述一致。目标身份设计三平面与 assume-only 主体人类访问首选终态人类操作者使用 IAM Identity Center 或其他联合身份operator 与 provisioner 两个角色的 assume 都要求 MFA不为人类访问创建长期密钥jade-deploy仅在迁移期间保留观察期结束后删除。如果过渡期必须保留 IAM 用户则jade-deploy无控制台密码、无任何服务权限唯一权限是对两个部署角色的sts:AssumeRole它不能修改自己、策略、访问密钥、MFA 设备或角色信任策略。jade-deploy的 assume-only 策略{ Version: 2012-10-17, Statement: [ { Sid: AssumePhoneServerRolesOnly, Effect: Allow, Action: sts:AssumeRole, Resource: [ arn:aws:iam::302154194530:role/jcode-phone/JcodePhoneOperator, arn:aws:iam::302154194530:role/jcode-phone/JcodePhoneProvisioner ] } ] }两个角色的信任策略都应要求 MFA对人类 IAM 主体{ Version: 2012-10-17, Statement: [ { Effect: Allow, Principal: { AWS: arn:aws:iam::302154194530:user/jade-deploy }, Action: sts:AssumeRole, Condition: { Bool: { aws:MultiFactorAuthPresent: true }, NumericLessThan: { aws:MultiFactorAuthAge: 3600 } } } ] }JcodePhoneProvisioner的最大会话时长设为 1 小时两个角色都不允许修改自己的信任策略或权限。对无人值守 CI使用独立的 OIDC 联合角色限定到具体仓库、分支/环境与 workflow不要为了 CI 而放宽人类角色的 MFA 信任。运行时策略实例与每个 Lambda 各用独立执行角色总原则实例与每个 Lambda 使用各自的执行角色运行时绝不复用部署角色。EC2 实例仅推理权限用以下客户管理策略替换AmazonBedrockFullAccess。注意两点List*操作必须Resource: *推理资源刻意只覆盖已配置的 Claude Opus 4.6 跨区 profile 及其底层 foundation model——因为跨区推理可能路由到us-east-1之外只写单区域的 foundation-model ARN 会失效。{ Version: 2012-10-17, Statement: [ { Sid: DiscoverBedrockModels, Effect: Allow, Action: [ bedrock:ListFoundationModels, bedrock:ListInferenceProfiles ], Resource: * }, { Sid: InvokeConfiguredClaudeProfile, Effect: Allow, Action: [ bedrock:InvokeModel, bedrock:InvokeModelWithResponseStream ], Resource: [ arn:aws:bedrock:us-east-1:302154194530:inference-profile/us.anthropic.claude-opus-4-6-v1, arn:aws:bedrock:*::foundation-model/anthropic.claude-opus-4-6-v1:0 ] } ] }应用前用bedrock list-inference-profiles核实确切的 inference-profile ARN 与底层模型 ID。如果部署的是 AWS 所有的 profile、或底层模型版本后缀不同应替换为返回的 ARN而不是放宽模型名通配。区域通配符是刻意为之因为 US 跨区推理 profile 可路由到多个 US 区域。测试完成后若所有生产路径都只用ConverseStream可移除bedrock:InvokeModel——保留它只是很小的兼容性余地不是管理权限。provider 的可选 STS 身份校验在正常操作中不需要额外服务权限见上文源码分析。这与源码行为吻合refresh_catalog() 先调list_foundation_models()收集模型 ID、推断 ON_DEMAND / INFERENCE_PROFILE 支持类型、标记 LEGACY 模型再调list_inference_profiles()收集 profile 与优选路由流式推理 走converse_stream()。目录刷新即/refresh-model-list的底层实现缺少bedrock:ListInferenceProfiles时源码会明确报错要求授权错误提示。Wake Lambda{ Version: 2012-10-17, Statement: [ { Sid: ReadTargetInstanceState, Effect: Allow, Action: ec2:DescribeInstances, Resource: * }, { Sid: StartTargetInstanceOnly, Effect: Allow, Action: ec2:StartInstances, Resource: arn:aws:ec2:us-east-1:302154194530:instance/i-08214cf66cd3f80c7 }, { Sid: WriteOwnLogs, Effect: Allow, Action: [ logs:CreateLogStream, logs:PutLogEvents ], Resource: arn:aws:logs:us-east-1:302154194530:log-group:/aws/lambda/jcode-phone-wake:* } ] }日志组应在开通期创建并配置保留策略而不是在运行时授予*上的logs:CreateLogGroup。当前部署已采用 SSM 唤醒/配对实现legacy 的公网:7644路径已禁用因此还要追加 SSM 语句{ Version: 2012-10-17, Statement: [ { Sid: ReadManagedInstanceStatus, Effect: Allow, Action: ssm:DescribeInstanceInformation, Resource: * }, { Sid: RunPairCommandOnTargetOnly, Effect: Allow, Action: ssm:SendCommand, Resource: [ arn:aws:ec2:us-east-1:302154194530:instance/i-08214cf66cd3f80c7, arn:aws:ssm:us-east-1::document/AWS-RunShellScript ] }, { Sid: ReadPairCommandResult, Effect: Allow, Action: ssm:GetCommandInvocation, Resource: * } ] }该变体同时要求 EC2 角色上有 SSM 受管实例策略。建议它与 Bedrock 策略分开维护在 CloudTrail 中核对确切的 Systems Manager 调用并在操作可行时从AmazonSSMManagedInstanceCore收窄。始终记住ssm:SendCommand是特权远程代码执行范围必须锁定到那一台实例和 AWS 托管文档。wake-lambda.py 中ssm_online()与fetch_pair_code()的调用正是这三条语句对应的最小集合。Breaker Lambda{ Version: 2012-10-17, Statement: [ { Sid: ReadTargetInstanceState, Effect: Allow, Action: ec2:DescribeInstances, Resource: * }, { Sid: StopTargetInstanceOnly, Effect: Allow, Action: ec2:StopInstances, Resource: arn:aws:ec2:us-east-1:302154194530:instance/i-08214cf66cd3f80c7 }, { Sid: PublishGuardNotification, Effect: Allow, Action: sns:Publish, Resource: arn:aws:sns:us-east-1:302154194530:jcode-guard-warn }, { Sid: WriteOwnLogs, Effect: Allow, Action: [ logs:CreateLogStream, logs:PutLogEvents ], Resource: arn:aws:logs:us-east-1:302154194530:log-group:/aws/lambda/jcode-guard-breaker:* } ] }对应 breaker-lambda.py 的逻辑检查实例状态 → 若在运行则停止 → 向jcode-guard-warn主题发布「jcode circuit breaker fired」消息。该 Lambda 由 SNSjcode-guard-stop订阅触发预算超支 100% 时由 AWS Budget 通知。日常操作角色JcodePhoneOperator这个角色能更新和诊断现有资源但不能创建身份、创建任意计算、终止实例、释放 EIP、删除护栏或修改角色信任。以下策略中的...占位值应在只读盘点后替换。注意 API Gateway 资源形式刻意使用不含账号 ID 的管理 ARN。{ Version: 2012-10-17, Statement: [ { Sid: DescribePhoneServerInfrastructure, Effect: Allow, Action: [ ec2:DescribeInstances, ec2:DescribeInstanceStatus, ec2:DescribeAddresses, ec2:DescribeSecurityGroups, ec2:DescribeVolumes, cloudwatch:DescribeAlarms, cloudwatch:GetMetricData, cloudwatch:GetMetricStatistics, cloudwatch:ListMetrics ], Resource: * }, { Sid: ReadExistingFunctions, Effect: Allow, Action: [ lambda:GetFunction, lambda:GetFunctionConfiguration, lambda:GetPolicy ], Resource: [ arn:aws:lambda:us-east-1:302154194530:function:jcode-phone-wake, arn:aws:lambda:us-east-1:302154194530:function:jcode-phone-wake:*, arn:aws:lambda:us-east-1:302154194530:function:jcode-guard-breaker, arn:aws:lambda:us-east-1:302154194530:function:jcode-guard-breaker:* ] }, { Sid: OperateExistingInstance, Effect: Allow, Action: [ ec2:StartInstances, ec2:StopInstances, ec2:RebootInstances, ec2:ModifyInstanceAttribute ], Resource: arn:aws:ec2:us-east-1:302154194530:instance/i-08214cf66cd3f80c7 }, { Sid: DeployExistingFunctions, Effect: Allow, Action: [ lambda:UpdateFunctionCode, lambda:UpdateFunctionConfiguration, lambda:PublishVersion, lambda:CreateAlias, lambda:UpdateAlias, lambda:DeleteAlias, lambda:InvokeFunction ], Resource: [ arn:aws:lambda:us-east-1:302154194530:function:jcode-phone-wake, arn:aws:lambda:us-east-1:302154194530:function:jcode-phone-wake:*, arn:aws:lambda:us-east-1:302154194530:function:jcode-guard-breaker, arn:aws:lambda:us-east-1:302154194530:function:jcode-guard-breaker:* ] }, { Sid: ReadAndPatchExistingHttpApiRoot, Effect: Allow, Action: [ apigateway:GET, apigateway:PATCH ], Resource: arn:aws:apigateway:us-east-1::/apis/8c3wp4cbag }, { Sid: MaintainExistingHttpApiChildren, Effect: Allow, Action: [ apigateway:GET, apigateway:POST, apigateway:PUT, apigateway:PATCH, apigateway:DELETE ], Resource: arn:aws:apigateway:us-east-1::/apis/8c3wp4cbag/* }, { Sid: PassInstanceRoleToEc2Only, Effect: Allow, Action: iam:PassRole, Resource: arn:aws:iam::302154194530:role/jcode-phone/runtime/JcodePhoneInstance, Condition: { StringEquals: { iam:PassedToService: ec2.amazonaws.com } } }, { Sid: PassLambdaRolesToLambdaOnly, Effect: Allow, Action: iam:PassRole, Resource: [ arn:aws:iam::302154194530:role/jcode-phone/runtime/JcodePhoneWakeLambda, arn:aws:iam::302154194530:role/jcode-phone/runtime/JcodePhoneBreakerLambda ], Condition: { StringEquals: { iam:PassedToService: lambda.amazonaws.com } } }, { Sid: ReadPhoneLogs, Effect: Allow, Action: [ logs:DescribeLogStreams, logs:GetLogEvents, logs:FilterLogEvents ], Resource: [ arn:aws:logs:us-east-1:302154194530:log-group:/aws/lambda/jcode-phone-wake:*, arn:aws:logs:us-east-1:302154194530:log-group:/aws/lambda/jcode-guard-breaker:* ] }, { Sid: MaintainGuardTopics, Effect: Allow, Action: [ sns:GetTopicAttributes, sns:ListSubscriptionsByTopic, sns:Publish ], Resource: [ arn:aws:sns:us-east-1:302154194530:jcode-guard-stop, arn:aws:sns:us-east-1:302154194530:jcode-guard-warn ] }, { Sid: ReadNamedBudget, Effect: Allow, Action: budgets:ViewBudget, Resource: arn:aws:budgets::302154194530:budget/jcode-dev-monthly-cost } ] }推荐的进一步收紧若日常维护从不改动关机行为、实例类型、source/destination check 或附加的 profile移除ec2:ModifyInstanceAttributelambda:AddPermission、lambda:RemovePermission、sns:Subscribe、告警变更、预算变更留在 MFA 门禁的 provisioner 路径——这些操作可能导致调用暴露、通知外泄或成本控制被禁用API Gateway 的DELETE只允许在/apis/8c3wp4cbag/*之下日常角色不能删除 API 根绝不授予cloudwatch:DeleteAlarms、budgets:DeleteBudget、sns:DeleteTopic、ec2:TerminateInstances、ec2:ReleaseAddress或任何 IAM 写操作。重建/供应角色用 CloudFormation 执行角色收敛建删权限重建天然需要多个服务的创建/删除权限这些权限必须远离日常角色。最易维护的做法是把栈放进 CloudFormation、CDK 或 Terraform让人类只调用一个命名的栈部署角色。推荐模型人类JcodePhoneProvisioner仅jcode-phone-server*栈的 CloudFormation 操作、只读诊断以及仅对JcodePhoneCloudFormationExecution、条件iam:PassedToService cloudformation.amazonaws.com的iam:PassRoleJcodePhoneCloudFormationExecution承载下述服务权限只能被 CloudFormation 使用所有创建的资源打标签Projectjcode-phone-server与ManagedBycloudformation所有创建的运行时角色位于路径/jcode-phone/runtime/之下且必须携带JcodePhoneRuntimeBoundary权限边界。人类 provisioner 策略{ Version: 2012-10-17, Statement: [ { Sid: ManageNamedPhoneStack, Effect: Allow, Action: [ cloudformation:CreateStack, cloudformation:UpdateStack, cloudformation:DeleteStack, cloudformation:DescribeStacks, cloudformation:DescribeStackEvents, cloudformation:DescribeStackResources, cloudformation:GetTemplate, cloudformation:GetTemplateSummary, cloudformation:ListStackResources, cloudformation:CreateChangeSet, cloudformation:DescribeChangeSet, cloudformation:ExecuteChangeSet, cloudformation:DeleteChangeSet, cloudformation:ValidateTemplate ], Resource: [ arn:aws:cloudformation:us-east-1:302154194530:stack/jcode-phone-server*/*, arn:aws:cloudformation:us-east-1:302154194530:changeSet/jcode-phone-server*/* ] }, { Sid: ValidateNewTemplate, Effect: Allow, Action: cloudformation:ValidateTemplate, Resource: * }, { Sid: PassPhoneCloudFormationExecutionRole, Effect: Allow, Action: iam:PassRole, Resource: arn:aws:iam::302154194530:role/jcode-phone/JcodePhoneCloudFormationExecution, Condition: { StringEquals: { iam:PassedToService: cloudformation.amazonaws.com } } } ] }CloudFormation 执行角色应只允许如下服务/操作包络服务必需的重建操作范围/护栏EC2启动/终止那台服务器创建/打标签卷与 ENI创建/管理一个安全组分配/关联/释放一个 EIP修改关机行为描述 AMI/子网/VPCus-east-1请求/资源标签Projectjcode-phone-server仅批准的实例类型强制 IMDSv2批准的 VPC/子网IAM创建/更新/删除三个运行时角色与一个实例 profileput/delete 内联策略pass role仅限路径/jcode-phone/runtime/CreateRole要求边界 ARN绝不允许修改 deploy/provisioner/emergency 角色Lambda创建/更新/删除两个命名函数版本/别名权限函数 ARN 前缀jcode-phone-*与jcode-guard-breaker*项目标签API Gateway v2创建/更新/删除一个 HTTP API、integration、route、stage项目标签与栈所有权SNS创建/管理/删除jcode-guard-stop与jcode-guard-warn订阅精确的主题名 ARNCloudWatch创建/更新/删除四个命名告警精确的告警名 ARNLogs创建/配置/删除两个 Lambda 日志组精确的/aws/lambda/...ARN必须设置保留Budgets创建/更新/删除jcode-dev-monthly-cost精确的预算 ARNlambda:AddPermission/RemovePermission、sns:Subscribe/Unsubscribe、CloudWatch 告警变更与预算变更由执行角色而非日常操作角色持有从而保住集成与护栏维护能力同时不把这些高影响操作放进日常凭据。CloudFormation 执行角色不应持有通用的iam:*、organizations:*、account:*、sts:AssumeRole、kms:*、不受限的s3:*、不受限的secretsmanager:*也不能修改 provisioner、operator、emergency 角色、自身角色或自身边界。权限边界不是授权而是上限。用它作为运行时角色的最大值并配合各自的窄内联策略。边界只应允许实例的 Bedrock 目录发现与已配置模型推理权限Wake Lambda 的启动/描述与自身日志权限Breaker Lambda 的停止/描述、告警发布与自身日志权限。由于各角色权限不同边界可以取它们的并集每个角色的内联策略必须保持为更窄的子集。边界中还应显式拒绝 IAM、STS assume-role、Organizations、账号管理和访问密钥操作作为纵深防御。迁移前必须完成的只读盘点以下命令在现有管理员会话重新认证后运行全部只读、不做任何变更aws sts get-caller-identity aws iam list-attached-user-policies --user-name jade-deploy aws iam list-user-policies --user-name jade-deploy aws iam list-access-keys --user-name jade-deploy aws iam get-account-authorization-details phone-server-iam-before.json aws ec2 describe-instances --instance-ids i-08214cf66cd3f80c7 --region us-east-1 aws ec2 describe-addresses --public-ips 54.196.207.97 --region us-east-1 aws lambda get-function --function-name jcode-phone-wake --region us-east-1 aws lambda get-function --function-name jcode-guard-breaker --region us-east-1 aws apigatewayv2 get-api --api-id 8c3wp4cbag --region us-east-1 aws sns list-topics --region us-east-1 aws cloudwatch describe-alarms --alarm-name-prefix jcode- --region us-east-1 aws budgets describe-budget --account-id 302154194530 --budget-name jcode-dev-monthly-cost aws bedrock list-inference-profiles --type-equals SYSTEM_DEFINED --region us-east-1另需盘点至少 30 天的 CloudTrail 使用情况只有当某个 action 对应已知的部署/维护操作时才加入策略。Access Analyzer 基于 CloudTrail 的策略生成可以作为第二意见但不能替代人工审查因为很少用到的恢复操作可能根本不出现在日志里。防锁死迁移与凭据轮换15 步操作序列先备好恢复路径。验证账号 root 邮箱、root MFA 与恢复联系人。建立或验证一条独立的、MFA 保护的紧急管理员路径首选 IAM Identity Center。它必须独立于jade-deploy、无访问密钥、且在触碰AdministratorAccess之前完成测试。捕获状态。导出 IAM 授权明细、用户策略挂载、角色信任策略、访问密钥元数据、资源 ARN 与标签记录正被替换的AdministratorAccess挂载的精确位置。创建运行时策略与角色。创建窄化的实例、wake、breaker 角色。此时不切换工作负载用 IAM Access Analyzer 或aws accessanalyzer validate-policy校验策略文档。创建 operator 与 provisioner 角色。加上 MFA 门禁信任确保两个角色都不能修改自己、紧急路径、权限边界或任意身份。管理员挂载仍在时授予 assume-only 访问。把小的sts:AssumeRole策略挂到jade-deploy但暂时保留AdministratorAccess。测试角色入口。用独立 profile/会话逐个 assume 各角色确认aws sts get-caller-identity报告的是角色 ARN确认 operator 对 EC2、Lambda、API Gateway、日志、SNS、告警与预算的读权限。模拟每一个必需的 API 调用。用iam:SimulatePrincipalPolicy或策略模拟器跑本文的动作/资源矩阵明确测试应被拒绝的控制项——如创建用户、挂载AdministratorAccess、终止任意实例、删除护栏。用金丝雀变更路径测试不碰生产。通过 provisioner 部署再删除一个带标签的小型金丝雀栈尽量使用相同的资源类别。对 operator更新一个可丢弃的 Lambda 别名或金丝雀函数而不是调用jcode-guard-breaker——它会停掉生产实例绝不能把它当 IAM 测试。逐个切换运行时角色。先换 Lambda 执行角色验证日志与无副作用的 wake 状态检查再替换 EC2 实例 profile跑一次真实的 Bedrock 流式请求。旧角色保持完整但先不挂载直到验证完成。轮换凭据载体。首选工作站切到 IAM Identity Center 与角色 profile。过渡 IAM 用户方案创建第二把jade-deploy访问密钥在新 profile 下配置并验证角色 assume。绝不先覆盖唯一可用的 profile——IAM 用户最多两把密钥。仅在独立恢复路径成功后才解绑AdministratorAccess。解绑前立刻在独立浏览器/profile 中确认紧急管理员路径然后从jade-deploy解绑AdministratorAccess。同一变更窗口内不删除用户、密钥、旧运行时角色或旧策略。跑解绑后检查。重新 assume operator 与 provisioner重跑所有只读检查与安全部署检查验证 phone-server 健康端点在约定的维护窗口内验证 wake 行为、配对流程与一次完整的 Bedrock 流式请求。停用旧密钥但先不删除。新访问路径稳定工作至少 24–72 小时后把旧密钥标记为 inactive监控 CloudTrail 中使用该 access-key ID 的尝试与预期工作流上的AccessDenied。观察后再删除。再观察 7–14 天、确认无需回滚后删除 inactive 密钥、清理废弃策略/角色并在联合身份稳定后彻底删除jade-deploy。每季度复审。使用访问密钥最近使用数据、CloudTrail、Access Analyzer、凭据报告、告警/预算测试移除未使用的 action演练紧急路径但不把它用于日常工作。回滚规则如果移除管理员后某个必需操作失败停下来用独立的紧急管理员路径修正那个窄化角色——不要把AdministratorAccess重新挂回日常用户当默认修复手段。也绝不把已有的 STS 会话当作唯一回滚机制策略变更与会话过期都可能使该假设失效。与 IAM 相邻的其他安全发现这些不是 IAM 替换所必需的但对部署有实质影响Wake 密钥原本内嵌在 Lambda 源码里并出现在查询字符串中。查询串 token 可能出现在浏览器历史、日志、分析工具、截图与 referrer 里。应存入 Secrets Manager 或 SSM Parameter Store改用 header 或短时签名请求比对并只授予 wake Lambda 对那一个密钥的读权限。仓库中的 wake-lambda.py 已体现改进方向token 走 URL fragment浏览器不会把它发给 API GatewayJavaScript 把它换成Authorization: Bearerheader 存于 session storagehmac.compare_digest恒定时间比对且 legacy?t链接一次性 302 重定向到 fragment 形式。端口7644曾公开暴露且 Lambda 以明文 HTTP 调用。应优先使用私有 VPC 路径、SSM 中介配对或仅 tailnet 访问若必须保留公网应限制安全组源并加 TLS。当前部署已通过 SSM Run Command 生成配对码该端口不再公开legacy 的 jcode-pair.service 已停用。配对服务曾以 root 运行并调用sudo -u ec2-usersystemd unit 应改为专用用户加文件系统保护、NoNewPrivileges与窄范围的 sudo 规则。即使修好了jade-deploy实例角色当前的AmazonBedrockFullAccess也偏宽。为AttachUserPolicy、PutUserPolicy、CreateAccessKey、UpdateAssumeRolePolicy、PassRole以及对 emergency/部署角色的任何变更添加 CloudTrail 告警。验收标准迁移完成的判据是jade-deploy没有AdministratorAccess也没有除角色 assume 之外的直接 AWS 服务权限日常部署与维护通过JcodePhoneOperator成功完成带标签的完整重建可以通过 MFA 门禁的 provisioner/CloudFormation 路径执行运行时角色只包含上文记录的 API 调用独立的紧急管理员路径经过测试旧访问密钥经历「停用 → 观察 → 删除」CloudTrail 中没有必需操作的意外AccessDenied观察期内也没有旧密钥的使用记录。小结这份评估文档的价值在于把「最小权限」落成了可执行的工程流程从源码级 API 证据出发写策略ec2:StartInstances只给一台实例、ssm:SendCommand只给一台实例加一个 AWS 文档、Bedrock 推理只给一个 profile 加通配区域的 foundation model ARN用三平面角色把日常、重建、应急三种风险隔离开再用 15 步防锁死序列完成AdministratorAccess的移除与凭据轮换。整个方案的所有资源 ARN、Lambda 代码与 Bedrock provider 行为都能在 phone-server 目录 与 jcode-provider-bedrock 源码 中逐一对证适合作为「长期部署凭据降权」的完整参考实现。【免费下载链接】jcodeThe most RAM efficient harness项目地址: https://gitcode.com/GitHub_Trending/jcod/jcode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考