@intentius/chant-lexicon-aws 0.124.30 → 0.124.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/dynamodb.js +41 -0
- package/dist/actions/ecr.js +9 -0
- package/dist/actions/ecs.js +5 -0
- package/dist/actions/iam.js +3 -0
- package/dist/actions/index.js +9 -0
- package/dist/actions/lambda.js +11 -0
- package/dist/actions/logs.js +4 -0
- package/dist/actions/s3.js +40 -0
- package/dist/actions/sns.js +5 -0
- package/dist/actions/sqs.js +15 -0
- package/dist/agentcore/trace-fetch.d.ts.map +1 -1
- package/dist/agentcore/trace-fetch.js +472 -0
- package/dist/agentcore/trace-render.js +359 -0
- package/dist/ambient.js +148 -0
- package/dist/api/credential-chain.d.ts +30 -3
- package/dist/api/credential-chain.d.ts.map +1 -1
- package/dist/api/credential-chain.js +509 -0
- package/dist/api/read-client.d.ts +16 -43
- package/dist/api/read-client.d.ts.map +1 -1
- package/dist/api/read-client.js +458 -0
- package/dist/api/sigv4.d.ts +4 -4
- package/dist/api/sigv4.js +185 -0
- package/dist/behaviour-kinds.js +114 -0
- package/dist/caller-identity.d.ts +3 -5
- package/dist/caller-identity.d.ts.map +1 -1
- package/dist/caller-identity.js +146 -0
- package/dist/codegen/docs-cli.js +2 -0
- package/dist/codegen/docs.js +120 -0
- package/dist/codegen/enum-overlay.js +162 -0
- package/dist/codegen/extensions.js +139 -0
- package/dist/codegen/fallback.js +32 -0
- package/dist/codegen/generate-cli.js +15 -0
- package/dist/codegen/generate-lexicon.js +70 -0
- package/dist/codegen/generate-typescript.js +226 -0
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/codegen/generate.js +234 -0
- package/dist/codegen/naming.js +135 -0
- package/dist/codegen/package.js +67 -0
- package/dist/codegen/patches.d.ts +26 -1
- package/dist/codegen/patches.d.ts.map +1 -1
- package/dist/codegen/patches.js +90 -0
- package/dist/codegen/property-overlay.js +85 -0
- package/dist/codegen/property-overlay.json +1 -16
- package/dist/codegen/sam.js +402 -0
- package/dist/codegen/typecheck.js +4 -0
- package/dist/codegen/versions.js +31 -0
- package/dist/components/__tests__/mock-cloud-executor.js +326 -0
- package/dist/components/apply.d.ts +44 -1
- package/dist/components/apply.d.ts.map +1 -1
- package/dist/components/apply.js +752 -0
- package/dist/components/builders.js +37 -0
- package/dist/components/capability-plugin.js +66 -0
- package/dist/components/cloud-executor.d.ts +35 -0
- package/dist/components/cloud-executor.d.ts.map +1 -1
- package/dist/components/cloud-executor.js +576 -0
- package/dist/components/config-bom.js +207 -0
- package/dist/components/host-delivery.js +117 -0
- package/dist/components/index.js +18 -0
- package/dist/components/job-submission.js +77 -0
- package/dist/components/publish.js +234 -0
- package/dist/components/safety.js +62 -0
- package/dist/components/wait-aws.js +68 -0
- package/dist/composites/agentcore-agent.js +187 -0
- package/dist/composites/agentcore-trust-policy.js +13 -0
- package/dist/composites/alb-shared.js +84 -0
- package/dist/composites/bucket-deployment.js +93 -0
- package/dist/composites/catalog.js +2714 -0
- package/dist/composites/dynamodb-table.js +66 -0
- package/dist/composites/ec2-instance-bundle.js +75 -0
- package/dist/composites/ec2-instance-role.js +26 -0
- package/dist/composites/ecr-repository.js +64 -0
- package/dist/composites/ecs-trust-policy.js +10 -0
- package/dist/composites/efs-with-access-point.js +44 -0
- package/dist/composites/eks-cluster.js +118 -0
- package/dist/composites/fargate-alb.js +216 -0
- package/dist/composites/fargate-service.js +222 -0
- package/dist/composites/index.js +28 -0
- package/dist/composites/lambda-api.js +15 -0
- package/dist/composites/lambda-dynamodb.js +77 -0
- package/dist/composites/lambda-eventbridge.js +27 -0
- package/dist/composites/lambda-function.js +54 -0
- package/dist/composites/lambda-s3.js +93 -0
- package/dist/composites/lambda-sns.js +23 -0
- package/dist/composites/lambda-sqs.js +34 -0
- package/dist/composites/landing-zone.js +82 -0
- package/dist/composites/microvm-app.js +293 -0
- package/dist/composites/minimal-vpc.js +40 -0
- package/dist/composites/monitoring-stack.js +105 -0
- package/dist/composites/nlb-service.js +61 -0
- package/dist/composites/rds-instance.js +98 -0
- package/dist/composites/scheduled-lambda.js +28 -0
- package/dist/composites/solr-fargate-service.js +33 -0
- package/dist/composites/step-functions-workflow.js +78 -0
- package/dist/composites/vpc-default.js +132 -0
- package/dist/condition.js +43 -0
- package/dist/coverage.js +4 -0
- package/dist/deep-observe.d.ts.map +1 -1
- package/dist/deep-observe.js +709 -0
- package/dist/deep-topology.js +226 -0
- package/dist/default-tags.js +50 -0
- package/dist/defaults.js +85 -0
- package/dist/dependencies.js +269 -0
- package/dist/detect.js +21 -0
- package/dist/disruption.d.ts.map +1 -1
- package/dist/disruption.js +129 -0
- package/dist/effect-receipt-row.js +107 -0
- package/dist/generated/index.d.ts +1297 -82
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/generated/index.js +12382 -0
- package/dist/generated/runtime.js +4 -0
- package/dist/governance.js +131 -0
- package/dist/identity-observe.d.ts.map +1 -1
- package/dist/identity-observe.js +127 -0
- package/dist/import/generator.js +757 -0
- package/dist/import/live-export.js +34 -0
- package/dist/import/parser.js +394 -0
- package/dist/index.js +69 -0
- package/dist/integrity.json +6 -6
- package/dist/intrinsics.js +393 -0
- package/dist/lint/audit-catalog.js +87 -0
- package/dist/lint/audit-lineage.js +150 -0
- package/dist/lint/post-synth/cf-refs.js +247 -0
- package/dist/lint/post-synth/cor020.js +60 -0
- package/dist/lint/post-synth/ext001.d.ts.map +1 -1
- package/dist/lint/post-synth/ext001.js +197 -0
- package/dist/lint/post-synth/index.js +124 -0
- package/dist/lint/post-synth/waw010.js +41 -0
- package/dist/lint/post-synth/waw011.js +41 -0
- package/dist/lint/post-synth/waw013.js +38 -0
- package/dist/lint/post-synth/waw014.js +42 -0
- package/dist/lint/post-synth/waw015.js +88 -0
- package/dist/lint/post-synth/waw016.d.ts.map +1 -1
- package/dist/lint/post-synth/waw016.js +116 -0
- package/dist/lint/post-synth/waw017.js +43 -0
- package/dist/lint/post-synth/waw018.js +61 -0
- package/dist/lint/post-synth/waw019.js +64 -0
- package/dist/lint/post-synth/waw020.js +56 -0
- package/dist/lint/post-synth/waw021.js +44 -0
- package/dist/lint/post-synth/waw022.js +36 -0
- package/dist/lint/post-synth/waw023.js +40 -0
- package/dist/lint/post-synth/waw024.js +46 -0
- package/dist/lint/post-synth/waw025.js +36 -0
- package/dist/lint/post-synth/waw026.js +38 -0
- package/dist/lint/post-synth/waw027.js +41 -0
- package/dist/lint/post-synth/waw028.js +39 -0
- package/dist/lint/post-synth/waw029.js +54 -0
- package/dist/lint/post-synth/waw030.js +282 -0
- package/dist/lint/post-synth/waw031.js +58 -0
- package/dist/lint/post-synth/waw032.js +45 -0
- package/dist/lint/post-synth/waw033.js +75 -0
- package/dist/lint/post-synth/waw034.js +52 -0
- package/dist/lint/post-synth/waw035.js +56 -0
- package/dist/lint/post-synth/waw036.js +79 -0
- package/dist/lint/post-synth/waw037.js +67 -0
- package/dist/lint/post-synth/waw038.js +42 -0
- package/dist/lint/post-synth/waw039.js +42 -0
- package/dist/lint/post-synth/waw040.js +45 -0
- package/dist/lint/post-synth/waw041.js +40 -0
- package/dist/lint/post-synth/waw042.js +99 -0
- package/dist/lint/post-synth/waw043.js +51 -0
- package/dist/lint/post-synth/waw044.js +64 -0
- package/dist/lint/post-synth/waw045.js +49 -0
- package/dist/lint/post-synth/waw046.js +52 -0
- package/dist/lint/post-synth/waw047.js +43 -0
- package/dist/lint/post-synth/waw048.js +40 -0
- package/dist/lint/post-synth/waw049.js +78 -0
- package/dist/lint/post-synth/waw050.js +44 -0
- package/dist/lint/post-synth/waw051.js +41 -0
- package/dist/lint/post-synth/waw052.js +43 -0
- package/dist/lint/post-synth/waw053.js +43 -0
- package/dist/lint/post-synth/waw054.js +41 -0
- package/dist/lint/post-synth/waw055.js +41 -0
- package/dist/lint/post-synth/waw056.js +65 -0
- package/dist/lint/post-synth/waw057.js +43 -0
- package/dist/lint/post-synth/waw058.js +61 -0
- package/dist/lint/post-synth/waw059.js +338 -0
- package/dist/lint/post-synth/waw060.js +83 -0
- package/dist/lint/post-synth/waw061.js +60 -0
- package/dist/lint/post-synth/waw062.js +0 -0
- package/dist/lint/post-synth/waw063.js +0 -0
- package/dist/lint/post-synth/waw064.js +45 -0
- package/dist/lint/post-synth/waw065.js +104 -0
- package/dist/lint/post-synth/waw066.js +145 -0
- package/dist/lint/post-synth/waw067.js +115 -0
- package/dist/lint/post-synth/waw068.js +69 -0
- package/dist/lint/post-synth/waw069.js +0 -0
- package/dist/lint/rules/hardcoded-region.js +38 -0
- package/dist/lint/rules/iam-wildcard.js +60 -0
- package/dist/lint/rules/index.js +6 -0
- package/dist/lint/rules/s3-encryption.js +60 -0
- package/dist/live-attrs.js +42 -0
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +18 -0
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +66 -0
- package/dist/manifest.json +1 -1
- package/dist/mapping.js +33 -0
- package/dist/meta.json +17359 -784
- package/dist/nested-stack.js +95 -0
- package/dist/okf/index.md +203 -0
- package/dist/okf/rules/EXT001.md +1 -0
- package/dist/okf/rules/WAW016.md +2 -0
- package/dist/okf/rules/WAW019.md +1 -0
- package/dist/okf/rules/WAW028.md +1 -0
- package/dist/okf/rules/WAW030.md +2 -0
- package/dist/okf/rules/WAW039.md +1 -0
- package/dist/okf/rules/WAW049.md +1 -0
- package/dist/okf/rules/WAW056.md +1 -0
- package/dist/okf/rules/WAW058.md +1 -0
- package/dist/okf/rules/WAW062.md +1 -0
- package/dist/okf/rules/WAW064.md +1 -0
- package/dist/okf/rules/WAW065.md +1 -0
- package/dist/okf/rules/WAW066.md +1 -0
- package/dist/okf/rules/WAW067.md +1 -0
- package/dist/okf/rules/WAW068.md +1 -0
- package/dist/okf/rules/WAW069.md +4 -0
- package/dist/okf/types/AIWorkloadConfig.md +23 -0
- package/dist/okf/types/ARCRegionSwitchPlan.md +1 -0
- package/dist/okf/types/AccountAccessApplication.md +28 -0
- package/dist/okf/types/AccountAccessEntitlement.md +22 -0
- package/dist/okf/types/ActionTarget.md +20 -0
- package/dist/okf/types/AdConfiguration.md +21 -0
- package/dist/okf/types/Adapter.md +26 -0
- package/dist/okf/types/AgentContext.md +35 -0
- package/dist/okf/types/AgentGoal.md +31 -0
- package/dist/okf/types/AgentProfile.md +34 -0
- package/dist/okf/types/Alarm.md +3 -1
- package/dist/okf/types/AlarmModel.md +14 -9
- package/dist/okf/types/AmplifyWebhook.md +25 -0
- package/dist/okf/types/ApiCache.md +8 -8
- package/dist/okf/types/ApiGatewayManagedOverrides.md +5 -5
- package/dist/okf/types/AppAuthorization.md +35 -0
- package/dist/okf/types/AppBlockBuilder.md +1 -0
- package/dist/okf/types/AppInstance.md +2 -2
- package/dist/okf/types/AppInstanceBot.md +2 -2
- package/dist/okf/types/AppStreamFleet.md +3 -2
- package/dist/okf/types/AppSyncApiKey.md +6 -6
- package/dist/okf/types/AppSyncType.md +22 -0
- package/dist/okf/types/ApplicationStatusCheck.md +36 -0
- package/dist/okf/types/ApplicationVersion.md +4 -1
- package/dist/okf/types/ApplicationsList.md +26 -0
- package/dist/okf/types/ApprovalPolicy.md +28 -0
- package/dist/okf/types/ArchiveRule.md +24 -0
- package/dist/okf/types/Asset.md +30 -0
- package/dist/okf/types/Backup.md +31 -0
- package/dist/okf/types/BedrockAgentCoreDataset.md +1 -1
- package/dist/okf/types/BedrockAgentCoreGateway.md +3 -0
- package/dist/okf/types/BedrockSession.md +28 -0
- package/dist/okf/types/BillEstimate.md +35 -0
- package/dist/okf/types/Brand.md +32 -0
- package/dist/okf/types/CallAnalyticsCategory.md +25 -0
- package/dist/okf/types/Campaign.md +28 -0
- package/dist/okf/types/CapacityProvider.md +30 -0
- package/dist/okf/types/Case.md +24 -0
- package/dist/okf/types/CertificateAssociation.md +13 -0
- package/dist/okf/types/ChangeSet.md +36 -0
- package/dist/okf/types/ChannelFlow.md +29 -0
- package/dist/okf/types/ChimeChannel.md +39 -0
- package/dist/okf/types/Classifier.md +6 -6
- package/dist/okf/types/ClientVpnAuthorizationRule.md +6 -6
- package/dist/okf/types/ClientVpnEndpoint.md +2 -0
- package/dist/okf/types/ClientVpnRoute.md +5 -5
- package/dist/okf/types/CloudConnector.md +29 -0
- package/dist/okf/types/Cluster.md +39 -0
- package/dist/okf/types/ClusterSchedulerConfig.md +30 -0
- package/dist/okf/types/CodeCommitRepository.md +12 -12
- package/dist/okf/types/CodeConnectionsHost.md +26 -0
- package/dist/okf/types/CodeRepository.md +5 -5
- package/dist/okf/types/CompositeAlarm.md +1 -0
- package/dist/okf/types/ComputeEnvironment.md +2 -0
- package/dist/okf/types/ComputeNodeGroup.md +1 -1
- package/dist/okf/types/ComputeQuota.md +34 -0
- package/dist/okf/types/ConfigRule.md +1 -1
- package/dist/okf/types/ConfigurationRecorder.md +7 -6
- package/dist/okf/types/ConnectAttachment.md +2 -0
- package/dist/okf/types/ConnectQueue.md +5 -1
- package/dist/okf/types/ConnectVocabulary.md +28 -0
- package/dist/okf/types/ConnectionType.md +24 -0
- package/dist/okf/types/ConsentPortal.md +33 -0
- package/dist/okf/types/ContactMethod.md +29 -0
- package/dist/okf/types/ContainerAssociation.md +26 -0
- package/dist/okf/types/ContainerFleet.md +1 -1
- package/dist/okf/types/ContainerGroupDefinition.md +1 -1
- package/dist/okf/types/Content.md +40 -0
- package/dist/okf/types/ContentAssociation.md +28 -0
- package/dist/okf/types/CustomDetectionRuleAssociation.md +28 -0
- package/dist/okf/types/CustomEntityType.md +4 -9
- package/dist/okf/types/Customization.md +22 -0
- package/dist/okf/types/CwIntegration.md +31 -0
- package/dist/okf/types/DAXParameterGroup.md +3 -8
- package/dist/okf/types/DAXSubnetGroup.md +0 -5
- package/dist/okf/types/DBClusterEndpoint.md +31 -0
- package/dist/okf/types/DBProxyTargetGroup.md +1 -0
- package/dist/okf/types/DBSnapshot.md +62 -0
- package/dist/okf/types/DLMLifecyclePolicy.md +12 -12
- package/dist/okf/types/DLPSetting.md +31 -0
- package/dist/okf/types/DMSInstanceProfile.md +1 -1
- package/dist/okf/types/DRSLaunchConfigurationTemplate.md +28 -0
- package/dist/okf/types/Daemon.md +1 -0
- package/dist/okf/types/DataExchangeDataSet.md +29 -0
- package/dist/okf/types/DataIntegrationFlow.md +27 -0
- package/dist/okf/types/DataMigration.md +1 -1
- package/dist/okf/types/DataProvider.md +2 -1
- package/dist/okf/types/DataQualityRuleset.md +6 -11
- package/dist/okf/types/DataSource.md +23 -0
- package/dist/okf/types/Dataset.md +20 -0
- package/dist/okf/types/DatasetIntegration.md +23 -0
- package/dist/okf/types/DbCluster.md +1 -1
- package/dist/okf/types/DbInstance.md +8 -2
- package/dist/okf/types/DeadlineBudget.md +29 -0
- package/dist/okf/types/DelegationSet.md +23 -0
- package/dist/okf/types/DeliveryChannel.md +6 -11
- package/dist/okf/types/DevOpsAgentAgentSpace.md +4 -0
- package/dist/okf/types/DevOpsAgentService.md +1 -0
- package/dist/okf/types/DevOpsAgentTrigger.md +28 -0
- package/dist/okf/types/DirectConnectGatewayAttachment.md +2 -0
- package/dist/okf/types/Directory.md +60 -0
- package/dist/okf/types/DocDBDBClusterParameterGroup.md +5 -10
- package/dist/okf/types/DocDBDBSubnetGroup.md +4 -9
- package/dist/okf/types/DocDBElasticClusterSnapshot.md +36 -0
- package/dist/okf/types/DocumentClassifierEndpoint.md +27 -0
- package/dist/okf/types/Domain.md +27 -0
- package/dist/okf/types/EKSCertificateAuthority.md +42 -0
- package/dist/okf/types/EKSCluster.md +8 -0
- package/dist/okf/types/EcSnapshot.md +66 -0
- package/dist/okf/types/EmailIdentityCertificate.md +15 -0
- package/dist/okf/types/EndpointConfig.md +14 -13
- package/dist/okf/types/EntityRecognizer.md +27 -0
- package/dist/okf/types/EntityRecognizerEndpoint.md +31 -0
- package/dist/okf/types/EnvironmentEC2.md +13 -13
- package/dist/okf/types/EvaluationForm.md +1 -0
- package/dist/okf/types/Evaluator.md +6 -2
- package/dist/okf/types/EventAction.md +26 -0
- package/dist/okf/types/EventRule.md +2 -0
- package/dist/okf/types/EventSource.md +30 -0
- package/dist/okf/types/EventTracker.md +22 -0
- package/dist/okf/types/EventsV2EventBus.md +28 -0
- package/dist/okf/types/EventsV2ResourcePolicy.md +19 -0
- package/dist/okf/types/EventsV2Subscriber.md +39 -0
- package/dist/okf/types/ExperimentDefinition.md +39 -0
- package/dist/okf/types/ExperimentRun.md +33 -0
- package/dist/okf/types/ExperimentTrialComponent.md +13 -11
- package/dist/okf/types/FHIRDatastore.md +3 -0
- package/dist/okf/types/FSxSnapshot.md +5 -5
- package/dist/okf/types/FSxVolume.md +9 -9
- package/dist/okf/types/FeaturedResultsSet.md +26 -0
- package/dist/okf/types/Feed.md +1 -0
- package/dist/okf/types/FieldLevelEncryptionConfig.md +25 -0
- package/dist/okf/types/FieldLevelEncryptionProfile.md +22 -0
- package/dist/okf/types/FileCache.md +45 -0
- package/dist/okf/types/Filter.md +27 -0
- package/dist/okf/types/Firewall.md +6 -0
- package/dist/okf/types/FlowMediaStream.md +28 -0
- package/dist/okf/types/FlowOutput.md +1 -0
- package/dist/okf/types/FpgaImage.md +38 -0
- package/dist/okf/types/Function.md +2 -2
- package/dist/okf/types/Gateway.md +41 -0
- package/dist/okf/types/GatewayClusterAssociations.md +23 -0
- package/dist/okf/types/GatewayRateLimit.md +26 -0
- package/dist/okf/types/GatewayRule.md +32 -0
- package/dist/okf/types/GlobalReplicationGroup.md +3 -0
- package/dist/okf/types/GlobalResolver.md +1 -1
- package/dist/okf/types/GlobalTable.md +1 -0
- package/dist/okf/types/GlueConnection.md +5 -4
- package/dist/okf/types/GlueSecurityConfiguration.md +1 -6
- package/dist/okf/types/GlueSession.md +38 -0
- package/dist/okf/types/GlueTable.md +5 -10
- package/dist/okf/types/GlueWorkflow.md +5 -10
- package/dist/okf/types/Group.md +27 -0
- package/dist/okf/types/Harness.md +1 -0
- package/dist/okf/types/HostKey.md +33 -0
- package/dist/okf/types/HostedZone.md +1 -0
- package/dist/okf/types/HttpApi.md +2 -0
- package/dist/okf/types/HttpNamespace.md +5 -5
- package/dist/okf/types/HubV2.md +1 -0
- package/dist/okf/types/HumanTaskUi.md +22 -0
- package/dist/okf/types/IPv4Pool.md +28 -0
- package/dist/okf/types/ImageBuilder.md +1 -0
- package/dist/okf/types/ImageBuilderImage.md +1 -1
- package/dist/okf/types/ImagePipeline.md +1 -1
- package/dist/okf/types/InferenceComponent.md +5 -1
- package/dist/okf/types/InfluxDBBackup.md +65 -0
- package/dist/okf/types/InfluxDBCluster.md +3 -0
- package/dist/okf/types/InfrastructureConfiguration.md +2 -0
- package/dist/okf/types/IngestionDestination.md +28 -0
- package/dist/okf/types/InputSecurityGroup.md +6 -4
- package/dist/okf/types/InspectorV2Connector.md +38 -0
- package/dist/okf/types/InstanceEventWindow.md +25 -0
- package/dist/okf/types/InstanceFleetConfig.md +10 -10
- package/dist/okf/types/InstanceGroupConfig.md +3 -3
- package/dist/okf/types/InstrumentationConfig.md +31 -0
- package/dist/okf/types/IntegrationAssociation.md +3 -0
- package/dist/okf/types/IoTSiteWiseApplication.md +34 -0
- package/dist/okf/types/IoTSiteWiseDataset.md +5 -2
- package/dist/okf/types/IoTSiteWiseTask.md +24 -0
- package/dist/okf/types/IpamExternalResourceVerificationToken.md +35 -0
- package/dist/okf/types/IpamInternetRegistryAssociation.md +32 -0
- package/dist/okf/types/Job.md +35 -0
- package/dist/okf/types/JobTemplate.md +26 -0
- package/dist/okf/types/KinesisChannel.md +31 -0
- package/dist/okf/types/KinesisStream.md +1 -0
- package/dist/okf/types/LambdaResourcePolicy.md +14 -0
- package/dist/okf/types/Lexicon.md +34 -0
- package/dist/okf/types/LicenseAssetGroup.md +23 -0
- package/dist/okf/types/LicenseConfiguration.md +33 -0
- package/dist/okf/types/LicenseServerEndpoint.md +32 -0
- package/dist/okf/types/LightsailKeyPair.md +29 -0
- package/dist/okf/types/LimitsProfile.md +27 -0
- package/dist/okf/types/LocationAzureBlob.md +2 -1
- package/dist/okf/types/LocationObjectStorage.md +1 -0
- package/dist/okf/types/LogAlarm.md +2 -0
- package/dist/okf/types/MGNConnector.md +23 -0
- package/dist/okf/types/MGNLaunchConfigurationTemplate.md +37 -0
- package/dist/okf/types/MLTransform.md +15 -15
- package/dist/okf/types/MWAAServerlessWorkflow.md +3 -0
- package/dist/okf/types/ManagedNotificationAccountContactAssociation.md +1 -0
- package/dist/okf/types/ManagedNotificationAdditionalChannelAssociation.md +1 -0
- package/dist/okf/types/MediaConvertJobTemplate.md +11 -13
- package/dist/okf/types/MediaConvertQueue.md +8 -10
- package/dist/okf/types/MediaInsightsPipelineConfiguration.md +28 -0
- package/dist/okf/types/MediaLiveInput.md +41 -18
- package/dist/okf/types/MediaPackageV2Channel.md +3 -0
- package/dist/okf/types/MediaPackageV2OriginEndpoint.md +1 -0
- package/dist/okf/types/MediaPipelineKinesisVideoStreamPool.md +28 -0
- package/dist/okf/types/MediaTailorFunction.md +27 -0
- package/dist/okf/types/MedicalVocabulary.md +21 -0
- package/dist/okf/types/Member.md +26 -0
- package/dist/okf/types/Memory.md +6 -0
- package/dist/okf/types/MemoryDBSnapshot.md +29 -0
- package/dist/okf/types/Metric.md +59 -0
- package/dist/okf/types/MetricAttribution.md +23 -0
- package/dist/okf/types/MicrosoftAD.md +11 -11
- package/dist/okf/types/MigrationProject.md +8 -1
- package/dist/okf/types/Monitor.md +26 -0
- package/dist/okf/types/NFSFileShare.md +44 -0
- package/dist/okf/types/NeptuneGraphGraph.md +1 -0
- package/dist/okf/types/NetworkConnector.md +4 -0
- package/dist/okf/types/NetworkFlowMonitorScope.md +23 -0
- package/dist/okf/types/NetworkMigrationDefinition.md +31 -0
- package/dist/okf/types/NetworkSecurityManagerDeployment.md +31 -0
- package/dist/okf/types/NetworkSecurityManagerPolicy.md +32 -0
- package/dist/okf/types/NetworkSecurityManagerScope.md +29 -0
- package/dist/okf/types/NotebookInstance.md +18 -18
- package/dist/okf/types/NotebookInstanceLifecycleConfig.md +6 -5
- package/dist/okf/types/NotifyConfiguration.md +35 -0
- package/dist/okf/types/OTelEnrichment.md +2 -0
- package/dist/okf/types/OnlineEvaluationConfig.md +0 -1
- package/dist/okf/types/OrganizationConfigRule.md +7 -7
- package/dist/okf/types/Outpost.md +32 -0
- package/dist/okf/types/ParallelData.md +40 -0
- package/dist/okf/types/Partition.md +5 -5
- package/dist/okf/types/PaymentConnector.md +4 -1
- package/dist/okf/types/Pentest.md +1 -0
- package/dist/okf/types/PerfReports.md +28 -0
- package/dist/okf/types/PermissionAssociation.md +30 -0
- package/dist/okf/types/PersonalizeDataset.md +1 -0
- package/dist/okf/types/PersonalizeDatasetGroup.md +1 -0
- package/dist/okf/types/PersonalizeSchema.md +1 -0
- package/dist/okf/types/Pipeline.md +25 -0
- package/dist/okf/types/PlaybackConfiguration.md +1 -0
- package/dist/okf/types/PolicyAssociation.md +1 -1
- package/dist/okf/types/PolicyGrant.md +2 -2
- package/dist/okf/types/PolicyPrincipalAttachment.md +2 -7
- package/dist/okf/types/PortalProduct.md +24 -0
- package/dist/okf/types/PrefetchSchedule.md +25 -0
- package/dist/okf/types/PricingPlanManagerSubscription.md +31 -0
- package/dist/okf/types/PrincipalAssociation.md +27 -0
- package/dist/okf/types/PrivateDnsNamespace.md +8 -8
- package/dist/okf/types/PrivateVirtualInterface.md +1 -0
- package/dist/okf/types/ProcurementPortalPreference.md +45 -0
- package/dist/okf/types/Program.md +33 -0
- package/dist/okf/types/ProjectMembership.md +1 -1
- package/dist/okf/types/ProtocolsList.md +26 -0
- package/dist/okf/types/PublicDnsNamespace.md +7 -7
- package/dist/okf/types/PublicVirtualInterface.md +1 -0
- package/dist/okf/types/QEV2IdcApplication.md +25 -0
- package/dist/okf/types/QueryLoggingConfig.md +21 -0
- package/dist/okf/types/QuerySuggestionsBlockList.md +25 -0
- package/dist/okf/types/QuickSightAssignment.md +24 -0
- package/dist/okf/types/RAMResourceAssociation.md +27 -0
- package/dist/okf/types/RDSClusterSnapshot.md +54 -0
- package/dist/okf/types/RDSDBParameterGroup.md +5 -0
- package/dist/okf/types/RDSDeployment.md +41 -0
- package/dist/okf/types/RcsAgent.md +38 -0
- package/dist/okf/types/ReceiptRule.md +5 -5
- package/dist/okf/types/ReceiptRuleSet.md +1 -6
- package/dist/okf/types/RecommenderFilter.md +27 -0
- package/dist/okf/types/RecommenderSchema.md +25 -0
- package/dist/okf/types/RecordSet.md +16 -22
- package/dist/okf/types/RecoveryPlan.md +28 -0
- package/dist/okf/types/RedshiftIdcApplication.md +31 -0
- package/dist/okf/types/RedshiftSnapshot.md +59 -0
- package/dist/okf/types/RegistrationAttachment.md +28 -0
- package/dist/okf/types/Registry.md +41 -0
- package/dist/okf/types/RegistryRecord.md +38 -0
- package/dist/okf/types/RelatedItem.md +24 -0
- package/dist/okf/types/ReplicationConfigurationTemplate.md +35 -0
- package/dist/okf/types/ReplicationSubnetGroup.md +4 -9
- package/dist/okf/types/ReplicationTask.md +14 -14
- package/dist/okf/types/ReportGenerator.md +29 -0
- package/dist/okf/types/ReportGroup.md +1 -3
- package/dist/okf/types/ResilienceHubV2Policy.md +1 -0
- package/dist/okf/types/ResilienceHubV2Service.md +1 -0
- package/dist/okf/types/ResourceConfiguration.md +1 -1
- package/dist/okf/types/ResourceMetricsConfiguration.md +21 -0
- package/dist/okf/types/RestApi.md +1 -0
- package/dist/okf/types/RetrievalInstruction.md +32 -0
- package/dist/okf/types/RouterOutput.md +1 -0
- package/dist/okf/types/Rule.md +31 -0
- package/dist/okf/types/RunCache.md +29 -0
- package/dist/okf/types/Runtime.md +2 -1
- package/dist/okf/types/SCNInstance.md +33 -0
- package/dist/okf/types/SDBDomain.md +2 -2
- package/dist/okf/types/SMBFileShare.md +49 -0
- package/dist/okf/types/SageMakerArtifact.md +27 -0
- package/dist/okf/types/SageMakerEndpoint.md +0 -1
- package/dist/okf/types/ScalableTarget.md +1 -0
- package/dist/okf/types/ScalingPlan.md +6 -6
- package/dist/okf/types/ScheduledReport.md +31 -0
- package/dist/okf/types/SecondaryNetwork.md +26 -0
- package/dist/okf/types/SecurityAgentArtifact.md +25 -0
- package/dist/okf/types/SecurityAgentIntegration.md +31 -0
- package/dist/okf/types/Server.md +1 -0
- package/dist/okf/types/ServerlessCache.md +2 -0
- package/dist/okf/types/ServerlessCacheSnapshot.md +31 -0
- package/dist/okf/types/ServerlessRepoApplication.md +32 -0
- package/dist/okf/types/ServiceDiscoveryInstance.md +3 -7
- package/dist/okf/types/SipMediaApplication.md +27 -0
- package/dist/okf/types/SiteToSiteVpnAttachment.md +2 -0
- package/dist/okf/types/SnapshotCopyGrant.md +20 -0
- package/dist/okf/types/Solution.md +1 -0
- package/dist/okf/types/SourceAssociation.md +25 -0
- package/dist/okf/types/SourceCredential.md +6 -6
- package/dist/okf/types/SourceNetwork.md +23 -0
- package/dist/okf/types/StackFleetAssociation.md +2 -7
- package/dist/okf/types/StorageTierPolicy.md +20 -0
- package/dist/okf/types/StorageVirtualMachine.md +9 -9
- package/dist/okf/types/Stream.md +28 -0
- package/dist/okf/types/SubnetCidrReservation.md +26 -0
- package/dist/okf/types/SubscriptionProvider.md +26 -0
- package/dist/okf/types/SupportPermit.md +29 -0
- package/dist/okf/types/Table.md +2 -1
- package/dist/okf/types/TableOptimizer.md +5 -10
- package/dist/okf/types/Tape.md +31 -0
- package/dist/okf/types/Template.md +36 -0
- package/dist/okf/types/Tenant.md +2 -0
- package/dist/okf/types/Terminology.md +39 -0
- package/dist/okf/types/Thesaurus.md +25 -0
- package/dist/okf/types/ThingPrincipalAttachment.md +3 -8
- package/dist/okf/types/Topic.md +1 -0
- package/dist/okf/types/TopicRuleDestination.md +1 -0
- package/dist/okf/types/TrafficPolicy.md +26 -0
- package/dist/okf/types/TrafficPolicyInstance.md +28 -0
- package/dist/okf/types/TranscribeVocabulary.md +27 -0
- package/dist/okf/types/TransitGatewayRouteTableAttachment.md +2 -0
- package/dist/okf/types/TransitVirtualInterface.md +1 -0
- package/dist/okf/types/Tunnel.md +25 -0
- package/dist/okf/types/UsageLimit.md +26 -0
- package/dist/okf/types/UseCase.md +23 -0
- package/dist/okf/types/User.md +47 -0
- package/dist/okf/types/VPCEndpoint.md +1 -1
- package/dist/okf/types/VPCEndpointService.md +6 -0
- package/dist/okf/types/VPCPeeringConnection.md +2 -2
- package/dist/okf/types/VPNConcentrator.md +1 -1
- package/dist/okf/types/VPNConnection.md +1 -1
- package/dist/okf/types/VerifiedDestinationNumber.md +25 -0
- package/dist/okf/types/View.md +27 -0
- package/dist/okf/types/VoiceConnector.md +30 -0
- package/dist/okf/types/Volume.md +44 -0
- package/dist/okf/types/Vpc.md +1 -1
- package/dist/okf/types/VpcAttachment.md +2 -0
- package/dist/okf/types/WebFunction.md +27 -0
- package/dist/okf/types/WebFunctionEndpoint.md +44 -0
- package/dist/okf/types/WebFunctionRevision.md +32 -0
- package/dist/okf/types/WickrNetwork.md +27 -0
- package/dist/okf/types/Worker.md +29 -0
- package/dist/okf/types/Workforce.md +26 -0
- package/dist/okf/types/Workload.md +35 -0
- package/dist/okf/types/WorkloadEstimate.md +35 -0
- package/dist/okf/types/Workspace.md +28 -0
- package/dist/okf/types/Workteam.md +8 -8
- package/dist/op/activities/aws-apply.js +214 -0
- package/dist/op/activities/floci.js +97 -0
- package/dist/op/activities/index.js +32 -0
- package/dist/op/builders.js +50 -0
- package/dist/ownership.js +52 -0
- package/dist/package-cli.js +25 -0
- package/dist/parameter.js +19 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +1006 -0
- package/dist/properties.js +166 -0
- package/dist/pseudo.js +25 -0
- package/dist/receipt-store.d.ts.map +1 -1
- package/dist/receipt-store.js +233 -0
- package/dist/reference-catalog.js +106 -0
- package/dist/rules/ext001.ts +3 -3
- package/dist/rules/waw016.ts +2 -2
- package/dist/serializer.js +529 -0
- package/dist/spec/fetch.js +193 -0
- package/dist/spec/parse.js +259 -0
- package/dist/spec/pin.js +185 -0
- package/dist/spec/pinned-types.json +203 -0
- package/dist/stack-errors.js +14 -0
- package/dist/taggable.d.ts.map +1 -1
- package/dist/taggable.js +33 -0
- package/dist/teardown.js +199 -0
- package/dist/template-sections.js +53 -0
- package/dist/template-transform.js +50 -0
- package/dist/types/index.d.ts +18847 -1124
- package/dist/validate-cli.js +16 -0
- package/dist/validate.js +33 -0
- package/package.json +9 -9
- package/src/agentcore/trace-fetch.ts +2 -1
- package/src/api/credential-chain.ts +119 -9
- package/src/api/credential-isolation.test.ts +72 -0
- package/src/api/read-client-chain.test.ts +159 -0
- package/src/api/read-client.ts +42 -6
- package/src/api/sigv4.ts +4 -4
- package/src/caller-identity.ts +3 -5
- package/src/codegen/any-budget.test.ts +12 -2
- package/src/codegen/generate.ts +9 -0
- package/src/codegen/package.ts +2 -2
- package/src/codegen/patches.test.ts +95 -0
- package/src/codegen/patches.ts +53 -9
- package/src/codegen/property-overlay.json +1 -16
- package/src/components/apply.ts +218 -6
- package/src/components/cfn-plan-floci.e2e.test.ts +76 -0
- package/src/components/cfn-plan.test.ts +225 -16
- package/src/components/cloud-executor.ts +73 -25
- package/src/deep-observe.ts +2 -1
- package/src/disruption.ts +2 -1
- package/src/generated/index.d.ts +18847 -1124
- package/src/generated/index.ts +1376 -161
- package/src/generated/lexicon-aws.json +17359 -784
- package/src/identity-observe.ts +2 -1
- package/src/lint/post-synth/ext001.ts +3 -3
- package/src/lint/post-synth/waw016.ts +2 -2
- package/src/lsp/completions.ts +2 -1
- package/src/lsp/hover.ts +2 -1
- package/src/plugin.ts +2 -1
- package/src/receipt-store.ts +2 -1
- package/src/spec/pin.ts +3 -3
- package/src/spec/pinned-types.json +203 -0
- package/src/taggable.ts +2 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Thin entry point for `npm run validate` in lexicon-aws.
|
|
4
|
+
*/
|
|
5
|
+
import { validate } from "./validate.js";
|
|
6
|
+
const result = await validate();
|
|
7
|
+
for (const check of result.checks) {
|
|
8
|
+
const status = check.ok ? "OK" : "FAIL";
|
|
9
|
+
const msg = check.error ? ` — ${check.error}` : "";
|
|
10
|
+
console.error(` [${status}] ${check.name}${msg}`);
|
|
11
|
+
}
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
console.error("Validation failed");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
console.error("All validation checks passed.");
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate generated lexicon-aws artifacts.
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper around the core validation framework
|
|
5
|
+
* with AWS-specific configuration.
|
|
6
|
+
*/
|
|
7
|
+
import { dirname } from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
import { validateLexiconArtifacts } from "@intentius/chant/codegen/validate";
|
|
10
|
+
const REQUIRED_NAMES = ["Bucket", "Function", "Role", "Table", "Policy", "LogGroup"];
|
|
11
|
+
/**
|
|
12
|
+
* Validate the generated lexicon-aws artifacts.
|
|
13
|
+
*
|
|
14
|
+
* @param opts.basePath - Override the package directory (defaults to lexicon-aws package root)
|
|
15
|
+
*/
|
|
16
|
+
export async function validate(opts) {
|
|
17
|
+
const basePath = opts?.basePath ?? dirname(dirname(fileURLToPath(import.meta.url)));
|
|
18
|
+
return validateLexiconArtifacts({
|
|
19
|
+
lexiconJsonFilename: "lexicon-aws.json",
|
|
20
|
+
requiredNames: REQUIRED_NAMES,
|
|
21
|
+
basePath,
|
|
22
|
+
// chant #1473 — this is the release gate for aws. `prepack` regenerates
|
|
23
|
+
// from a CloudFormation archive that is republished several times a day,
|
|
24
|
+
// so the spec pin cannot decide whether a build is safe to ship; what must
|
|
25
|
+
// match the reviewed baseline is the API that comes out.
|
|
26
|
+
checkSurfaceSnapshot: true,
|
|
27
|
+
coverageThresholds: {
|
|
28
|
+
minPropertyPct: 1,
|
|
29
|
+
minLifecyclePct: 1,
|
|
30
|
+
minAttrPct: 1,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-aws",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.32",
|
|
4
4
|
"description": "AWS CloudFormation lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -32,32 +32,32 @@
|
|
|
32
32
|
".": {
|
|
33
33
|
"development": "./src/index.ts",
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
|
-
"default": "./
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
36
|
},
|
|
37
37
|
"./*": {
|
|
38
38
|
"development": "./src/*.ts",
|
|
39
39
|
"types": "./dist/*.d.ts",
|
|
40
|
-
"default": "./
|
|
40
|
+
"default": "./dist/*.js"
|
|
41
41
|
},
|
|
42
42
|
"./components": {
|
|
43
43
|
"development": "./src/components/index.ts",
|
|
44
44
|
"types": "./dist/components/index.d.ts",
|
|
45
|
-
"default": "./
|
|
45
|
+
"default": "./dist/components/index.js"
|
|
46
46
|
},
|
|
47
47
|
"./op/activities": {
|
|
48
48
|
"development": "./src/op/activities/index.ts",
|
|
49
49
|
"types": "./dist/op/activities/index.d.ts",
|
|
50
|
-
"default": "./
|
|
50
|
+
"default": "./dist/op/activities/index.js"
|
|
51
51
|
},
|
|
52
52
|
"./detect": {
|
|
53
53
|
"development": "./src/detect.ts",
|
|
54
54
|
"types": "./dist/detect.d.ts",
|
|
55
|
-
"default": "./
|
|
55
|
+
"default": "./dist/detect.js"
|
|
56
56
|
},
|
|
57
57
|
"./lint/post-synth": {
|
|
58
58
|
"development": "./src/lint/post-synth/index.ts",
|
|
59
59
|
"types": "./dist/lint/post-synth/index.d.ts",
|
|
60
|
-
"default": "./
|
|
60
|
+
"default": "./dist/lint/post-synth/index.js"
|
|
61
61
|
},
|
|
62
62
|
"./manifest": "./dist/manifest.json",
|
|
63
63
|
"./meta": "./dist/meta.json",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"validate": "tsx src/validate-cli.ts",
|
|
70
70
|
"docs": "tsx src/codegen/docs-cli.ts",
|
|
71
71
|
"prepack": "npm run generate && npm run bundle && npm run validate && npm run build",
|
|
72
|
-
"build": "../../scripts/tsc7.sh -p tsconfig.build.json && tsc-alias -p tsconfig.build.json
|
|
72
|
+
"build": "../../scripts/tsc7.sh -p tsconfig.build.json --sourceMap false && tsc-alias -p tsconfig.build.json"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"fflate": "^0.8.2",
|
|
@@ -80,6 +80,6 @@
|
|
|
80
80
|
"typescript": "^5.9.3"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"@intentius/chant": "^0.124.
|
|
83
|
+
"@intentius/chant": "^0.124.32"
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -80,6 +80,7 @@ import {
|
|
|
80
80
|
AwsReadError,
|
|
81
81
|
requestHeaders,
|
|
82
82
|
serviceUrl,
|
|
83
|
+
withChainCredentials,
|
|
83
84
|
withEndpointOverride,
|
|
84
85
|
type AwsCredentialSource,
|
|
85
86
|
type AwsReadHttp,
|
|
@@ -536,7 +537,7 @@ async function agentCorePost(
|
|
|
536
537
|
http: AwsReadHttp,
|
|
537
538
|
signal?: AbortSignal,
|
|
538
539
|
): Promise<Record<string, unknown>> {
|
|
539
|
-
const options = withEndpointOverride(SERVICE, readOptions);
|
|
540
|
+
const options = await withChainCredentials(withEndpointOverride(SERVICE, readOptions));
|
|
540
541
|
const url = `${serviceUrl(SERVICE, options.endpoint, options.region)}${path.replace(/^\//, "")}`;
|
|
541
542
|
const wire = JSON.stringify(body);
|
|
542
543
|
const res = await http(
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* than keys: `AWS_PROFILE=dev` with an SSO session came back as "no identity
|
|
9
9
|
* is configured" while `aws sts get-caller-identity` answered. This module is
|
|
10
10
|
* the asynchronous half: it resolves what the CLI would sign with and hands
|
|
11
|
-
* back literal credentials plus a label for where they came from.
|
|
11
|
+
* back literal credentials plus a label for where they came from. The read
|
|
12
|
+
* transport uses the same walk through {@link transportCredentials} (#3958),
|
|
13
|
+
* so whoami and `describeResources` sign as the same principal.
|
|
12
14
|
*
|
|
13
15
|
* There is still no `@aws-sdk/*` here, for the reason the read transport gives:
|
|
14
16
|
* a lexicon keeps that tree out. The chain is small enough to state.
|
|
@@ -16,8 +18,7 @@
|
|
|
16
18
|
* ## Order
|
|
17
19
|
*
|
|
18
20
|
* 1. `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` (+ `AWS_SESSION_TOKEN`).
|
|
19
|
-
* They win over `AWS_PROFILE`, as they do in the AWS CLI
|
|
20
|
-
* in chant's own read transport, which signs with nothing else. (The JS
|
|
21
|
+
* They win over `AWS_PROFILE`, as they do in the AWS CLI. (The JS
|
|
21
22
|
* SDK v3 skips the environment when `AWS_PROFILE` is set; the CLI does
|
|
22
23
|
* not, and the CLI is what an operator checks whoami against.) When both
|
|
23
24
|
* are set, the label says the profile was not used.
|
|
@@ -90,6 +91,8 @@ export interface ResolvedChainCredentials {
|
|
|
90
91
|
source: string;
|
|
91
92
|
/** The profile that resolved them, when one did. */
|
|
92
93
|
profile?: string;
|
|
94
|
+
/** When the credentials stop working, for role, SSO and `credential_process` credentials that say so. */
|
|
95
|
+
expiration?: Date;
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
export interface UnresolvedChainCredentials {
|
|
@@ -103,6 +106,20 @@ export type CredentialChainResult =
|
|
|
103
106
|
|
|
104
107
|
type Section = Record<string, string>;
|
|
105
108
|
|
|
109
|
+
/** One link of the chain's answer, before the profile name is attached. */
|
|
110
|
+
interface Resolved {
|
|
111
|
+
credentials: AwsCredentials;
|
|
112
|
+
source: string;
|
|
113
|
+
expiration?: Date;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** A timestamp as a Date, or undefined when it is absent or does not parse. */
|
|
117
|
+
function expiryOf(value: string | number | undefined): Date | undefined {
|
|
118
|
+
if (value === undefined || value === "") return undefined;
|
|
119
|
+
const ms = typeof value === "number" ? value : Date.parse(value);
|
|
120
|
+
return Number.isFinite(ms) ? new Date(ms) : undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
106
123
|
/**
|
|
107
124
|
* The INI dialect of the AWS shared files: `[section]`, `key = value`, `#` and
|
|
108
125
|
* `;` comments on their own line (not inline: a `credential_process` command
|
|
@@ -263,7 +280,7 @@ async function resolveProfile(
|
|
|
263
280
|
ctx: Context,
|
|
264
281
|
name: string,
|
|
265
282
|
visited: string[],
|
|
266
|
-
): Promise<
|
|
283
|
+
): Promise<Resolved> {
|
|
267
284
|
if (visited.includes(name)) {
|
|
268
285
|
throw new ChainRefusal("no-credentials", `profile ${name}: source_profile loops (${[...visited, name].join(" -> ")})`);
|
|
269
286
|
}
|
|
@@ -303,16 +320,26 @@ async function resolveProfile(
|
|
|
303
320
|
);
|
|
304
321
|
}
|
|
305
322
|
|
|
323
|
+
function withExpiry(expiration: Date | undefined): { expiration?: Date } {
|
|
324
|
+
return expiration ? { expiration } : {};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function earliest(a: Date | undefined, b: Date | undefined): Date | undefined {
|
|
328
|
+
if (!a) return b;
|
|
329
|
+
if (!b) return a;
|
|
330
|
+
return a.getTime() <= b.getTime() ? a : b;
|
|
331
|
+
}
|
|
332
|
+
|
|
306
333
|
async function resolveRoleProfile(
|
|
307
334
|
ctx: Context,
|
|
308
335
|
name: string,
|
|
309
336
|
p: Section,
|
|
310
337
|
visited: string[],
|
|
311
|
-
): Promise<
|
|
338
|
+
): Promise<Resolved> {
|
|
312
339
|
if (p.mfa_serial) {
|
|
313
340
|
throw new ChainRefusal("no-credentials", `profile ${name} sets mfa_serial; chant cannot prompt for an MFA code`);
|
|
314
341
|
}
|
|
315
|
-
let base:
|
|
342
|
+
let base: Resolved;
|
|
316
343
|
if (p.source_profile) {
|
|
317
344
|
base = await resolveProfile(ctx, p.source_profile, [...visited, name]);
|
|
318
345
|
} else if (p.credential_source === "Environment") {
|
|
@@ -351,6 +378,7 @@ async function resolveRoleProfile(
|
|
|
351
378
|
sessionToken: assumed.sessionToken,
|
|
352
379
|
},
|
|
353
380
|
source: `profile ${name} (role ${p.role_arn} via ${base.source})`,
|
|
381
|
+
...withExpiry(earliest(expiryOf(assumed.expiration), base.expiration)),
|
|
354
382
|
};
|
|
355
383
|
} catch (err) {
|
|
356
384
|
const what = err instanceof AwsReadError ? `${err.code ? `${err.code}: ` : ""}${err.message}` : String(err);
|
|
@@ -376,7 +404,7 @@ async function resolveSsoProfile(
|
|
|
376
404
|
ctx: Context,
|
|
377
405
|
name: string,
|
|
378
406
|
p: Section,
|
|
379
|
-
): Promise<
|
|
407
|
+
): Promise<Resolved> {
|
|
380
408
|
let startUrl = p.sso_start_url;
|
|
381
409
|
let ssoRegion = p.sso_region;
|
|
382
410
|
let cacheKey = startUrl;
|
|
@@ -446,7 +474,7 @@ async function resolveSsoProfile(
|
|
|
446
474
|
if (res.status >= 400) {
|
|
447
475
|
throw new ChainRefusal("read-failed", `profile ${name}: sso:GetRoleCredentials for ${roleName} in ${accountId} failed with HTTP ${res.status}`);
|
|
448
476
|
}
|
|
449
|
-
let role: { accessKeyId?: string; secretAccessKey?: string; sessionToken?: string } | undefined;
|
|
477
|
+
let role: { accessKeyId?: string; secretAccessKey?: string; sessionToken?: string; expiration?: number } | undefined;
|
|
450
478
|
try {
|
|
451
479
|
role = (JSON.parse(res.text) as { roleCredentials?: typeof role }).roleCredentials;
|
|
452
480
|
} catch {
|
|
@@ -462,6 +490,7 @@ async function resolveSsoProfile(
|
|
|
462
490
|
...(role.sessionToken ? { sessionToken: role.sessionToken } : {}),
|
|
463
491
|
},
|
|
464
492
|
source: `${label}, role ${roleName} in ${accountId}`,
|
|
493
|
+
...withExpiry(expiryOf(role.expiration)),
|
|
465
494
|
};
|
|
466
495
|
}
|
|
467
496
|
|
|
@@ -501,7 +530,7 @@ async function resolveProcessProfile(
|
|
|
501
530
|
ctx: Context,
|
|
502
531
|
name: string,
|
|
503
532
|
command: string,
|
|
504
|
-
): Promise<
|
|
533
|
+
): Promise<Resolved> {
|
|
505
534
|
const out = await ctx.runProcess(command);
|
|
506
535
|
if (out.exitCode !== 0) {
|
|
507
536
|
const firstLine = out.stderr.trim().split(/\r?\n/)[0] ?? "";
|
|
@@ -532,5 +561,86 @@ async function resolveProcessProfile(
|
|
|
532
561
|
...(parsed.SessionToken ? { sessionToken: parsed.SessionToken } : {}),
|
|
533
562
|
},
|
|
534
563
|
source: `profile ${name} (credential_process)`,
|
|
564
|
+
...withExpiry(expiryOf(parsed.Expiration)),
|
|
535
565
|
};
|
|
536
566
|
}
|
|
567
|
+
|
|
568
|
+
/* ── Credentials for the read transport (#3958) ─────────────────────────── */
|
|
569
|
+
|
|
570
|
+
/** Cached credentials are re-resolved this long before they expire. */
|
|
571
|
+
export const TRANSPORT_REFRESH_MARGIN_MS = 5 * 60_000;
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* How long "nothing resolves" is kept before the chain is walked again, so a
|
|
575
|
+
* long-running process picks up an `aws sso login` done after it started.
|
|
576
|
+
*/
|
|
577
|
+
export const TRANSPORT_UNRESOLVED_TTL_MS = 5 * 60_000;
|
|
578
|
+
|
|
579
|
+
interface TransportEntry {
|
|
580
|
+
credentials?: AwsCredentials;
|
|
581
|
+
/** Epoch ms after which the entry is walked again. */
|
|
582
|
+
refreshAt: number;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* One walk per environment and shared-file location, shared by every read in
|
|
587
|
+
* the process. Concurrent first reads await the same promise, so an SSO
|
|
588
|
+
* portal call or a `credential_process` runs once rather than once per read.
|
|
589
|
+
*/
|
|
590
|
+
const transportCache = new Map<string, Promise<TransportEntry>>();
|
|
591
|
+
|
|
592
|
+
/** Forget every cached walk. For tests, and for a process that changed its profile. */
|
|
593
|
+
export function resetTransportCredentials(): void {
|
|
594
|
+
transportCache.clear();
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
async function walkForTransport(options: CredentialChainOptions, now: () => Date): Promise<TransportEntry> {
|
|
598
|
+
let result: CredentialChainResult | undefined;
|
|
599
|
+
try {
|
|
600
|
+
result = await resolveCredentialChain(options);
|
|
601
|
+
} catch {
|
|
602
|
+
result = undefined;
|
|
603
|
+
}
|
|
604
|
+
const t = now().getTime();
|
|
605
|
+
if (!result || "unresolved" in result) return { refreshAt: t + TRANSPORT_UNRESOLVED_TTL_MS };
|
|
606
|
+
const expires = result.resolved.expiration?.getTime();
|
|
607
|
+
if (expires === undefined) return { credentials: result.resolved.credentials, refreshAt: Infinity };
|
|
608
|
+
const early = expires - TRANSPORT_REFRESH_MARGIN_MS;
|
|
609
|
+
return { credentials: result.resolved.credentials, refreshAt: early > t ? early : expires };
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* What the native read transport signs with when the caller injected nothing:
|
|
614
|
+
* the same chain whoami walks, so `lifecycle diff --live` signs as the
|
|
615
|
+
* principal whoami reports. The signing seam (`AwsCredentialResolver` in
|
|
616
|
+
* ./sigv4.ts) is synchronous and the chain is not, so the transport awaits
|
|
617
|
+
* this once before a request and passes the literal credentials in.
|
|
618
|
+
*
|
|
619
|
+
* Environment keys answer directly, as in the chain. Otherwise the walk is
|
|
620
|
+
* cached per process, keyed by the profile and the shared-file locations, and
|
|
621
|
+
* walked again within {@link TRANSPORT_REFRESH_MARGIN_MS} of the expiry the
|
|
622
|
+
* role, SSO or `credential_process` answer carried. A refusal or a failure is
|
|
623
|
+
* `undefined`, which leaves the request unsigned exactly as before; it is kept
|
|
624
|
+
* for {@link TRANSPORT_UNRESOLVED_TTL_MS}.
|
|
625
|
+
*/
|
|
626
|
+
export async function transportCredentials(options: CredentialChainOptions = {}): Promise<AwsCredentials | undefined> {
|
|
627
|
+
const env = options.env ?? process.env;
|
|
628
|
+
const fromEnv = envCredentials(env);
|
|
629
|
+
if (fromEnv) return fromEnv;
|
|
630
|
+
const now = options.now ?? (() => new Date());
|
|
631
|
+
const home = options.home ?? (env.HOME || env.USERPROFILE || homedir());
|
|
632
|
+
const key = JSON.stringify([env.AWS_PROFILE ?? "", env.AWS_CONFIG_FILE ?? "", env.AWS_SHARED_CREDENTIALS_FILE ?? "", home]);
|
|
633
|
+
|
|
634
|
+
const cached = transportCache.get(key);
|
|
635
|
+
if (cached) {
|
|
636
|
+
const entry = await cached;
|
|
637
|
+
if (now().getTime() < entry.refreshAt) return entry.credentials;
|
|
638
|
+
if (transportCache.get(key) === cached) transportCache.delete(key);
|
|
639
|
+
}
|
|
640
|
+
let pending = transportCache.get(key);
|
|
641
|
+
if (!pending) {
|
|
642
|
+
pending = walkForTransport({ ...options, env, home }, now);
|
|
643
|
+
transportCache.set(key, pending);
|
|
644
|
+
}
|
|
645
|
+
return (await pending).credentials;
|
|
646
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The unit project keeps the developer's ~/.aws out of reach (#3958).
|
|
3
|
+
* test/aws-credential-isolation.setup.ts strips the credential variables and
|
|
4
|
+
* points the shared files at paths that do not exist. These tests put a
|
|
5
|
+
* `credential_process` profile under a HOME that the chain would otherwise
|
|
6
|
+
* read and check that a read with no injected `env` never runs it.
|
|
7
|
+
*/
|
|
8
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
9
|
+
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { describeStackResources, type AwsReadHttp } from "./read-client";
|
|
13
|
+
import { resetTransportCredentials, resolveCredentialChain, transportCredentials } from "./credential-chain";
|
|
14
|
+
|
|
15
|
+
const stackXml =
|
|
16
|
+
"<DescribeStackResourcesResponse><DescribeStackResourcesResult><StackResources></StackResources>" +
|
|
17
|
+
"</DescribeStackResourcesResult></DescribeStackResourcesResponse>";
|
|
18
|
+
|
|
19
|
+
let home: string;
|
|
20
|
+
let marker: string;
|
|
21
|
+
let savedHome: string | undefined;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
resetTransportCredentials();
|
|
25
|
+
home = mkdtempSync(join(tmpdir(), "chant-aws-isolation-"));
|
|
26
|
+
marker = join(home, "credential-process-ran");
|
|
27
|
+
mkdirSync(join(home, ".aws"));
|
|
28
|
+
// The command writes the marker and prints nothing, so the chain refuses its
|
|
29
|
+
// output; the marker alone says whether it ran.
|
|
30
|
+
writeFileSync(join(home, ".aws", "config"), `[default]\ncredential_process = touch '${marker}'\n`);
|
|
31
|
+
savedHome = process.env.HOME;
|
|
32
|
+
process.env.HOME = home;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
if (savedHome === undefined) delete process.env.HOME;
|
|
37
|
+
else process.env.HOME = savedHome;
|
|
38
|
+
rmSync(home, { recursive: true, force: true });
|
|
39
|
+
resetTransportCredentials();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("unit tests do not read the real AWS shared files (#3958)", () => {
|
|
43
|
+
test("the setup file cleared the credential variables and pointed the shared files nowhere", () => {
|
|
44
|
+
for (const name of ["AWS_PROFILE", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"]) {
|
|
45
|
+
expect(process.env[name]).toBeUndefined();
|
|
46
|
+
}
|
|
47
|
+
expect(process.env.AWS_CONFIG_FILE).toBeTruthy();
|
|
48
|
+
expect(existsSync(process.env.AWS_CONFIG_FILE!)).toBe(false);
|
|
49
|
+
expect(process.env.AWS_SHARED_CREDENTIALS_FILE).toBeTruthy();
|
|
50
|
+
expect(existsSync(process.env.AWS_SHARED_CREDENTIALS_FILE!)).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("a read with no injected env goes out unsigned and runs no credential_process", async () => {
|
|
54
|
+
const auth: string[] = [];
|
|
55
|
+
const http: AwsReadHttp = async (_url, init) => {
|
|
56
|
+
auth.push(init.headers.authorization ?? "");
|
|
57
|
+
return { status: 200, text: stackXml };
|
|
58
|
+
};
|
|
59
|
+
await describeStackResources("app", { http, region: "us-east-1" });
|
|
60
|
+
expect(auth[0]).toContain("Signature=unsigned");
|
|
61
|
+
expect(await transportCredentials()).toBeUndefined();
|
|
62
|
+
const chain = await resolveCredentialChain();
|
|
63
|
+
expect("unresolved" in chain).toBe(true);
|
|
64
|
+
expect(existsSync(marker)).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("control: the same HOME injected without the setup's file paths does run the command", async () => {
|
|
68
|
+
const result = await resolveCredentialChain({ env: { HOME: home } });
|
|
69
|
+
expect("unresolved" in result).toBe(true);
|
|
70
|
+
expect(existsSync(marker)).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The read transport signs with the AWS CLI's credential chain (#3958), the
|
|
3
|
+
* same walk `chant lifecycle whoami` does (#3954). Shared files live in a temp
|
|
4
|
+
* directory and HTTP is injected, so nothing reads the real `~/.aws` or
|
|
5
|
+
* reaches a network.
|
|
6
|
+
*/
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
8
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { describeStackResources, getCallerIdentity, type AwsReadHttp } from "./read-client";
|
|
12
|
+
import { resetTransportCredentials, transportCredentials, TRANSPORT_REFRESH_MARGIN_MS } from "./credential-chain";
|
|
13
|
+
import { ssmCall } from "../receipt-store";
|
|
14
|
+
|
|
15
|
+
const stackXml =
|
|
16
|
+
"<DescribeStackResourcesResponse><DescribeStackResourcesResult><StackResources></StackResources>" +
|
|
17
|
+
"</DescribeStackResourcesResult></DescribeStackResourcesResponse>";
|
|
18
|
+
|
|
19
|
+
function recording(text: (url: string, body: string) => string) {
|
|
20
|
+
const calls: Array<{ url: string; headers: Record<string, string>; body: string }> = [];
|
|
21
|
+
const http: AwsReadHttp = async (url, init) => {
|
|
22
|
+
calls.push({ url, headers: init.headers, body: init.body });
|
|
23
|
+
return { status: 200, text: text(url, init.body) };
|
|
24
|
+
};
|
|
25
|
+
return { http, calls };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let home: string;
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
resetTransportCredentials();
|
|
31
|
+
home = mkdtempSync(join(tmpdir(), "chant-aws-chain-"));
|
|
32
|
+
});
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
rmSync(home, { recursive: true, force: true });
|
|
35
|
+
resetTransportCredentials();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
function writeAws(config: string, credentials = ""): Record<string, string> {
|
|
39
|
+
const configPath = join(home, "config");
|
|
40
|
+
const credentialsPath = join(home, "credentials");
|
|
41
|
+
writeFileSync(configPath, config);
|
|
42
|
+
writeFileSync(credentialsPath, credentials);
|
|
43
|
+
return { HOME: home, AWS_CONFIG_FILE: configPath, AWS_SHARED_CREDENTIALS_FILE: credentialsPath };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe("the read transport walks the credential chain (#3958)", () => {
|
|
47
|
+
test("AWS_PROFILE with static keys in the shared credentials file signs a CloudFormation read", async () => {
|
|
48
|
+
const env = { ...writeAws("[profile dev]\nregion = eu-west-1\n", "[dev]\naws_access_key_id = AKIDPROFILE\naws_secret_access_key = secret\n"), AWS_PROFILE: "dev" };
|
|
49
|
+
const { http, calls } = recording(() => stackXml);
|
|
50
|
+
await describeStackResources("app", { http, env, region: "eu-west-1" });
|
|
51
|
+
const auth = calls[0]!.headers.authorization ?? "";
|
|
52
|
+
expect(auth).toMatch(/^AWS4-HMAC-SHA256 Credential=AKIDPROFILE\/\d{8}\/eu-west-1\/cloudformation\/aws4_request/);
|
|
53
|
+
expect(auth).not.toContain("Signature=unsigned");
|
|
54
|
+
expect(calls[0]!.headers["x-amz-date"]).toBeDefined();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("the default profile signs when AWS_PROFILE is unset, and the SSM receipt store signs too", async () => {
|
|
58
|
+
const env = writeAws("", "[default]\naws_access_key_id = AKIDDEFAULT\naws_secret_access_key = secret\naws_session_token = tok\n");
|
|
59
|
+
const { http, calls } = recording(() => "{}");
|
|
60
|
+
await ssmCall("GetParameter", { Name: "/x" }, { http, env });
|
|
61
|
+
expect(calls[0]!.headers.authorization).toMatch(/Credential=AKIDDEFAULT\/.*\/ssm\/aws4_request/);
|
|
62
|
+
expect(calls[0]!.headers["x-amz-security-token"]).toBe("tok");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("a role_arn profile assumes the role once and signs later reads with the role's keys", async () => {
|
|
66
|
+
const env = {
|
|
67
|
+
...writeAws(
|
|
68
|
+
"[profile ops]\nrole_arn = arn:aws:iam::111122223333:role/ops\nsource_profile = base\n",
|
|
69
|
+
"[base]\naws_access_key_id = AKIDBASE\naws_secret_access_key = secret\n",
|
|
70
|
+
),
|
|
71
|
+
AWS_PROFILE: "ops",
|
|
72
|
+
};
|
|
73
|
+
const expiration = new Date(Date.now() + 3600_000).toISOString();
|
|
74
|
+
const { http, calls } = recording((_url, body) =>
|
|
75
|
+
body.includes("Action=AssumeRole")
|
|
76
|
+
? `<AssumeRoleResponse><AssumeRoleResult><Credentials><AccessKeyId>ASIAROLE</AccessKeyId><SecretAccessKey>s</SecretAccessKey><SessionToken>t</SessionToken><Expiration>${expiration}</Expiration></Credentials></AssumeRoleResult></AssumeRoleResponse>`
|
|
77
|
+
: body.includes("GetCallerIdentity")
|
|
78
|
+
? "<GetCallerIdentityResponse><GetCallerIdentityResult><Arn>arn:aws:sts::111122223333:assumed-role/ops/x</Arn><Account>111122223333</Account></GetCallerIdentityResult></GetCallerIdentityResponse>"
|
|
79
|
+
: stackXml,
|
|
80
|
+
);
|
|
81
|
+
await Promise.all([describeStackResources("a", { http, env }), describeStackResources("b", { http, env })]);
|
|
82
|
+
await getCallerIdentity({ http, env });
|
|
83
|
+
const assume = calls.filter((c) => c.body.includes("Action=AssumeRole"));
|
|
84
|
+
expect(assume).toHaveLength(1);
|
|
85
|
+
expect(assume[0]!.headers.authorization).toContain("Credential=AKIDBASE/");
|
|
86
|
+
const reads = calls.filter((c) => !c.body.includes("Action=AssumeRole"));
|
|
87
|
+
expect(reads).toHaveLength(3);
|
|
88
|
+
for (const r of reads) expect(r.headers.authorization).toContain("Credential=ASIAROLE/");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("environment keys still win over AWS_PROFILE", async () => {
|
|
92
|
+
const env = {
|
|
93
|
+
...writeAws("", "[dev]\naws_access_key_id = AKIDPROFILE\naws_secret_access_key = secret\n"),
|
|
94
|
+
AWS_PROFILE: "dev",
|
|
95
|
+
AWS_ACCESS_KEY_ID: "AKIDENV",
|
|
96
|
+
AWS_SECRET_ACCESS_KEY: "secret",
|
|
97
|
+
};
|
|
98
|
+
const { http, calls } = recording(() => stackXml);
|
|
99
|
+
await describeStackResources("app", { http, env });
|
|
100
|
+
expect(calls[0]!.headers.authorization).toContain("Credential=AKIDENV/");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("an endpoint override stays unsigned and the chain is not walked", async () => {
|
|
104
|
+
const env = { ...writeAws("[profile tool]\ncredential_process = definitely-not-a-command\n"), AWS_PROFILE: "tool" };
|
|
105
|
+
const { http, calls } = recording(() => stackXml);
|
|
106
|
+
await describeStackResources("app", { http, env, endpoint: "http://localhost:4566", region: "us-west-1" });
|
|
107
|
+
expect(calls[0]!.headers.authorization).toContain("Signature=unsigned");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("an injected environment that names no shared files does not read the process's ~/.aws", async () => {
|
|
111
|
+
const { http, calls } = recording(() => stackXml);
|
|
112
|
+
await describeStackResources("app", { http, env: {}, region: "us-east-1" });
|
|
113
|
+
expect(calls[0]!.headers.authorization).toContain("Signature=unsigned");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("a profile that does not resolve leaves the read unsigned, as before", async () => {
|
|
117
|
+
const env = { ...writeAws("[profile s]\nsso_start_url = https://a/start\nsso_region = us-east-1\nsso_account_id = 1\nsso_role_name = R\n"), AWS_PROFILE: "s" };
|
|
118
|
+
const { http, calls } = recording(() => stackXml);
|
|
119
|
+
await describeStackResources("app", { http, env, region: "us-east-1" });
|
|
120
|
+
expect(calls[0]!.headers.authorization).toContain("Signature=unsigned");
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe("transportCredentials caching", () => {
|
|
125
|
+
test("credentials are resolved once and walked again within the refresh margin of their expiry", async () => {
|
|
126
|
+
const env = { ...writeAws("[profile tool]\ncredential_process = issue\n"), AWS_PROFILE: "tool" };
|
|
127
|
+
let t = Date.parse("2026-10-19T12:00:00Z");
|
|
128
|
+
const expires = t + 3600_000;
|
|
129
|
+
let runs = 0;
|
|
130
|
+
const runProcess = async () => {
|
|
131
|
+
runs++;
|
|
132
|
+
return {
|
|
133
|
+
exitCode: 0,
|
|
134
|
+
stderr: "",
|
|
135
|
+
stdout: JSON.stringify({ Version: 1, AccessKeyId: `AKID${runs}`, SecretAccessKey: "s", Expiration: new Date(expires + (runs - 1) * 3600_000).toISOString() }),
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
const options = { env, runProcess, now: () => new Date(t) };
|
|
139
|
+
expect((await transportCredentials(options))?.accessKeyId).toBe("AKID1");
|
|
140
|
+
t = expires - TRANSPORT_REFRESH_MARGIN_MS - 1;
|
|
141
|
+
expect((await transportCredentials(options))?.accessKeyId).toBe("AKID1");
|
|
142
|
+
expect(runs).toBe(1);
|
|
143
|
+
t = expires - TRANSPORT_REFRESH_MARGIN_MS + 1;
|
|
144
|
+
expect((await transportCredentials(options))?.accessKeyId).toBe("AKID2");
|
|
145
|
+
expect(runs).toBe(2);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("concurrent first calls share one walk", async () => {
|
|
149
|
+
const env = { ...writeAws("[profile tool]\ncredential_process = issue\n"), AWS_PROFILE: "tool" };
|
|
150
|
+
let runs = 0;
|
|
151
|
+
const runProcess = async () => {
|
|
152
|
+
runs++;
|
|
153
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
154
|
+
return { exitCode: 0, stderr: "", stdout: JSON.stringify({ Version: 1, AccessKeyId: "AKID", SecretAccessKey: "s" }) };
|
|
155
|
+
};
|
|
156
|
+
await Promise.all([1, 2, 3].map(() => transportCredentials({ env, runProcess })));
|
|
157
|
+
expect(runs).toBe(1);
|
|
158
|
+
});
|
|
159
|
+
});
|