@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,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The native AWS read transport (#1206) — the read half of what
|
|
3
|
+
* `op/activities/aws-apply.ts` already does for writes.
|
|
4
|
+
*
|
|
5
|
+
* Every AWS observer shelled `aws …` once per entity, serially, and parsed
|
|
6
|
+
* stderr to find out what went wrong (#1085). The applier does not: `awsApply`
|
|
7
|
+
* speaks the CloudFormation Query protocol over `fetch`, honours an endpoint
|
|
8
|
+
* override, and is injectable for tests. This module is that same transport
|
|
9
|
+
* pointed at the two APIs the read path needs:
|
|
10
|
+
*
|
|
11
|
+
* - **CloudFormation Query** (form-encoded POST, XML back) — the stack reads
|
|
12
|
+
* `describeResources` and the deep pass both start from.
|
|
13
|
+
* - **Cloud Control** (AWS JSON 1.0, `X-Amz-Target: CloudApiService.*`) — the
|
|
14
|
+
* property-level reads (#1015).
|
|
15
|
+
*
|
|
16
|
+
* Both take the endpoint the same way the applier does, so `chant emulator` /
|
|
17
|
+
* behold `--local` keep working by construction rather than by each observer
|
|
18
|
+
* remembering to inject `--endpoint-url`.
|
|
19
|
+
*
|
|
20
|
+
* ## Signing
|
|
21
|
+
*
|
|
22
|
+
* Requests are signed with SigV4 (#1686) when credentials resolve — see
|
|
23
|
+
* `./sigv4.ts`, which holds the implementation so that cedar's AVP client can
|
|
24
|
+
* adopt the same one rather than growing a second. With none injected, they
|
|
25
|
+
* resolve through the AWS CLI's chain (`./credential-chain.ts`, the one
|
|
26
|
+
* `chant lifecycle whoami` walks) once per process, by
|
|
27
|
+
* {@link withChainCredentials} (#3958). Two cases stay unsigned, and both are
|
|
28
|
+
* deliberate:
|
|
29
|
+
*
|
|
30
|
+
* - **No credentials.** The caller's existing no-credentials path is
|
|
31
|
+
* untouched: the request still goes out carrying only the credential scope
|
|
32
|
+
* of {@link regionScope}, which is what the emulator lanes have always
|
|
33
|
+
* sent.
|
|
34
|
+
* - **An endpoint override.** Floci does not verify signatures, and signing
|
|
35
|
+
* against it would mean every local lane suddenly needs credentials to read
|
|
36
|
+
* what it just deployed. `signEndpointOverride` opts back in for an
|
|
37
|
+
* override that *is* real AWS — a VPC endpoint, a signing proxy.
|
|
38
|
+
*
|
|
39
|
+
* What counts as an override is one rule, {@link resolveEndpointOverride}: the
|
|
40
|
+
* `endpoint` option, else the ambient `AWS_ENDPOINT_URL_<SERVICE>` the AWS SDK
|
|
41
|
+
* honours per service, else `AWS_ENDPOINT_URL` (#1694). Cedar's AVP client
|
|
42
|
+
* (`lexicons/cedar/src/avp/client.ts`) applies the same rule; it restates it
|
|
43
|
+
* rather than importing it, because cedar does not depend on this lexicon and
|
|
44
|
+
* a lexicon build compiles against the published core, so a helper hoisted
|
|
45
|
+
* into core would not be visible to either until the next core release.
|
|
46
|
+
*/
|
|
47
|
+
import { homedir } from "node:os";
|
|
48
|
+
import { transportCredentials } from "./credential-chain.js";
|
|
49
|
+
import { resolveCredentials, signRequest } from "./sigv4.js";
|
|
50
|
+
const DEFAULT_REGION = "us-east-1";
|
|
51
|
+
const CFN_API_VERSION = "2010-05-15";
|
|
52
|
+
const CLOUD_CONTROL_TARGET_PREFIX = "CloudApiService";
|
|
53
|
+
const defaultHttp = async (url, init, signal) => {
|
|
54
|
+
const res = await fetch(url, { method: "POST", headers: init.headers, body: init.body, signal });
|
|
55
|
+
return { status: res.status, text: await res.text() };
|
|
56
|
+
};
|
|
57
|
+
/** A failed read, carrying enough to classify it without parsing prose. */
|
|
58
|
+
export class AwsReadError extends Error {
|
|
59
|
+
constructor(message, status,
|
|
60
|
+
/** The API's own error code (`ValidationError`, `UnsupportedOperation`, …) when it sent one. */
|
|
61
|
+
code) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.status = status;
|
|
64
|
+
this.code = code;
|
|
65
|
+
this.name = "AwsReadError";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The SDK's per-service endpoint variable for a signing-service name:
|
|
70
|
+
* `AWS_ENDPOINT_URL_<SERVICE ID>`, the service id upper-cased with every
|
|
71
|
+
* non-alphanumeric run replaced by `_`. The SDK keys that by the service id of
|
|
72
|
+
* its model, which is the signing name for every service here except Cloud
|
|
73
|
+
* Control (`cloudcontrolapi` signs, `CloudControl` is the id).
|
|
74
|
+
*/
|
|
75
|
+
const ENV_SERVICE_ID = { cloudcontrolapi: "cloudcontrol" };
|
|
76
|
+
/** The name of the service-specific endpoint variable the AWS SDK reads for `service`. */
|
|
77
|
+
export function serviceEndpointEnvVar(service) {
|
|
78
|
+
const id = ENV_SERVICE_ID[service] ?? service;
|
|
79
|
+
return `AWS_ENDPOINT_URL_${id.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}`;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The one rule for what an endpoint override is (#1694): the `endpoint` option
|
|
83
|
+
* when given, else the service-specific `AWS_ENDPOINT_URL_<SERVICE>`, else the
|
|
84
|
+
* ambient `AWS_ENDPOINT_URL` — the same precedence the AWS SDK applies. The
|
|
85
|
+
* result is the target the request goes to and, through {@link requestHeaders},
|
|
86
|
+
* the fact that decides whether it is signed. Returns `undefined` for real AWS.
|
|
87
|
+
*/
|
|
88
|
+
export function resolveEndpointOverride(service, endpoint, env = process.env) {
|
|
89
|
+
return endpoint || env[serviceEndpointEnvVar(service)] || env.AWS_ENDPOINT_URL || undefined;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* `options` with its endpoint settled by {@link resolveEndpointOverride}, so
|
|
93
|
+
* the URL builder and the signing decision read the same answer.
|
|
94
|
+
*/
|
|
95
|
+
export function withEndpointOverride(service, options) {
|
|
96
|
+
const endpoint = resolveEndpointOverride(service, options.endpoint, options.env ?? process.env);
|
|
97
|
+
return endpoint ? { ...options, endpoint } : options;
|
|
98
|
+
}
|
|
99
|
+
/** Service host for `service`, honouring an endpoint override. */
|
|
100
|
+
export function serviceUrl(service, endpoint, region = DEFAULT_REGION) {
|
|
101
|
+
return `${(endpoint ?? `https://${service}.${region}.amazonaws.com`).replace(/\/$/, "")}/`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* How the request says which region it is for.
|
|
105
|
+
*
|
|
106
|
+
* Against real AWS the region is the hostname, which is why `serviceUrl` takes
|
|
107
|
+
* it. Against an endpoint override there is only one host for every region, so
|
|
108
|
+
* the hostname carries nothing and the region has to travel in the request —
|
|
109
|
+
* and every emulator reads it where a real SDK puts it, in the credential scope
|
|
110
|
+
* of the `Authorization` header.
|
|
111
|
+
*
|
|
112
|
+
* Without this, a stack observed with `region: "us-west-1"` was read against
|
|
113
|
+
* whatever region the emulator defaults to. The result is not an error: the
|
|
114
|
+
* stack genuinely does not exist in us-east-1, so `describeResources` returned
|
|
115
|
+
* an empty observation and the snapshot recorded the region as holding nothing.
|
|
116
|
+
* A three-region estate snapshotted as one region and nothing said so.
|
|
117
|
+
*
|
|
118
|
+
* This is NOT SigV4. The signature is a placeholder and real AWS rejects it. It
|
|
119
|
+
* is what an unsigned request still has to carry so an emulator learns the
|
|
120
|
+
* region, and it is only ever sent when no credentials resolved — the moment
|
|
121
|
+
* they do, {@link requestHeaders} sends a real signature instead.
|
|
122
|
+
*/
|
|
123
|
+
function regionScope(service, region, env) {
|
|
124
|
+
if (!region)
|
|
125
|
+
return {};
|
|
126
|
+
const day = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
127
|
+
const key = env.AWS_ACCESS_KEY_ID || "chant";
|
|
128
|
+
return {
|
|
129
|
+
authorization: `AWS4-HMAC-SHA256 Credential=${key}/${day}/${region}/${service}/aws4_request, ` +
|
|
130
|
+
"SignedHeaders=host, Signature=unsigned",
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The headers one request goes out with — signed when there is something to
|
|
135
|
+
* sign with and the target is real AWS, scope-only otherwise.
|
|
136
|
+
*
|
|
137
|
+
* Signing needs a region even when the caller named none, because the scope
|
|
138
|
+
* string has a slot for one; it borrows the same `us-east-1` default that
|
|
139
|
+
* {@link serviceUrl} already used to build the host, so the signature agrees
|
|
140
|
+
* with the endpoint it is sent to.
|
|
141
|
+
*
|
|
142
|
+
* Exported because this decision — sign, or carry the scope and no signature —
|
|
143
|
+
* belongs to the lexicon's read transport rather than to any one API on it.
|
|
144
|
+
* `agentcore/trace-fetch.ts` reads `bedrock-agentcore` through the same seam,
|
|
145
|
+
* and a second copy of this would be a second place for the emulator carve-out
|
|
146
|
+
* to drift.
|
|
147
|
+
*
|
|
148
|
+
* Callers pass options already settled by {@link withEndpointOverride}, so an
|
|
149
|
+
* override the environment named is skipped exactly like one the option did.
|
|
150
|
+
*/
|
|
151
|
+
export function requestHeaders(service, url, body, base, options) {
|
|
152
|
+
const env = options.env ?? process.env;
|
|
153
|
+
const credentials = resolveCredentials(options.credentials, env);
|
|
154
|
+
const signable = credentials && (!options.endpoint || options.signEndpointOverride === true);
|
|
155
|
+
if (!signable)
|
|
156
|
+
return { ...base, ...regionScope(service, options.region, env) };
|
|
157
|
+
return signRequest({
|
|
158
|
+
method: "POST",
|
|
159
|
+
url,
|
|
160
|
+
headers: base,
|
|
161
|
+
body,
|
|
162
|
+
service,
|
|
163
|
+
region: options.region ?? DEFAULT_REGION,
|
|
164
|
+
credentials,
|
|
165
|
+
...(options.now ? { now: options.now } : {}),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* `options` with literal credentials from the AWS CLI's credential chain
|
|
170
|
+
* (#3958), when the caller injected none and the request will be signed.
|
|
171
|
+
*
|
|
172
|
+
* Every request function awaits this after {@link withEndpointOverride} and
|
|
173
|
+
* before {@link requestHeaders}, whose seam is synchronous. The chain is not
|
|
174
|
+
* walked against an endpoint override that is not signed: an emulator read
|
|
175
|
+
* should not start an SSO refresh or a `credential_process`, the same rule
|
|
176
|
+
* whoami follows. When nothing resolves the options come back unchanged and
|
|
177
|
+
* the request goes out unsigned, as it did before.
|
|
178
|
+
*
|
|
179
|
+
* An injected `env` without `HOME`, `USERPROFILE`, `AWS_CONFIG_FILE` or
|
|
180
|
+
* `AWS_SHARED_CREDENTIALS_FILE` names no shared files, so only its keys are
|
|
181
|
+
* read; the process's own `~/.aws` is not consulted behind it.
|
|
182
|
+
*/
|
|
183
|
+
export async function withChainCredentials(options) {
|
|
184
|
+
if (options.credentials)
|
|
185
|
+
return options;
|
|
186
|
+
if (options.endpoint && options.signEndpointOverride !== true)
|
|
187
|
+
return options;
|
|
188
|
+
const env = options.env ?? process.env;
|
|
189
|
+
const home = env.HOME || env.USERPROFILE;
|
|
190
|
+
if (options.env && options.env !== process.env && !home && !env.AWS_CONFIG_FILE && !env.AWS_SHARED_CREDENTIALS_FILE) {
|
|
191
|
+
return options;
|
|
192
|
+
}
|
|
193
|
+
const credentials = await transportCredentials({
|
|
194
|
+
env,
|
|
195
|
+
home: home || homedir(),
|
|
196
|
+
sts: { ...(options.http ? { http: options.http } : {}), env },
|
|
197
|
+
});
|
|
198
|
+
return credentials ? { ...options, credentials } : options;
|
|
199
|
+
}
|
|
200
|
+
/* ── CloudFormation Query ─────────────────────────────────────────────────── */
|
|
201
|
+
/**
|
|
202
|
+
* The `<Tag>text</Tag>` pairs of one XML fragment, as a flat record. Repeated
|
|
203
|
+
* tags keep the first occurrence, which is what a `<member>` body wants —
|
|
204
|
+
* nested lists inside a member are not modelled, because nothing the read path
|
|
205
|
+
* needs from `DescribeStackResources` / `DescribeStacks` is nested that deep.
|
|
206
|
+
*/
|
|
207
|
+
export function xmlLeaves(fragment) {
|
|
208
|
+
const out = {};
|
|
209
|
+
for (const m of fragment.matchAll(/<([A-Za-z0-9]+)>([^<]*)<\/\1>/g)) {
|
|
210
|
+
const [, tag, value] = m;
|
|
211
|
+
if (tag && !(tag in out))
|
|
212
|
+
out[tag] = decodeXmlEntities(value ?? "");
|
|
213
|
+
}
|
|
214
|
+
return out;
|
|
215
|
+
}
|
|
216
|
+
/** The five predefined XML entities. Query responses carry them in ARNs and policy text. */
|
|
217
|
+
function decodeXmlEntities(value) {
|
|
218
|
+
return value
|
|
219
|
+
.replace(/</g, "<")
|
|
220
|
+
.replace(/>/g, ">")
|
|
221
|
+
.replace(/"/g, '"')
|
|
222
|
+
.replace(/'/g, "'")
|
|
223
|
+
.replace(/&/g, "&");
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Every `<member>…</member>` under `listTag`, each flattened by
|
|
227
|
+
* {@link xmlLeaves}. The Query protocol renders a list as repeated `<member>`
|
|
228
|
+
* elements, and `xmlField` in the applier deliberately does not handle them —
|
|
229
|
+
* it was written for scalar status fields.
|
|
230
|
+
*/
|
|
231
|
+
export function xmlMembers(xml, listTag) {
|
|
232
|
+
const list = xml.match(new RegExp(`<${listTag}>([\\s\\S]*?)</${listTag}>`))?.[1];
|
|
233
|
+
if (!list)
|
|
234
|
+
return [];
|
|
235
|
+
return [...list.matchAll(/<member>([\s\S]*?)<\/member>/g)].map((m) => xmlLeaves(m[1] ?? ""));
|
|
236
|
+
}
|
|
237
|
+
/** `<Error><Code>…</Code><Message>…</Message></Error>`, when the response carries one. */
|
|
238
|
+
export function xmlError(xml) {
|
|
239
|
+
if (!/<Error>/.test(xml))
|
|
240
|
+
return undefined;
|
|
241
|
+
const leaves = xmlLeaves(xml.match(/<Error>([\s\S]*?)<\/Error>/)?.[1] ?? "");
|
|
242
|
+
return { code: leaves.Code, message: leaves.Message };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* One CloudFormation Query call. Returns the raw XML; throws
|
|
246
|
+
* {@link AwsReadError} for a non-2xx or an `<Error>` body, so a caller
|
|
247
|
+
* classifies a typed failure instead of matching on stderr.
|
|
248
|
+
*/
|
|
249
|
+
export async function cfnQuery(action, params, options = {}) {
|
|
250
|
+
options = await withChainCredentials(withEndpointOverride("cloudformation", options));
|
|
251
|
+
const http = options.http ?? defaultHttp;
|
|
252
|
+
const url = serviceUrl("cloudformation", options.endpoint, options.region);
|
|
253
|
+
const body = new URLSearchParams({ Action: action, Version: CFN_API_VERSION, ...params }).toString();
|
|
254
|
+
const res = await http(url, {
|
|
255
|
+
headers: requestHeaders("cloudformation", url, body, { "content-type": "application/x-www-form-urlencoded" }, options),
|
|
256
|
+
body,
|
|
257
|
+
}, options.signal);
|
|
258
|
+
const err = xmlError(res.text);
|
|
259
|
+
if (err || res.status >= 400) {
|
|
260
|
+
throw new AwsReadError(err?.message ?? `${action} failed with HTTP ${res.status}`, res.status, err?.code);
|
|
261
|
+
}
|
|
262
|
+
return res.text;
|
|
263
|
+
}
|
|
264
|
+
/** `DescribeStackResources` for one stack, mapped off the Query XML. */
|
|
265
|
+
export async function describeStackResources(stackName, options = {}) {
|
|
266
|
+
const xml = await cfnQuery("DescribeStackResources", { StackName: stackName }, options);
|
|
267
|
+
return xmlMembers(xml, "StackResources").map((m) => ({
|
|
268
|
+
logicalId: m.LogicalResourceId ?? "",
|
|
269
|
+
type: m.ResourceType ?? "",
|
|
270
|
+
...(m.PhysicalResourceId ? { physicalId: m.PhysicalResourceId } : {}),
|
|
271
|
+
...(m.ResourceStatus ? { status: m.ResourceStatus } : {}),
|
|
272
|
+
...(m.Timestamp ? { timestamp: m.Timestamp } : {}),
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* `DescribeStacks` for one stack, outputs and tags off the same response. The
|
|
277
|
+
* two ride together because they come from one call: reading the ownership
|
|
278
|
+
* marker on the observation path (#1998) costs no extra round trip.
|
|
279
|
+
*/
|
|
280
|
+
export async function describeStackDetail(stackName, options = {}) {
|
|
281
|
+
const xml = await cfnQuery("DescribeStacks", { StackName: stackName }, options);
|
|
282
|
+
const outputs = {};
|
|
283
|
+
for (const m of xmlMembers(xml, "Outputs")) {
|
|
284
|
+
if (m.OutputKey)
|
|
285
|
+
outputs[m.OutputKey] = m.OutputValue ?? "";
|
|
286
|
+
}
|
|
287
|
+
const tags = {};
|
|
288
|
+
for (const m of xmlMembers(xml, "Tags")) {
|
|
289
|
+
if (m.Key)
|
|
290
|
+
tags[m.Key] = m.Value ?? "";
|
|
291
|
+
}
|
|
292
|
+
return { outputs, tags };
|
|
293
|
+
}
|
|
294
|
+
/** `DescribeStacks` outputs for one stack, as `key → value`. */
|
|
295
|
+
export async function describeStackOutputs(stackName, options = {}) {
|
|
296
|
+
return (await describeStackDetail(stackName, options)).outputs;
|
|
297
|
+
}
|
|
298
|
+
/* ── STS ──────────────────────────────────────────────────────────────────── */
|
|
299
|
+
const STS_API_VERSION = "2011-06-15";
|
|
300
|
+
/**
|
|
301
|
+
* `sts:GetCallerIdentity` — who these credentials are, per the service itself
|
|
302
|
+
* (#1982). Query protocol like CloudFormation, so it rides the same transport,
|
|
303
|
+
* the same endpoint-override rule and the same signing decision as every other
|
|
304
|
+
* read, which is what keeps `chant lifecycle whoami` and `describeResources`
|
|
305
|
+
* from resolving different targets.
|
|
306
|
+
*
|
|
307
|
+
* The response carries an ARN, an account and a `UserId`. Only the first two
|
|
308
|
+
* are returned: `UserId` adds nothing a principal ARN does not already say,
|
|
309
|
+
* and the narrower the surface, the fewer ways a credential reaches a report.
|
|
310
|
+
*/
|
|
311
|
+
export async function getCallerIdentity(options = {}) {
|
|
312
|
+
options = await withChainCredentials(withEndpointOverride("sts", options));
|
|
313
|
+
const http = options.http ?? defaultHttp;
|
|
314
|
+
const url = serviceUrl("sts", options.endpoint, options.region);
|
|
315
|
+
const body = new URLSearchParams({ Action: "GetCallerIdentity", Version: STS_API_VERSION }).toString();
|
|
316
|
+
const res = await http(url, {
|
|
317
|
+
headers: requestHeaders("sts", url, body, { "content-type": "application/x-www-form-urlencoded" }, options),
|
|
318
|
+
body,
|
|
319
|
+
}, options.signal);
|
|
320
|
+
const err = xmlError(res.text);
|
|
321
|
+
if (err || res.status >= 400) {
|
|
322
|
+
throw new AwsReadError(err?.message ?? `GetCallerIdentity failed with HTTP ${res.status}`, res.status, err?.code);
|
|
323
|
+
}
|
|
324
|
+
const leaves = xmlLeaves(res.text);
|
|
325
|
+
return { arn: leaves.Arn ?? "", account: leaves.Account ?? "" };
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* `sts:AssumeRole` — the call behind a shared-config profile with `role_arn`
|
|
329
|
+
* (#3954). Signed with the source credentials the caller passes in
|
|
330
|
+
* `options.credentials`, on the same Query transport as
|
|
331
|
+
* {@link getCallerIdentity}. The response is credential material, so it goes
|
|
332
|
+
* back to the caller and never into an error message.
|
|
333
|
+
*/
|
|
334
|
+
export async function assumeRole(params, options = {}) {
|
|
335
|
+
options = await withChainCredentials(withEndpointOverride("sts", options));
|
|
336
|
+
const http = options.http ?? defaultHttp;
|
|
337
|
+
const url = serviceUrl("sts", options.endpoint, options.region);
|
|
338
|
+
const body = new URLSearchParams({
|
|
339
|
+
Action: "AssumeRole",
|
|
340
|
+
Version: STS_API_VERSION,
|
|
341
|
+
RoleArn: params.roleArn,
|
|
342
|
+
RoleSessionName: params.sessionName,
|
|
343
|
+
...(params.externalId ? { ExternalId: params.externalId } : {}),
|
|
344
|
+
...(params.durationSeconds ? { DurationSeconds: String(params.durationSeconds) } : {}),
|
|
345
|
+
}).toString();
|
|
346
|
+
const res = await http(url, {
|
|
347
|
+
headers: requestHeaders("sts", url, body, { "content-type": "application/x-www-form-urlencoded" }, options),
|
|
348
|
+
body,
|
|
349
|
+
}, options.signal);
|
|
350
|
+
const err = xmlError(res.text);
|
|
351
|
+
if (err || res.status >= 400) {
|
|
352
|
+
throw new AwsReadError(err?.message ?? `AssumeRole failed with HTTP ${res.status}`, res.status, err?.code);
|
|
353
|
+
}
|
|
354
|
+
const leaves = xmlLeaves(res.text.match(/<Credentials>([\s\S]*?)<\/Credentials>/)?.[1] ?? "");
|
|
355
|
+
if (!leaves.AccessKeyId || !leaves.SecretAccessKey || !leaves.SessionToken) {
|
|
356
|
+
throw new AwsReadError("AssumeRole answered without credentials", res.status);
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
accessKeyId: leaves.AccessKeyId,
|
|
360
|
+
secretAccessKey: leaves.SecretAccessKey,
|
|
361
|
+
sessionToken: leaves.SessionToken,
|
|
362
|
+
...(leaves.Expiration ? { expiration: leaves.Expiration } : {}),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* One Cloud Control call (AWS JSON 1.0). Throws {@link AwsReadError} carrying
|
|
367
|
+
* the service's `__type` so `UnsupportedOperation` — what Floci answers for
|
|
368
|
+
* `GetResource` — stays distinguishable from a credential or a genuine miss.
|
|
369
|
+
*/
|
|
370
|
+
async function cloudControl(operation, payload, options = {}) {
|
|
371
|
+
options = await withChainCredentials(withEndpointOverride("cloudcontrolapi", options));
|
|
372
|
+
const http = options.http ?? defaultHttp;
|
|
373
|
+
const url = serviceUrl("cloudcontrolapi", options.endpoint, options.region);
|
|
374
|
+
const payloadJson = JSON.stringify(payload);
|
|
375
|
+
const res = await http(url, {
|
|
376
|
+
headers: requestHeaders("cloudcontrolapi", url, payloadJson, {
|
|
377
|
+
"content-type": "application/x-amz-json-1.0",
|
|
378
|
+
"x-amz-target": `${CLOUD_CONTROL_TARGET_PREFIX}.${operation}`,
|
|
379
|
+
}, options),
|
|
380
|
+
body: payloadJson,
|
|
381
|
+
}, options.signal);
|
|
382
|
+
let parsed;
|
|
383
|
+
try {
|
|
384
|
+
parsed = JSON.parse(res.text);
|
|
385
|
+
}
|
|
386
|
+
catch {
|
|
387
|
+
throw new AwsReadError(`unparseable ${operation} response`, res.status);
|
|
388
|
+
}
|
|
389
|
+
const body = isRecord(parsed) ? parsed : {};
|
|
390
|
+
const type = typeof body.__type === "string" ? body.__type.split("#").pop() : undefined;
|
|
391
|
+
if (type || res.status >= 400) {
|
|
392
|
+
const message = typeof body.message === "string" ? body.message : `${operation} failed with HTTP ${res.status}`;
|
|
393
|
+
throw new AwsReadError(message, res.status, type);
|
|
394
|
+
}
|
|
395
|
+
return body;
|
|
396
|
+
}
|
|
397
|
+
function isRecord(value) {
|
|
398
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Cloud Control returns a resource model as a JSON *string* inside the
|
|
402
|
+
* envelope, so every description unwraps twice. Returns null when either level
|
|
403
|
+
* does not parse to an object — an unparseable body is a failed read, not an
|
|
404
|
+
* empty resource.
|
|
405
|
+
*/
|
|
406
|
+
export function parseResourceDescription(raw) {
|
|
407
|
+
if (!isRecord(raw))
|
|
408
|
+
return null;
|
|
409
|
+
const properties = typeof raw.Properties === "string" ? safeParseObject(raw.Properties) : undefined;
|
|
410
|
+
if (!properties)
|
|
411
|
+
return null;
|
|
412
|
+
return {
|
|
413
|
+
identifier: typeof raw.Identifier === "string" ? raw.Identifier : "",
|
|
414
|
+
properties,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
function safeParseObject(text) {
|
|
418
|
+
try {
|
|
419
|
+
const parsed = JSON.parse(text);
|
|
420
|
+
return isRecord(parsed) ? parsed : null;
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/** `GetResource` — the full live model for one identifier. */
|
|
427
|
+
export async function getResource(typeName, identifier, options = {}) {
|
|
428
|
+
const body = await cloudControl("GetResource", { TypeName: typeName, Identifier: identifier }, options);
|
|
429
|
+
return parseResourceDescription(body.ResourceDescription);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* `ListResources` — every live resource of one type, paginated to exhaustion.
|
|
433
|
+
*
|
|
434
|
+
* `resourceModel` is Cloud Control's `ResourceModel`: the scope a child-typed
|
|
435
|
+
* listing requires (`{ RoleName }` for `AWS::IAM::RolePolicy`,
|
|
436
|
+
* `{ TopicArn }` for `AWS::SNS::Subscription`). The API takes it as a JSON
|
|
437
|
+
* *string*, the same double encoding `GetResource` answers with; this takes
|
|
438
|
+
* the object and encodes it so no caller repeats that detail.
|
|
439
|
+
*/
|
|
440
|
+
export async function listResources(typeName, options = {}, resourceModel) {
|
|
441
|
+
const out = [];
|
|
442
|
+
let nextToken;
|
|
443
|
+
do {
|
|
444
|
+
const body = await cloudControl("ListResources", {
|
|
445
|
+
TypeName: typeName,
|
|
446
|
+
...(resourceModel ? { ResourceModel: JSON.stringify(resourceModel) } : {}),
|
|
447
|
+
...(nextToken ? { NextToken: nextToken } : {}),
|
|
448
|
+
}, options);
|
|
449
|
+
const descriptions = Array.isArray(body.ResourceDescriptions) ? body.ResourceDescriptions : [];
|
|
450
|
+
for (const d of descriptions) {
|
|
451
|
+
const parsed = parseResourceDescription(d);
|
|
452
|
+
if (parsed)
|
|
453
|
+
out.push(parsed);
|
|
454
|
+
}
|
|
455
|
+
nextToken = typeof body.NextToken === "string" && body.NextToken.length > 0 ? body.NextToken : undefined;
|
|
456
|
+
} while (nextToken);
|
|
457
|
+
return out;
|
|
458
|
+
}
|
package/dist/api/sigv4.d.ts
CHANGED
|
@@ -25,10 +25,10 @@ export type AwsCredentialSource = AwsCredentials | AwsCredentialResolver;
|
|
|
25
25
|
* environment — a key id with no secret — is absent rather than a signature
|
|
26
26
|
* that cannot verify.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
* credential
|
|
30
|
-
*
|
|
31
|
-
*
|
|
28
|
+
* The shared profile files are resolved asynchronously by
|
|
29
|
+
* `./credential-chain.ts`, and the read transport passes its answer in as
|
|
30
|
+
* literal credentials (#3958), so this function stays synchronous. Not
|
|
31
|
+
* implemented anywhere: IMDS and the container credential endpoints.
|
|
32
32
|
*/
|
|
33
33
|
export declare function resolveCredentials(source?: AwsCredentialSource, env?: Record<string, string | undefined>): AwsCredentials | undefined;
|
|
34
34
|
/** One request to sign. `headers` are the caller's; the signer adds its own. */
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Signature Version 4, for the shared read transport (#1686).
|
|
3
|
+
*
|
|
4
|
+
* Two modules asked for this by name before it existed: `./read-client.ts` and
|
|
5
|
+
* cedar's `lexicons/cedar/src/avp/client.ts` both send a placeholder
|
|
6
|
+
* `Signature=unsigned` `Authorization` header that carries a credential scope
|
|
7
|
+
* and nothing else, and both say in prose that the real thing belongs here
|
|
8
|
+
* once rather than twice. Nothing else in the repo signs an AWS request — the
|
|
9
|
+
* appliers (`op/activities/aws-apply.ts`) are unsigned too, which is why the
|
|
10
|
+
* native paths have been emulator-scoped.
|
|
11
|
+
*
|
|
12
|
+
* ## No dependency
|
|
13
|
+
*
|
|
14
|
+
* SigV4 is four HMACs and two SHA-256s. `node:crypto` has both, so signing
|
|
15
|
+
* costs nothing in the dependency tree — which matters here, because the whole
|
|
16
|
+
* reason these transports are hand-written is to keep `@aws-sdk/*` and its
|
|
17
|
+
* thirty-odd transitive packages out of a lexicon.
|
|
18
|
+
*
|
|
19
|
+
* ## What is signed, and what is not
|
|
20
|
+
*
|
|
21
|
+
* Header signing only. Query-string (presigned-URL) signing has no caller: the
|
|
22
|
+
* read paths POST to a service endpoint, they do not hand out URLs.
|
|
23
|
+
*
|
|
24
|
+
* `host` is signed but never emitted. `fetch` computes `Host` from the URL and
|
|
25
|
+
* forbids overriding it, so the signer derives the same value from the URL it
|
|
26
|
+
* was given. A transport that rewrites the URL underneath the signer — a proxy
|
|
27
|
+
* that keeps the original `Host`, say — would invalidate the signature; the
|
|
28
|
+
* injectable-HTTP seam is for tests and emulators, not for URL rewriting.
|
|
29
|
+
*/
|
|
30
|
+
import { createHash, createHmac } from "node:crypto";
|
|
31
|
+
const ALGORITHM = "AWS4-HMAC-SHA256";
|
|
32
|
+
const TERMINATOR = "aws4_request";
|
|
33
|
+
/** SHA-256 of the empty string — the payload hash of every bodyless request. */
|
|
34
|
+
export const EMPTY_PAYLOAD_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
|
35
|
+
/**
|
|
36
|
+
* Headers that must not be signed even when a caller sets them: `authorization`
|
|
37
|
+
* is the output, and the others are rewritten in transit by proxies and agents,
|
|
38
|
+
* so signing them produces intermittent 403s rather than security.
|
|
39
|
+
*/
|
|
40
|
+
const UNSIGNABLE = new Set(["authorization", "connection", "expect", "user-agent", "x-amzn-trace-id"]);
|
|
41
|
+
/**
|
|
42
|
+
* Credentials for a request: explicit → environment → absent.
|
|
43
|
+
*
|
|
44
|
+
* A resolver function is authoritative — if one is injected and it declines,
|
|
45
|
+
* the environment is not consulted behind its back, because the point of
|
|
46
|
+
* injecting one is to control the answer. Literal credentials are likewise
|
|
47
|
+
* final. Only the no-source case falls through to `AWS_ACCESS_KEY_ID` /
|
|
48
|
+
* `AWS_SECRET_ACCESS_KEY` (plus `AWS_SESSION_TOKEN` when set), and a half-set
|
|
49
|
+
* environment — a key id with no secret — is absent rather than a signature
|
|
50
|
+
* that cannot verify.
|
|
51
|
+
*
|
|
52
|
+
* The shared profile files are resolved asynchronously by
|
|
53
|
+
* `./credential-chain.ts`, and the read transport passes its answer in as
|
|
54
|
+
* literal credentials (#3958), so this function stays synchronous. Not
|
|
55
|
+
* implemented anywhere: IMDS and the container credential endpoints.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveCredentials(source, env = process.env) {
|
|
58
|
+
if (typeof source === "function")
|
|
59
|
+
return source();
|
|
60
|
+
if (source)
|
|
61
|
+
return source;
|
|
62
|
+
const accessKeyId = env.AWS_ACCESS_KEY_ID;
|
|
63
|
+
const secretAccessKey = env.AWS_SECRET_ACCESS_KEY;
|
|
64
|
+
if (!accessKeyId || !secretAccessKey)
|
|
65
|
+
return undefined;
|
|
66
|
+
return {
|
|
67
|
+
accessKeyId,
|
|
68
|
+
secretAccessKey,
|
|
69
|
+
...(env.AWS_SESSION_TOKEN ? { sessionToken: env.AWS_SESSION_TOKEN } : {}),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** `YYYYMMDDTHHMMSSZ` — the `X-Amz-Date` format, which is ISO-8601 basic. */
|
|
73
|
+
export function amzDate(date) {
|
|
74
|
+
return date.toISOString().replace(/[:-]|\.\d{3}/g, "");
|
|
75
|
+
}
|
|
76
|
+
/** Lowercase hex SHA-256. */
|
|
77
|
+
export function sha256Hex(payload) {
|
|
78
|
+
return createHash("sha256").update(payload, "utf8").digest("hex");
|
|
79
|
+
}
|
|
80
|
+
function hmac(key, data) {
|
|
81
|
+
return createHmac("sha256", key).update(data, "utf8").digest();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The signing key: four chained HMACs from the secret, so the key on the wire
|
|
85
|
+
* is scoped to one day, one region and one service rather than being the
|
|
86
|
+
* account secret itself.
|
|
87
|
+
*/
|
|
88
|
+
export function signingKey(secretAccessKey, day, region, service) {
|
|
89
|
+
const dateKey = hmac(`AWS4${secretAccessKey}`, day);
|
|
90
|
+
const regionKey = hmac(dateKey, region);
|
|
91
|
+
const serviceKey = hmac(regionKey, service);
|
|
92
|
+
return hmac(serviceKey, TERMINATOR);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* RFC 3986 percent-encoding. `encodeURIComponent` leaves `!'()*` alone and AWS
|
|
96
|
+
* does not, which is the difference between a signature that verifies and one
|
|
97
|
+
* that does not for any path or parameter containing them.
|
|
98
|
+
*/
|
|
99
|
+
function encodeRfc3986(value) {
|
|
100
|
+
return encodeURIComponent(value).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The canonical path.
|
|
104
|
+
*
|
|
105
|
+
* Every caller of this module POSTs to `/`, so the one place implementations
|
|
106
|
+
* genuinely diverge — S3 signs the path once-encoded, every other service signs
|
|
107
|
+
* it twice-encoded — never arises. Segments are encoded once; a future caller
|
|
108
|
+
* with a real path on a non-S3 service is the moment to revisit that.
|
|
109
|
+
*/
|
|
110
|
+
function canonicalPath(pathname) {
|
|
111
|
+
if (!pathname || pathname === "/")
|
|
112
|
+
return "/";
|
|
113
|
+
return pathname.split("/").map(encodeRfc3986).join("/");
|
|
114
|
+
}
|
|
115
|
+
/** Query parameters sorted by name, then by value, each side encoded. */
|
|
116
|
+
function canonicalQuery(search) {
|
|
117
|
+
const pairs = [];
|
|
118
|
+
search.forEach((value, name) => pairs.push([encodeRfc3986(name), encodeRfc3986(value)]));
|
|
119
|
+
pairs.sort((a, b) => (a[0] === b[0] ? (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0) : a[0] < b[0] ? -1 : 1));
|
|
120
|
+
return pairs.map(([name, value]) => `${name}=${value}`).join("&");
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Header names lowercased, values trimmed with internal whitespace runs
|
|
124
|
+
* collapsed, sorted by name. Returns the canonical block and the `;`-joined
|
|
125
|
+
* signed-header list that has to agree with it exactly.
|
|
126
|
+
*/
|
|
127
|
+
export function canonicalHeaders(headers) {
|
|
128
|
+
const entries = Object.entries(headers)
|
|
129
|
+
.map(([name, value]) => [name.toLowerCase().trim(), value.trim().replace(/\s+/g, " ")])
|
|
130
|
+
.filter(([name]) => !UNSIGNABLE.has(name))
|
|
131
|
+
.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
|
|
132
|
+
return {
|
|
133
|
+
canonical: entries.map(([name, value]) => `${name}:${value}\n`).join(""),
|
|
134
|
+
signed: entries.map(([name]) => name).join(";"),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** The canonical request, verbatim as it is hashed into the string to sign. */
|
|
138
|
+
export function canonicalRequest(method, url, headers, payloadHash) {
|
|
139
|
+
const { canonical: headerBlock, signed } = canonicalHeaders(headers);
|
|
140
|
+
return {
|
|
141
|
+
canonical: [
|
|
142
|
+
method.toUpperCase(),
|
|
143
|
+
canonicalPath(url.pathname),
|
|
144
|
+
canonicalQuery(url.searchParams),
|
|
145
|
+
headerBlock,
|
|
146
|
+
signed,
|
|
147
|
+
payloadHash,
|
|
148
|
+
].join("\n"),
|
|
149
|
+
signed,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/** The string to sign: algorithm, timestamp, scope, hashed canonical request. */
|
|
153
|
+
export function stringToSign(timestamp, scope, canonical) {
|
|
154
|
+
return [ALGORITHM, timestamp, scope, sha256Hex(canonical)].join("\n");
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The caller's headers plus everything SigV4 adds: `x-amz-date`,
|
|
158
|
+
* `x-amz-content-sha256`, `x-amz-security-token` when the credentials are
|
|
159
|
+
* temporary, and the `Authorization` header itself.
|
|
160
|
+
*
|
|
161
|
+
* `host` is signed (AWS requires it) but not returned — see the module header.
|
|
162
|
+
*/
|
|
163
|
+
export function signRequest(request) {
|
|
164
|
+
const url = new URL(request.url);
|
|
165
|
+
const timestamp = amzDate(request.now ?? new Date());
|
|
166
|
+
const day = timestamp.slice(0, 8);
|
|
167
|
+
const payloadHash = request.body.length === 0 ? EMPTY_PAYLOAD_SHA256 : sha256Hex(request.body);
|
|
168
|
+
const signable = {
|
|
169
|
+
...request.headers,
|
|
170
|
+
host: url.host,
|
|
171
|
+
"x-amz-date": timestamp,
|
|
172
|
+
"x-amz-content-sha256": payloadHash,
|
|
173
|
+
...(request.credentials.sessionToken ? { "x-amz-security-token": request.credentials.sessionToken } : {}),
|
|
174
|
+
};
|
|
175
|
+
const { canonical, signed } = canonicalRequest(request.method, url, signable, payloadHash);
|
|
176
|
+
const scope = `${day}/${request.region}/${request.service}/${TERMINATOR}`;
|
|
177
|
+
const key = signingKey(request.credentials.secretAccessKey, day, request.region, request.service);
|
|
178
|
+
const signature = hmac(key, stringToSign(timestamp, scope, canonical)).toString("hex");
|
|
179
|
+
const { host: _host, ...emitted } = signable;
|
|
180
|
+
return {
|
|
181
|
+
...emitted,
|
|
182
|
+
authorization: `${ALGORITHM} Credential=${request.credentials.accessKeyId}/${scope}, ` +
|
|
183
|
+
`SignedHeaders=${signed}, Signature=${signature}`,
|
|
184
|
+
};
|
|
185
|
+
}
|