From cdf966f784186f1f2c637cedf17a28b095560ea1 Mon Sep 17 00:00:00 2001 From: Jade Zheng Date: Tue, 6 Aug 2024 20:17:08 +0800 Subject: [PATCH] feat(sdk): remove runtime dependency for AWS account ID retrieval (#319) The previous AWS queue resource type implementation required the `AWS_ACCOUNT_ID` environment variable to be set by the runtime handler. The setting only occurred upon receiving a request, causing a panic if the queue resource type was used globally without the `AWS_ACCOUNT_ID` being set. This commit eliminates the need for runtime setting of `AWS_ACCOUNT_ID` by utilizing the `sts.GetCallerIdentity` API to retrieve the account ID. --- .changeset/early-onions-guess.md | 9 +++ docs/dev_guide/extend-sdk.en.md | 9 +-- docs/dev_guide/extend-sdk.zh-CN.md | 9 +-- examples/quickstart-python/package.json | 4 +- packages/pluto-py/CHANGELOG.md | 8 ++ .../pluto_client/clients/aws/queue_sns.py | 6 +- .../pluto_client/clients/aws/utils.py | 8 +- packages/pluto-py/poetry.lock | 8 +- packages/pluto-py/pyproject.toml | 4 +- packages/pluto/package.json | 1 + packages/pluto/src/clients/aws/queue.sns.ts | 13 ++-- packages/pluto/src/clients/aws/utils.ts | 14 ++++ pnpm-lock.yaml | 75 ++++++++++--------- 13 files changed, 99 insertions(+), 69 deletions(-) create mode 100644 .changeset/early-onions-guess.md diff --git a/.changeset/early-onions-guess.md b/.changeset/early-onions-guess.md new file mode 100644 index 00000000..90351586 --- /dev/null +++ b/.changeset/early-onions-guess.md @@ -0,0 +1,9 @@ +--- +"@plutolang/pluto": patch +--- + +feat(sdk): remove runtime dependency for AWS account ID retrieval + +The previous AWS queue resource type implementation required the `AWS_ACCOUNT_ID` environment variable to be set by the runtime handler. The setting only occurred upon receiving a request, causing a panic if the queue resource type was used globally without the `AWS_ACCOUNT_ID` being set. + +This commit eliminates the need for runtime setting of `AWS_ACCOUNT_ID` by utilizing the `sts.GetCallerIdentity` API to retrieve the account ID. diff --git a/docs/dev_guide/extend-sdk.en.md b/docs/dev_guide/extend-sdk.en.md index d1936b81..4126d00d 100644 --- a/docs/dev_guide/extend-sdk.en.md +++ b/docs/dev_guide/extend-sdk.en.md @@ -193,22 +193,19 @@ export class SNSQueue implements IQueueClient { }; await this.client.send( new PublishCommand({ - TopicArn: this.buildARN(this.topicName), + TopicArn: await this.buildARN(this.topicName), Message: JSON.stringify(evt), }) ); } - private buildARN(topicName: string): string { + private async buildARN(topicName: string): Promise { const region = process.env.AWS_REGION; if (!region) { throw new Error("Missing AWS Region"); } - const accountId = process.env.AWS_ACCOUNT_ID; - if (!accountId) { - throw new Error("Missing AWS Account ID"); - } + const accountId = await getAwsAccountId(); return `arn:aws:sns:${region}:${accountId}:${topicName}`; } diff --git a/docs/dev_guide/extend-sdk.zh-CN.md b/docs/dev_guide/extend-sdk.zh-CN.md index cf31b7ed..d8203a69 100644 --- a/docs/dev_guide/extend-sdk.zh-CN.md +++ b/docs/dev_guide/extend-sdk.zh-CN.md @@ -193,22 +193,19 @@ export class SNSQueue implements IQueueClient { }; await this.client.send( new PublishCommand({ - TopicArn: this.buildARN(this.topicName), + TopicArn: await this.buildARN(this.topicName), Message: JSON.stringify(evt), }) ); } - private buildARN(topicName: string): string { + private async buildARN(topicName: string): Promise { const region = process.env.AWS_REGION; if (!region) { throw new Error("Missing AWS Region"); } - const accountId = process.env.AWS_ACCOUNT_ID; - if (!accountId) { - throw new Error("Missing AWS Account ID"); - } + const accountId = await getAwsAccountId(); return `arn:aws:sns:${region}:${accountId}:${topicName}`; } diff --git a/examples/quickstart-python/package.json b/examples/quickstart-python/package.json index 5d52aa30..a7190262 100644 --- a/examples/quickstart-python/package.json +++ b/examples/quickstart-python/package.json @@ -12,8 +12,8 @@ "devDependencies": { "@types/node": "^20", "typescript": "^5.2.2", - "@plutolang/base": "latest", - "@plutolang/pluto-infra": "latest", + "@plutolang/base": "workspace:*", + "@plutolang/pluto-infra": "workspace:*", "@pulumi/pulumi": "^3.88.0" }, "main": "dist/index.js" diff --git a/packages/pluto-py/CHANGELOG.md b/packages/pluto-py/CHANGELOG.md index 643f1d05..93a8d785 100644 --- a/packages/pluto-py/CHANGELOG.md +++ b/packages/pluto-py/CHANGELOG.md @@ -1,5 +1,13 @@ # pluto-client +## 0.0.19 + +feat: remove runtime dependency for AWS account ID retrieval + +The previous AWS queue resource type implementation required the `AWS_ACCOUNT_ID` environment variable to be set by the runtime handler. The setting only occurred upon receiving a request, causing a panic if the queue resource type was used globally without the `AWS_ACCOUNT_ID` being set. + +This commit eliminates the need for runtime setting of `AWS_ACCOUNT_ID` by utilizing the `sts.GetCallerIdentity` API to retrieve the account ID. + ## 0.0.18 chore: lint and format code diff --git a/packages/pluto-py/pluto_client/clients/aws/queue_sns.py b/packages/pluto-py/pluto_client/clients/aws/queue_sns.py index 44ca4305..8f413fbc 100644 --- a/packages/pluto-py/pluto_client/clients/aws/queue_sns.py +++ b/packages/pluto-py/pluto_client/clients/aws/queue_sns.py @@ -4,7 +4,7 @@ import boto3 from typing import Optional from pluto_base.utils.resource_id import gen_resource_id -from pluto_client.clients.aws.utils import gen_aws_resource_name +from pluto_client.clients.aws.utils import gen_aws_resource_name, get_aws_account_id from ...queue import CloudEvent, IQueueClient, Queue, QueueOptions @@ -26,8 +26,6 @@ def __build_arn(self, topic_name: str) -> str: if not region: raise EnvironmentError("Missing AWS Region") - account_id = os.environ.get("AWS_ACCOUNT_ID") - if not account_id: - raise EnvironmentError("Missing AWS Account ID") + account_id = get_aws_account_id() return f"arn:aws:sns:{region}:{account_id}:{topic_name}" diff --git a/packages/pluto-py/pluto_client/clients/aws/utils.py b/packages/pluto-py/pluto_client/clients/aws/utils.py index 59a71beb..7dd4e7af 100644 --- a/packages/pluto-py/pluto_client/clients/aws/utils.py +++ b/packages/pluto-py/pluto_client/clients/aws/utils.py @@ -1,6 +1,7 @@ import re -import hashlib import json +import boto3 +import hashlib RESOURCE_NAME_MAX_LENGTH = 50 @@ -15,3 +16,8 @@ def gen_aws_resource_name(*parts: str) -> str: start = len(resource_full_id) - (RESOURCE_NAME_MAX_LENGTH - len(hash)) end = len(resource_full_id) return (resource_full_id[start:end] + hash).strip("-") + + +def get_aws_account_id() -> str: + client = boto3.client("sts") # type: ignore + return client.get_caller_identity().get("Account") # type: ignore diff --git a/packages/pluto-py/poetry.lock b/packages/pluto-py/poetry.lock index 943da5f7..b0c46866 100644 --- a/packages/pluto-py/poetry.lock +++ b/packages/pluto-py/poetry.lock @@ -123,13 +123,13 @@ files = [ [[package]] name = "pluto-base" -version = "0.0.5" +version = "0.0.7" description = "The Base Library for Pluto Programming Language." optional = false python-versions = "<4.0,>=3.10" files = [ - {file = "pluto_base-0.0.5-py3-none-any.whl", hash = "sha256:7a6c62a04cb53eff7f8806f8d8c3ab5acdee03a1f899208a4a9285e1da51a942"}, - {file = "pluto_base-0.0.5.tar.gz", hash = "sha256:f5f1cd36d9c8fb9304c3c9abb63b1c4fb71e2997730791e9955235dada5bb979"}, + {file = "pluto_base-0.0.7-py3-none-any.whl", hash = "sha256:5749c7c14461247526f6449a33ffe25572432fe4dbd3785d24f821fd20b3f40b"}, + {file = "pluto_base-0.0.7.tar.gz", hash = "sha256:1301f380035b7072cf71904e88b6bd97658651b0ff77876f1ff153263e5318b8"}, ] [package.dependencies] @@ -176,4 +176,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "00abe309b4899372e3f3ddfca3e399e999a43ed8f52cfb857425dd85c737fc60" +content-hash = "fde6396a504a9d9de1e8a8d00e35da4ccb3177400c8ed33accea6b62c40e7fc9" diff --git a/packages/pluto-py/pyproject.toml b/packages/pluto-py/pyproject.toml index 6be2e31d..9f1445c3 100644 --- a/packages/pluto-py/pyproject.toml +++ b/packages/pluto-py/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "pluto-client" -version = "0.0.18" +version = "0.0.19" description = "The Client Library for Pluto Programming Language." authors = ["Jade Zheng "] license = "Apache-2.0" @@ -25,7 +25,7 @@ Issues = "https://github.com/pluto-lang/pluto/issues" [tool.poetry.dependencies] python = "^3.10" -pluto-base = "^0.0.6" +pluto-base = "^0.0.7" [[tool.poetry.source]] name = "testpypi" diff --git a/packages/pluto/package.json b/packages/pluto/package.json index 2f8fd237..17850626 100644 --- a/packages/pluto/package.json +++ b/packages/pluto/package.json @@ -23,6 +23,7 @@ "@aws-sdk/client-sagemaker-runtime": "^3.614.0", "@aws-sdk/client-secrets-manager": "^3.614.0", "@aws-sdk/client-sns": "^3.614.0", + "@aws-sdk/client-sts": "^3.614.0", "@aws-sdk/lib-dynamodb": "^3.614.0", "@plutolang/base": "workspace:^", "redis": "^4.6.10" diff --git a/packages/pluto/src/clients/aws/queue.sns.ts b/packages/pluto/src/clients/aws/queue.sns.ts index 5fb5c856..d2a224e0 100644 --- a/packages/pluto/src/clients/aws/queue.sns.ts +++ b/packages/pluto/src/clients/aws/queue.sns.ts @@ -1,14 +1,14 @@ import { SNSClient, PublishCommand } from "@aws-sdk/client-sns"; import { genResourceId } from "@plutolang/base/utils"; import { CloudEvent, IQueueClient, Queue, QueueOptions } from "../../queue"; -import { genAwsResourceName } from "./utils"; +import { genAwsResourceName, getAwsAccountId } from "./utils"; /** * Implementation of Queue using AWS SNS. */ export class SNSQueue implements IQueueClient { private readonly id: string; - private readonly topicArn: string; + private readonly topicArn: Promise; private client: SNSClient; @@ -28,22 +28,19 @@ export class SNSQueue implements IQueueClient { }; await this.client.send( new PublishCommand({ - TopicArn: this.topicArn, + TopicArn: await this.topicArn, Message: JSON.stringify(evt), }) ); } - private buildARN(topicName: string): string { + private async buildARN(topicName: string): Promise { const region = process.env.AWS_REGION; if (!region) { throw new Error("Missing AWS Region"); } - const accountId = process.env.AWS_ACCOUNT_ID; - if (!accountId) { - throw new Error("Missing AWS Account ID"); - } + const accountId = await getAwsAccountId(); return `arn:aws:sns:${region}:${accountId}:${topicName}`; } diff --git a/packages/pluto/src/clients/aws/utils.ts b/packages/pluto/src/clients/aws/utils.ts index ff07ce21..9fbeae6f 100644 --- a/packages/pluto/src/clients/aws/utils.ts +++ b/packages/pluto/src/clients/aws/utils.ts @@ -1,3 +1,4 @@ +import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts"; import { createHash } from "crypto"; const RESOURCE_NAME_MAX_LENGTH = 50; @@ -20,3 +21,16 @@ export function genAwsResourceName(...parts: string[]): string { return (resourceFullId.substring(start, end) + hash).replace(/^-+|-+$/g, ""); } } + +export async function getAwsAccountId(): Promise { + const client = new STSClient({}); + + const command = new GetCallerIdentityCommand({}); + const response = await client.send(command); + + const accountId = response.Account; + if (!accountId) { + throw new Error("Missing AWS Account ID"); + } + return accountId; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9242e184..5358eac3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -374,17 +374,17 @@ importers: dependencies: '@plutolang/pluto': specifier: latest - version: 0.4.17 + version: 0.4.18 openai: specifier: ^4.13.0 version: 4.13.0 devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -399,17 +399,17 @@ importers: dependencies: '@plutolang/pluto': specifier: latest - version: 0.4.17 + version: 0.4.18 '@slack/web-api': specifier: ^6.9.0 version: 6.9.0 devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -424,10 +424,10 @@ importers: devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -442,10 +442,10 @@ importers: devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -460,14 +460,14 @@ importers: dependencies: '@plutolang/pluto': specifier: latest - version: 0.4.17 + version: 0.4.18 devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -519,10 +519,10 @@ importers: devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -574,14 +574,14 @@ importers: dependencies: '@plutolang/pluto': specifier: latest - version: 0.4.17 + version: 0.4.18 devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -595,11 +595,11 @@ importers: examples/quickstart-python: devDependencies: '@plutolang/base': - specifier: latest - version: 0.4.9 + specifier: workspace:* + version: link:../../packages/base '@plutolang/pluto-infra': - specifier: latest - version: 0.4.26 + specifier: workspace:* + version: link:../../packages/pluto-infra '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -614,10 +614,10 @@ importers: devDependencies: '@plutolang/base': specifier: latest - version: 0.4.9 + version: 0.4.10 '@plutolang/pluto-infra': specifier: latest - version: 0.4.26 + version: 0.4.27 '@pulumi/pulumi': specifier: ^3.88.0 version: 3.88.0 @@ -720,6 +720,9 @@ importers: '@aws-sdk/client-sns': specifier: ^3.614.0 version: 3.614.0 + '@aws-sdk/client-sts': + specifier: ^3.614.0 + version: 3.614.0 '@aws-sdk/lib-dynamodb': specifier: ^3.614.0 version: 3.614.0(@aws-sdk/client-dynamodb@3.614.0) @@ -2497,14 +2500,14 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@plutolang/base@0.4.9': - resolution: {integrity: sha512-1x5wAZ0dfqe68vVHBBMZpH0XVjy6UFK2huYUrpKntkWZmysflSgsxf7AK756PVzPEh3oILiWxFdEdL6+2jRCug==} + '@plutolang/base@0.4.10': + resolution: {integrity: sha512-r+6BngsJHj58fVoppHkCYFyCMYEyBzIhbDYiOAZMhVVapFtoXi8GLzsLXZTKv7mmNzPw/PwoIPdYOKhU13pRsA==} - '@plutolang/pluto-infra@0.4.26': - resolution: {integrity: sha512-/ZieLfJG1g4YDJluP+876pF8TUkLYZya3I8gMl42T0IQLtjR2CPYcwD3s6MEr+hnz7HrF4hkxF29EKeafBNjag==} + '@plutolang/pluto-infra@0.4.27': + resolution: {integrity: sha512-22uQud0cVGls0HhtyeULki8zlqjm23NcjLQ03G94OCB6z5lLESefYjGvyLTS0K4ocHWE1r5m+snTgDBd0f9QCA==} - '@plutolang/pluto@0.4.17': - resolution: {integrity: sha512-aCFyHbZ+aurUuhSFFo/5fddk8RyA5XHQOFfTZezkq+aA3Q4zb0JQYRsWb0XN9UYoXi/5mAceMYFmN7Jty+/g/w==} + '@plutolang/pluto@0.4.18': + resolution: {integrity: sha512-x8cdRH8cdHJAjUo8N8FA4/norEN7S5GNqNm/jW22ndqKmlz9ORwT7KBkilDN4IntPl4UWhW3rRsAejAD8m/S3w==} '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -9135,7 +9138,7 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@plutolang/base@0.4.9': + '@plutolang/base@0.4.10': dependencies: fs-extra: 11.1.1 js-yaml: 4.1.0 @@ -9144,10 +9147,10 @@ snapshots: transitivePeerDependencies: - encoding - '@plutolang/pluto-infra@0.4.26': + '@plutolang/pluto-infra@0.4.27': dependencies: - '@plutolang/base': 0.4.9 - '@plutolang/pluto': 0.4.17 + '@plutolang/base': 0.4.10 + '@plutolang/pluto': 0.4.18 '@pulumi/alicloud': 3.45.0 '@pulumi/archive': 0.0.2 '@pulumi/aws': 6.34.1 @@ -9167,7 +9170,7 @@ snapshots: - encoding - supports-color - '@plutolang/pluto@0.4.17': + '@plutolang/pluto@0.4.18': dependencies: '@alicloud/credentials': 2.3.0 '@alicloud/fc-open20210406': 2.0.13 @@ -9180,7 +9183,7 @@ snapshots: '@aws-sdk/client-secrets-manager': 3.614.0 '@aws-sdk/client-sns': 3.614.0 '@aws-sdk/lib-dynamodb': 3.614.0(@aws-sdk/client-dynamodb@3.614.0) - '@plutolang/base': 0.4.9 + '@plutolang/base': 0.4.10 redis: 4.6.10 transitivePeerDependencies: - aws-crt