refactor: migrate Secrets Manager secrets to SSM Parameter Store (free tier)
This commit is contained in:
@@ -20,8 +20,8 @@
|
|||||||
"OAUTH_START_URL": "https://sptejrymri.execute-api.us-east-1.amazonaws.com/oauth/start",
|
"OAUTH_START_URL": "https://sptejrymri.execute-api.us-east-1.amazonaws.com/oauth/start",
|
||||||
"USERS_TABLE_NAME": "agent-claw-users",
|
"USERS_TABLE_NAME": "agent-claw-users",
|
||||||
"WORKSPACE_BUCKET_NAME": "agent-claw-workspace-495395224548",
|
"WORKSPACE_BUCKET_NAME": "agent-claw-workspace-495395224548",
|
||||||
"TELEGRAM_BOT_TOKEN_SECRET_ARN": "arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/telegram-bot-token-Oq3in3",
|
"TELEGRAM_BOT_TOKEN_SSM_PARAM": "/agent-claw/telegram-bot-token",
|
||||||
"BRAVE_API_KEY_SECRET_ARN": "arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/brave-api-key-uUSgzi",
|
"BRAVE_API_KEY_SSM_PARAM": "/agent-claw/brave-api-key",
|
||||||
"SCHEDULER_LAMBDA_ARN": "arn:aws:lambda:us-east-1:495395224548:function:agent-claw-scheduler"
|
"SCHEDULER_LAMBDA_ARN": "arn:aws:lambda:us-east-1:495395224548:function:agent-claw-scheduler"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ class TelegramAdapter:
|
|||||||
if self._token is None:
|
if self._token is None:
|
||||||
with self._lock:
|
with self._lock:
|
||||||
if self._token is None:
|
if self._token is None:
|
||||||
secret_arn = self._secret_arn or os.environ.get(
|
param_name = self._secret_arn or os.environ.get(
|
||||||
'TELEGRAM_BOT_TOKEN_SECRET_ARN',
|
'TELEGRAM_BOT_TOKEN_SSM_PARAM',
|
||||||
'arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/telegram-bot-token-Oq3in3'
|
'/agent-claw/telegram-bot-token'
|
||||||
)
|
)
|
||||||
sm = boto3.client('secretsmanager')
|
ssm = boto3.client('ssm')
|
||||||
self._token = sm.get_secret_value(
|
self._token = ssm.get_parameter(
|
||||||
SecretId=secret_arn
|
Name=param_name, WithDecryption=True
|
||||||
)['SecretString']
|
)['Parameter']['Value']
|
||||||
return self._token
|
return self._token
|
||||||
|
|
||||||
def _api(self, method: str, data: dict) -> dict:
|
def _api(self, method: str, data: dict) -> dict:
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ def _get_brave_key() -> str:
|
|||||||
if _brave_key is None:
|
if _brave_key is None:
|
||||||
with _brave_lock:
|
with _brave_lock:
|
||||||
if _brave_key is None:
|
if _brave_key is None:
|
||||||
secret_arn = os.environ.get(
|
param_name = os.environ.get(
|
||||||
'BRAVE_API_KEY_SECRET_ARN',
|
'BRAVE_API_KEY_SSM_PARAM',
|
||||||
'arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/brave-api-key-uUSgzi'
|
'/agent-claw/brave-api-key'
|
||||||
)
|
)
|
||||||
sm = boto3.client('secretsmanager')
|
ssm = boto3.client('ssm')
|
||||||
_brave_key = sm.get_secret_value(SecretId=secret_arn)['SecretString']
|
_brave_key = ssm.get_parameter(Name=param_name, WithDecryption=True)['Parameter']['Value']
|
||||||
return _brave_key
|
return _brave_key
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import * as apigatewayv2 from 'aws-cdk-lib/aws-apigatewayv2';
|
|||||||
import * as apigatewayv2integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
import * as apigatewayv2integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
||||||
import * as iam from 'aws-cdk-lib/aws-iam';
|
import * as iam from 'aws-cdk-lib/aws-iam';
|
||||||
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
||||||
|
import * as ssm from 'aws-cdk-lib/aws-ssm';
|
||||||
import * as events from 'aws-cdk-lib/aws-events';
|
import * as events from 'aws-cdk-lib/aws-events';
|
||||||
import * as eventsTargets from 'aws-cdk-lib/aws-events-targets';
|
import * as eventsTargets from 'aws-cdk-lib/aws-events-targets';
|
||||||
import { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
|
import { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
|
||||||
@@ -20,25 +21,33 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
super(scope, id, props);
|
super(scope, id, props);
|
||||||
|
|
||||||
// ── Context parameters ─────────────────────────────────────────────────
|
// ── Context parameters ─────────────────────────────────────────────────
|
||||||
const telegramBotTokenSecretArn = this.node.tryGetContext('telegramBotTokenSecretArn') as string | undefined;
|
const telegramBotTokenParamName = this.node.tryGetContext('telegramBotTokenParamName') as string | undefined;
|
||||||
const braveApiKeySecretArn = this.node.tryGetContext('braveApiKeySecretArn') as string | undefined;
|
const braveApiKeyParamName = this.node.tryGetContext('braveApiKeyParamName') as string | undefined;
|
||||||
|
const googleOAuthClientParamName = this.node.tryGetContext('googleOAuthClientParamName') as string | undefined;
|
||||||
const existingWorkspaceBucketName = this.node.tryGetContext('workspaceBucketName') as string | undefined;
|
const existingWorkspaceBucketName = this.node.tryGetContext('workspaceBucketName') as string | undefined;
|
||||||
const runtime1Arn = this.node.tryGetContext('runtime1Arn') as string | undefined;
|
const runtime1Arn = this.node.tryGetContext('runtime1Arn') as string | undefined;
|
||||||
|
|
||||||
if (!telegramBotTokenSecretArn) {
|
if (!telegramBotTokenParamName) {
|
||||||
throw new Error('Context param required: telegramBotTokenSecretArn');
|
throw new Error('Context param required: telegramBotTokenParamName');
|
||||||
}
|
}
|
||||||
if (!braveApiKeySecretArn) {
|
if (!braveApiKeyParamName) {
|
||||||
throw new Error('Context param required: braveApiKeySecretArn');
|
throw new Error('Context param required: braveApiKeyParamName');
|
||||||
|
}
|
||||||
|
if (!googleOAuthClientParamName) {
|
||||||
|
throw new Error('Context param required: googleOAuthClientParamName');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Secrets (reference existing) ───────────────────────────────────────
|
// ── SSM Parameters (reference existing SecureString params) ────────────
|
||||||
const botTokenSecret = secretsmanager.Secret.fromSecretCompleteArn(
|
const ssmParamArns = [
|
||||||
this, 'TelegramBotToken', telegramBotTokenSecretArn
|
`arn:aws:ssm:${this.region}:${this.account}:parameter${telegramBotTokenParamName}`,
|
||||||
);
|
`arn:aws:ssm:${this.region}:${this.account}:parameter${braveApiKeyParamName}`,
|
||||||
const braveApiKeySecret = secretsmanager.Secret.fromSecretCompleteArn(
|
`arn:aws:ssm:${this.region}:${this.account}:parameter${googleOAuthClientParamName}`,
|
||||||
this, 'BraveApiKey', braveApiKeySecretArn
|
];
|
||||||
);
|
|
||||||
|
const ssmReadPolicy = new iam.PolicyStatement({
|
||||||
|
actions: ['ssm:GetParameter'],
|
||||||
|
resources: ssmParamArns,
|
||||||
|
});
|
||||||
|
|
||||||
// ── S3 workspace bucket ────────────────────────────────────────────────
|
// ── S3 workspace bucket ────────────────────────────────────────────────
|
||||||
const workspaceBucket = existingWorkspaceBucketName
|
const workspaceBucket = existingWorkspaceBucketName
|
||||||
@@ -94,13 +103,13 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
memorySize: 128,
|
memorySize: 128,
|
||||||
environment: {
|
environment: {
|
||||||
MESSAGE_QUEUE_URL: messageQueue.queueUrl,
|
MESSAGE_QUEUE_URL: messageQueue.queueUrl,
|
||||||
TELEGRAM_BOT_TOKEN_SECRET_ARN: telegramBotTokenSecretArn,
|
TELEGRAM_BOT_TOKEN_SSM_PARAM: telegramBotTokenParamName,
|
||||||
TELEGRAM_WEBHOOK_SECRET: '', // set via SSM or direct env after deploy
|
TELEGRAM_WEBHOOK_SECRET: '', // set via SSM or direct env after deploy
|
||||||
ATTACHMENTS_BUCKET_NAME: workspaceBucket.bucketName,
|
ATTACHMENTS_BUCKET_NAME: workspaceBucket.bucketName,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
messageQueue.grantSendMessages(tgIngestFn);
|
messageQueue.grantSendMessages(tgIngestFn);
|
||||||
botTokenSecret.grantRead(tgIngestFn);
|
tgIngestFn.addToRolePolicy(ssmReadPolicy);
|
||||||
workspaceBucket.grantWrite(tgIngestFn);
|
workspaceBucket.grantWrite(tgIngestFn);
|
||||||
|
|
||||||
// ── Lambda: agent-runner ───────────────────────────────────────────────
|
// ── Lambda: agent-runner ───────────────────────────────────────────────
|
||||||
@@ -114,8 +123,8 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
environment: {
|
environment: {
|
||||||
SESSION_TABLE_NAME: sessionTable.tableName,
|
SESSION_TABLE_NAME: sessionTable.tableName,
|
||||||
WORKSPACE_BUCKET_NAME: workspaceBucket.bucketName,
|
WORKSPACE_BUCKET_NAME: workspaceBucket.bucketName,
|
||||||
TELEGRAM_BOT_TOKEN_SECRET_ARN: telegramBotTokenSecretArn,
|
TELEGRAM_BOT_TOKEN_SSM_PARAM: telegramBotTokenParamName,
|
||||||
BRAVE_API_KEY_SECRET_ARN: braveApiKeySecretArn,
|
BRAVE_API_KEY_SSM_PARAM: braveApiKeyParamName,
|
||||||
RUNTIME_1_ARN: runtime1Arn ?? 'PLACEHOLDER_SET_AFTER_RUNTIME_DEPLOY',
|
RUNTIME_1_ARN: runtime1Arn ?? 'PLACEHOLDER_SET_AFTER_RUNTIME_DEPLOY',
|
||||||
AWS_REGION_NAME: 'us-east-1',
|
AWS_REGION_NAME: 'us-east-1',
|
||||||
},
|
},
|
||||||
@@ -125,8 +134,7 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
usersTable.grantReadWriteData(agentRunnerFn);
|
usersTable.grantReadWriteData(agentRunnerFn);
|
||||||
agentRunnerFn.addEnvironment('USERS_TABLE_NAME', usersTable.tableName);
|
agentRunnerFn.addEnvironment('USERS_TABLE_NAME', usersTable.tableName);
|
||||||
workspaceBucket.grantRead(agentRunnerFn);
|
workspaceBucket.grantRead(agentRunnerFn);
|
||||||
botTokenSecret.grantRead(agentRunnerFn);
|
agentRunnerFn.addToRolePolicy(ssmReadPolicy);
|
||||||
braveApiKeySecret.grantRead(agentRunnerFn);
|
|
||||||
messageQueue.grantConsumeMessages(agentRunnerFn);
|
messageQueue.grantConsumeMessages(agentRunnerFn);
|
||||||
|
|
||||||
// AgentCore invoke permission
|
// AgentCore invoke permission
|
||||||
@@ -172,8 +180,7 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
resources: ['*'],
|
resources: ['*'],
|
||||||
}));
|
}));
|
||||||
workspaceBucket.grantRead(runtime1Role);
|
workspaceBucket.grantRead(runtime1Role);
|
||||||
botTokenSecret.grantRead(runtime1Role);
|
runtime1Role.addToPolicy(ssmReadPolicy);
|
||||||
braveApiKeySecret.grantRead(runtime1Role);
|
|
||||||
usersTable.grantReadWriteData(runtime1Role);
|
usersTable.grantReadWriteData(runtime1Role);
|
||||||
// Google secret grants added after workspace_mcp section below
|
// Google secret grants added after workspace_mcp section below
|
||||||
runtime1Role.addToPolicy(new iam.PolicyStatement({
|
runtime1Role.addToPolicy(new iam.PolicyStatement({
|
||||||
@@ -192,15 +199,12 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
// and fed back as context param runtime1Arn.
|
// and fed back as context param runtime1Arn.
|
||||||
|
|
||||||
// ── Google Workspace MCP ──────────────────────────────────────────────
|
// ── Google Workspace MCP ──────────────────────────────────────────────
|
||||||
const googleOAuthClientSecret = secretsmanager.Secret.fromSecretCompleteArn(
|
|
||||||
this, 'GoogleOAuthClient', 'arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/google-oauth-client-subXHl'
|
|
||||||
);
|
|
||||||
|
|
||||||
// workspace-mcp Lambda execution role (import existing — created during initial setup)
|
// workspace-mcp Lambda execution role (import existing — created during initial setup)
|
||||||
const _workspaceMcpRole = iam.Role.fromRoleName(
|
const _workspaceMcpRole = iam.Role.fromRoleName(
|
||||||
this, 'WorkspaceMcpRole', 'agent-claw-workspace-mcp-role'
|
this, 'WorkspaceMcpRole', 'agent-claw-workspace-mcp-role'
|
||||||
);
|
);
|
||||||
googleOAuthClientSecret.grantRead(_workspaceMcpRole);
|
_workspaceMcpRole.addToPrincipalPolicy?.(ssmReadPolicy);
|
||||||
// Grant workspace-mcp role read access to all per-user Google credential secrets
|
// Grant workspace-mcp role read access to all per-user Google credential secrets
|
||||||
(_workspaceMcpRole as iam.Role).addToPrincipalPolicy?.(new iam.PolicyStatement({
|
(_workspaceMcpRole as iam.Role).addToPrincipalPolicy?.(new iam.PolicyStatement({
|
||||||
sid: 'PerUserGoogleCredentialsRead',
|
sid: 'PerUserGoogleCredentialsRead',
|
||||||
@@ -225,8 +229,7 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
conditions: { StringEquals: { 'lambda:FunctionUrlAuthType': 'AWS_IAM' } },
|
conditions: { StringEquals: { 'lambda:FunctionUrlAuthType': 'AWS_IAM' } },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Grant AgentCore execution role read access to Google OAuth client + per-user credentials
|
// Grant AgentCore execution role read access to per-user Google credentials (stays in Secrets Manager)
|
||||||
googleOAuthClientSecret.grantRead(runtime1Role);
|
|
||||||
runtime1Role.addToPolicy(new iam.PolicyStatement({
|
runtime1Role.addToPolicy(new iam.PolicyStatement({
|
||||||
sid: 'PerUserGoogleCredentialsReadRuntime',
|
sid: 'PerUserGoogleCredentialsReadRuntime',
|
||||||
actions: ['secretsmanager:GetSecretValue'],
|
actions: ['secretsmanager:GetSecretValue'],
|
||||||
@@ -250,22 +253,15 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
timeout: cdk.Duration.seconds(30),
|
timeout: cdk.Duration.seconds(30),
|
||||||
memorySize: 128,
|
memorySize: 128,
|
||||||
environment: {
|
environment: {
|
||||||
GOOGLE_OAUTH_CLIENT_SECRET_ARN: googleOAuthClientSecret.secretArn,
|
GOOGLE_OAUTH_CLIENT_SSM_PARAM: googleOAuthClientParamName,
|
||||||
USERS_TABLE_NAME: usersTable.tableName,
|
USERS_TABLE_NAME: usersTable.tableName,
|
||||||
TELEGRAM_BOT_TOKEN_SECRET_ARN: telegramBotTokenSecretArn,
|
TELEGRAM_BOT_TOKEN_SSM_PARAM: telegramBotTokenParamName,
|
||||||
// OAUTH_REDIRECT_URI set after API GW URL is known — injected via addEnvironment below
|
// OAUTH_REDIRECT_URI set after API GW URL is known — injected via addEnvironment below
|
||||||
OAUTH_REDIRECT_URI: 'PLACEHOLDER',
|
OAUTH_REDIRECT_URI: 'PLACEHOLDER',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
googleOAuthClientSecret.grantRead(oauthHandlerFn);
|
oauthHandlerFn.addToRolePolicy(ssmReadPolicy);
|
||||||
botTokenSecret.grantRead(oauthHandlerFn);
|
|
||||||
usersTable.grantReadWriteData(oauthHandlerFn);
|
usersTable.grantReadWriteData(oauthHandlerFn);
|
||||||
// Explicit access to the OAuth client secret (fromSecretNameV2 wildcard may not resolve)
|
|
||||||
oauthHandlerFn.addToRolePolicy(new iam.PolicyStatement({
|
|
||||||
sid: 'GoogleOAuthClientSecretExact',
|
|
||||||
actions: ['secretsmanager:GetSecretValue'],
|
|
||||||
resources: ['arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/google-oauth-client-subXHl'],
|
|
||||||
}));
|
|
||||||
// Grant OAuth handler write access to per-user credential secrets
|
// Grant OAuth handler write access to per-user credential secrets
|
||||||
oauthHandlerFn.addToRolePolicy(new iam.PolicyStatement({
|
oauthHandlerFn.addToRolePolicy(new iam.PolicyStatement({
|
||||||
sid: 'PerUserGoogleCredentialsWrite',
|
sid: 'PerUserGoogleCredentialsWrite',
|
||||||
@@ -344,10 +340,10 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
timeout: cdk.Duration.seconds(30),
|
timeout: cdk.Duration.seconds(30),
|
||||||
memorySize: 128,
|
memorySize: 128,
|
||||||
environment: {
|
environment: {
|
||||||
TELEGRAM_BOT_TOKEN_SECRET_ARN: telegramBotTokenSecretArn,
|
TELEGRAM_BOT_TOKEN_SSM_PARAM: telegramBotTokenParamName,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
botTokenSecret.grantRead(schedulerFn);
|
schedulerFn.addToRolePolicy(ssmReadPolicy);
|
||||||
// Allow EventBridge to invoke the scheduler Lambda
|
// Allow EventBridge to invoke the scheduler Lambda
|
||||||
schedulerFn.addPermission('EventBridgeInvoke', {
|
schedulerFn.addPermission('EventBridgeInvoke', {
|
||||||
principal: new iam.ServicePrincipal('events.amazonaws.com'),
|
principal: new iam.ServicePrincipal('events.amazonaws.com'),
|
||||||
|
|||||||
@@ -163,11 +163,11 @@ def handler(event, context):
|
|||||||
user_profile['status'] = 'active'
|
user_profile['status'] = 'active'
|
||||||
prompt = f"[System: User just registered with name '{name}'. Welcome them warmly and ask how you can help.]"
|
prompt = f"[System: User just registered with name '{name}'. Welcome them warmly and ask how you can help.]"
|
||||||
else:
|
else:
|
||||||
bot_token_secret_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', '')
|
bot_token_secret_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SSM_PARAM', '')
|
||||||
bot_token = ''
|
bot_token = ''
|
||||||
if bot_token_secret_arn:
|
if bot_token_secret_arn:
|
||||||
sm = boto3.client('secretsmanager', region_name='us-east-1')
|
ssm = boto3.client('ssm', region_name='us-east-1')
|
||||||
bot_token = sm.get_secret_value(SecretId=bot_token_secret_arn)['SecretString']
|
bot_token = ssm.get_parameter(Name=bot_token_secret_arn, WithDecryption=True)['Parameter']['Value']
|
||||||
send_telegram_direct(chat_id, bot_token, "Hi! I don't recognize you yet. What's your name?", thread_id=message_thread_id)
|
send_telegram_direct(chat_id, bot_token, "Hi! I don't recognize you yet. What's your name?", thread_id=message_thread_id)
|
||||||
return
|
return
|
||||||
# ── Get or create AgentCore session ──────────────────────────────────
|
# ── Get or create AgentCore session ──────────────────────────────────
|
||||||
@@ -212,7 +212,7 @@ def handler(event, context):
|
|||||||
'type': channel,
|
'type': channel,
|
||||||
'target_id': str(chat_id),
|
'target_id': str(chat_id),
|
||||||
'message_thread_id': message_thread_id,
|
'message_thread_id': message_thread_id,
|
||||||
'bot_token_secret_arn': os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', ''),
|
'bot_token_secret_arn': os.environ.get('TELEGRAM_BOT_TOKEN_SSM_PARAM', ''),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,11 +232,11 @@ def handler(event, context):
|
|||||||
|
|
||||||
# Process streaming response: buffer text chunks and send to Telegram as paragraphs arrive
|
# Process streaming response: buffer text chunks and send to Telegram as paragraphs arrive
|
||||||
bot_token = ''
|
bot_token = ''
|
||||||
bot_token_secret_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', '')
|
bot_token_param = os.environ.get('TELEGRAM_BOT_TOKEN_SSM_PARAM', '')
|
||||||
if bot_token_secret_arn:
|
if bot_token_param:
|
||||||
sm = boto3.client('secretsmanager', region_name='us-east-1')
|
ssm = boto3.client('ssm', region_name='us-east-1')
|
||||||
try:
|
try:
|
||||||
bot_token = sm.get_secret_value(SecretId=bot_token_secret_arn)['SecretString']
|
bot_token = ssm.get_parameter(Name=bot_token_param, WithDecryption=True)['Parameter']['Value']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'[agent-runner] Failed to get bot token: {e}')
|
print(f'[agent-runner] Failed to get bot token: {e}')
|
||||||
|
|
||||||
|
|||||||
@@ -44,9 +44,10 @@ def get_ddb():
|
|||||||
|
|
||||||
|
|
||||||
def get_oauth_client() -> tuple[str, str]:
|
def get_oauth_client() -> tuple[str, str]:
|
||||||
"""Return (client_id, client_secret) from Secrets Manager."""
|
"""Return (client_id, client_secret) from SSM Parameter Store."""
|
||||||
arn = os.environ['GOOGLE_OAUTH_CLIENT_SECRET_ARN']
|
param_name = os.environ['GOOGLE_OAUTH_CLIENT_SSM_PARAM']
|
||||||
secret = json.loads(get_sm().get_secret_value(SecretId=arn)['SecretString'])
|
ssm = boto3.client('ssm', region_name=os.environ.get('AWS_REGION', 'us-east-1'))
|
||||||
|
secret = json.loads(ssm.get_parameter(Name=param_name, WithDecryption=True)['Parameter']['Value'])
|
||||||
return secret['client_id'], secret['client_secret']
|
return secret['client_id'], secret['client_secret']
|
||||||
|
|
||||||
|
|
||||||
@@ -222,10 +223,11 @@ def handle_callback(params: dict) -> dict:
|
|||||||
|
|
||||||
# Best-effort Telegram confirmation
|
# Best-effort Telegram confirmation
|
||||||
try:
|
try:
|
||||||
bot_token_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', '')
|
bot_token_param = os.environ.get('TELEGRAM_BOT_TOKEN_SSM_PARAM', '')
|
||||||
if bot_token_arn and actor_id.startswith('telegram:'):
|
if bot_token_param and actor_id.startswith('telegram:'):
|
||||||
chat_id = actor_id.split(':', 1)[1]
|
chat_id = actor_id.split(':', 1)[1]
|
||||||
bot_token = get_sm().get_secret_value(SecretId=bot_token_arn)['SecretString']
|
ssm = boto3.client('ssm', region_name=os.environ.get('AWS_REGION', 'us-east-1'))
|
||||||
|
bot_token = ssm.get_parameter(Name=bot_token_param, WithDecryption=True)['Parameter']['Value']
|
||||||
tg_text = f'✅ Connected {user_email} as "{label}"'
|
tg_text = f'✅ Connected {user_email} as "{label}"'
|
||||||
tg_payload = json.dumps({'chat_id': chat_id, 'text': tg_text}).encode()
|
tg_payload = json.dumps({'chat_id': chat_id, 'text': tg_text}).encode()
|
||||||
tg_req = urllib.request.Request(
|
tg_req = urllib.request.Request(
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ def handler(event, context):
|
|||||||
rule_name = event['rule_name']
|
rule_name = event['rule_name']
|
||||||
|
|
||||||
# Fetch bot token
|
# Fetch bot token
|
||||||
sm = boto3.client('secretsmanager', region_name='us-east-1')
|
ssm = boto3.client('ssm', region_name='us-east-1')
|
||||||
token = sm.get_secret_value(SecretId=os.environ['TELEGRAM_BOT_TOKEN_SECRET_ARN'])['SecretString']
|
token = ssm.get_parameter(Name=os.environ['TELEGRAM_BOT_TOKEN_SSM_PARAM'], WithDecryption=True)['Parameter']['Value']
|
||||||
|
|
||||||
# Send Telegram message
|
# Send Telegram message
|
||||||
payload = json.dumps({'chat_id': chat_id, 'text': message}).encode()
|
payload = json.dumps({'chat_id': chat_id, 'text': message}).encode()
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ def get_bot_token() -> str:
|
|||||||
if _bot_token is None:
|
if _bot_token is None:
|
||||||
with _token_lock:
|
with _token_lock:
|
||||||
if _bot_token is None:
|
if _bot_token is None:
|
||||||
sm = boto3.client('secretsmanager')
|
ssm = boto3.client('ssm')
|
||||||
_bot_token = sm.get_secret_value(
|
_bot_token = ssm.get_parameter(
|
||||||
SecretId=os.environ['TELEGRAM_BOT_TOKEN_SECRET_ARN']
|
Name=os.environ['TELEGRAM_BOT_TOKEN_SSM_PARAM'],
|
||||||
)['SecretString']
|
WithDecryption=True
|
||||||
|
)['Parameter']['Value']
|
||||||
return _bot_token
|
return _bot_token
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Fetch Google OAuth credentials and client secrets from Secrets Manager.
|
Fetch Google OAuth credentials from SSM (client secret) and Secrets Manager (per-user tokens).
|
||||||
Called by bootstrap before starting workspace-mcp.
|
Called by bootstrap before starting workspace-mcp.
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
@@ -12,10 +12,11 @@ def main():
|
|||||||
sm = boto3.client('secretsmanager', region_name=region)
|
sm = boto3.client('secretsmanager', region_name=region)
|
||||||
|
|
||||||
# Fetch OAuth client credentials (client_id + client_secret)
|
# Fetch OAuth client credentials (client_id + client_secret)
|
||||||
client_secret_arn = os.environ.get('GOOGLE_OAUTH_CLIENT_SECRET_ARN')
|
client_secret_param = os.environ.get('GOOGLE_OAUTH_CLIENT_SSM_PARAM')
|
||||||
if client_secret_arn:
|
if client_secret_param:
|
||||||
try:
|
try:
|
||||||
client_creds = json.loads(sm.get_secret_value(SecretId=client_secret_arn)['SecretString'])
|
ssm = boto3.client('ssm', region_name=region)
|
||||||
|
client_creds = json.loads(ssm.get_parameter(Name=client_secret_param, WithDecryption=True)['Parameter']['Value'])
|
||||||
os.environ['GOOGLE_OAUTH_CLIENT_ID'] = client_creds['client_id']
|
os.environ['GOOGLE_OAUTH_CLIENT_ID'] = client_creds['client_id']
|
||||||
os.environ['GOOGLE_OAUTH_CLIENT_SECRET'] = client_creds['client_secret']
|
os.environ['GOOGLE_OAUTH_CLIENT_SECRET'] = client_creds['client_secret']
|
||||||
print('[fetch_credentials] OAuth client credentials loaded', file=sys.stderr)
|
print('[fetch_credentials] OAuth client credentials loaded', file=sys.stderr)
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ def _setup_shared_environment():
|
|||||||
os.environ.setdefault('HOME', '/tmp')
|
os.environ.setdefault('HOME', '/tmp')
|
||||||
os.environ.setdefault('GOOGLE_WORKSPACE_MCP_CREDENTIALS_DIR', '/tmp/workspace_mcp_credentials')
|
os.environ.setdefault('GOOGLE_WORKSPACE_MCP_CREDENTIALS_DIR', '/tmp/workspace_mcp_credentials')
|
||||||
|
|
||||||
client_arn = os.environ.get('GOOGLE_OAUTH_CLIENT_SECRET_ARN', '')
|
client_param = os.environ.get('GOOGLE_OAUTH_CLIENT_SSM_PARAM', '')
|
||||||
if client_arn:
|
if client_param:
|
||||||
try:
|
try:
|
||||||
sm = boto3.client('secretsmanager', region_name=os.environ.get('AWS_REGION', 'us-east-1'))
|
ssm = boto3.client('ssm', region_name=os.environ.get('AWS_REGION', 'us-east-1'))
|
||||||
client_creds = json.loads(sm.get_secret_value(SecretId=client_arn)['SecretString'])
|
client_creds = json.loads(ssm.get_parameter(Name=client_param, WithDecryption=True)['Parameter']['Value'])
|
||||||
os.environ['GOOGLE_OAUTH_CLIENT_ID'] = client_creds['client_id']
|
os.environ['GOOGLE_OAUTH_CLIENT_ID'] = client_creds['client_id']
|
||||||
os.environ['GOOGLE_OAUTH_CLIENT_SECRET'] = client_creds['client_secret']
|
os.environ['GOOGLE_OAUTH_CLIENT_SECRET'] = client_creds['client_secret']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user