Skip to content

Commit

Permalink
feat(sdk): remove runtime dependency for AWS account ID retrieval (#319)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jianzs authored Aug 6, 2024
1 parent 35cba9c commit cdf966f
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 69 deletions.
9 changes: 9 additions & 0 deletions .changeset/early-onions-guess.md
Original file line number Diff line number Diff line change
@@ -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.
9 changes: 3 additions & 6 deletions docs/dev_guide/extend-sdk.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> {
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}`;
}
Expand Down
9 changes: 3 additions & 6 deletions docs/dev_guide/extend-sdk.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> {
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}`;
}
Expand Down
4 changes: 2 additions & 2 deletions examples/quickstart-python/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 8 additions & 0 deletions packages/pluto-py/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 2 additions & 4 deletions packages/pluto-py/pluto_client/clients/aws/queue_sns.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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}"
8 changes: 7 additions & 1 deletion packages/pluto-py/pluto_client/clients/aws/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import re
import hashlib
import json
import boto3
import hashlib

RESOURCE_NAME_MAX_LENGTH = 50

Expand All @@ -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
8 changes: 4 additions & 4 deletions packages/pluto-py/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/pluto-py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <zheng.shoujian@outlook.com>"]
license = "Apache-2.0"
Expand All @@ -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"
Expand Down
1 change: 1 addition & 0 deletions packages/pluto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
13 changes: 5 additions & 8 deletions packages/pluto/src/clients/aws/queue.sns.ts
Original file line number Diff line number Diff line change
@@ -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<string>;

private client: SNSClient;

Expand All @@ -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<string> {
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}`;
}
Expand Down
14 changes: 14 additions & 0 deletions packages/pluto/src/clients/aws/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
import { createHash } from "crypto";

const RESOURCE_NAME_MAX_LENGTH = 50;
Expand All @@ -20,3 +21,16 @@ export function genAwsResourceName(...parts: string[]): string {
return (resourceFullId.substring(start, end) + hash).replace(/^-+|-+$/g, "");
}
}

export async function getAwsAccountId(): Promise<string> {
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;
}
Loading

0 comments on commit cdf966f

Please sign in to comment.