Skip to content

Instantly share code, notes, and snippets.

@junkor-1011
Last active February 14, 2023 16:29
Show Gist options
  • Save junkor-1011/54d2c56d75cd10a53fd343e4feb322d9 to your computer and use it in GitHub Desktop.
Save junkor-1011/54d2c56d75cd10a53fd343e4feb322d9 to your computer and use it in GitHub Desktop.
localstack + s3 presigned url
AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test
AWS_DEFAULT_REGION=ap-northeast-1
USE_LOCALSTACK=true
node_modules
pnpm-lock.yaml
.env
.env.local

localstack + s3 presigned url

#!/usr/bin/env bash
set -eu
# aws-env in this script
# export AWS_ACCESS_KEY_ID=test
# export AWS_SECRET_ACCESS_KEY=test
# export AWS_DEFAULT_REGION=ap-northeast-1
SCRIPT_DIR="$(cd "$(dirname "$0")" || exit; pwd)"
cd "$SCRIPT_DIR" || exit
aws \
--endpoint-url="${LOCALSTACK_ENDPOINT_URL:-http://localhost:4566}" \
cloudformation deploy \
--stack-name "${DEV_STACK_NAME:-sample-stack}" \
--template-file "${SCRIPT_DIR}/clf-template.yaml" \
--no-cli-auto-prompt
AWSTemplateFormatVersion: 2010-09-09
Description: This CloudFormation template to for local development with localstack
Resources:
LocalSoftwareBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: sample-bucket
DBAccessSecrets:
Type: AWS::SecretsManager::Secret
Properties:
Name: 'sample-secret'
Description: Secrets for RDS
SecretString: '{"username":"postgres","password":"!passw0rd", "host": "localhost", "port": 5432, "schema": "app", "db": "appdb"}'
ParamA1:
Type: AWS::SSM::Parameter
Properties:
Description: 'A-1'
Name: '/A/param-1'
Type: String
Value: 'sample-value-A-1'
ParamA2:
Type: AWS::SSM::Parameter
Properties:
Description: 'A-2'
Name: '/A/param-2'
Type: String
Value: 'sample-value-A-2'
ParamB1:
Type: AWS::SSM::Parameter
Properties:
Description: 'B-1'
Name: '/B/param-1'
Type: String
Value: 'sample-value-B-1'
ParamB2:
Type: AWS::SSM::Parameter
Properties:
Description: 'B-2'
Name: '/B/param-2'
Type: String
Value: 'sample-value-B-2'
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME:-localstack_main}"
image: localstack/localstack:1.4.0
ports:
- "4566:4566" # LocalStack Gateway
- "4510-4559:4510-4559" # external services port range
environment:
# - SERVICES=s3,ssm,secretsmanager
- AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-ap-northeast-1}
- DEBUG=${DEBUG-}
# - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-}
- DISABLE_CORS_CHECK=1
# - AWS_ACCESS_KEY_ID=test
# - AWS_SECRET_ACCESS_KEY=test
# volumes:
# - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager';
const main = async (): Promise<void> => {
const client = new SecretsManagerClient({
endpoint: process.env.USE_LOCALSTACK === 'true'
? 'http://localhost:4566'
: undefined,
});
const res = await client.send(new GetSecretValueCommand({
SecretId: 'sample-secret',
}));
console.debug(res);
const secretValues = JSON.parse(res.SecretString ?? ''); // to avoid `any`, use schema validation such as zod for example
console.log('value: ', secretValues);
}
await main();
import { GetParameterCommand, GetParametersByPathCommand, GetParametersCommand, SSMClient } from '@aws-sdk/client-ssm';
const main = async (): Promise<void> => {
const client = new SSMClient({
endpoint: process.env.USE_LOCALSTACK === 'true'
? 'http://localhost:4566'
: undefined,
});
{
const resultA = await client.send(new GetParametersByPathCommand({
Path: '/A/'
}));
console.log('path /A/*: ', resultA);
}
console.log(`
============================================================
`)
{
const resultB1 = await client.send(new GetParameterCommand({
Name: '/B/param-1'
}));
console.log('Name /B/param-1: ', resultB1);
}
console.log(`
============================================================
`)
{
const results = await client.send(new GetParametersCommand({
Names: [
'/A/param-2',
'/B/param-2',
],
}))
console.log('Params: ', results);
}
}
await main();
{
"name": "aws-example",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "index.js",
"scripts": {
"get-secrets": "dotenv -e .env -e .env.default tsx get-secrets-value.ts",
"get-ssm-params": "dotenv -e .env -e .env.default tsx get-ssm-params.ts",
"s3-presigned": "dotenv -e .env -e .env.default tsx s3-presigned.ts",
"clf:deploy": "dotenv -e .env -e .env.default ./clf-localstack-deploy.sh"
},
"private": true,
"devDependencies": {
"@types/node": "^18.13.0",
"@types/uuid": "^9.0.0",
"dotenv-cli": "^7.0.0",
"tsx": "^3.12.3",
"typescript": "^4.9.5"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.267.0",
"@aws-sdk/client-secrets-manager": "^3.267.0",
"@aws-sdk/client-ssm": "^3.267.0",
"@aws-sdk/s3-request-presigner": "^3.267.0",
"uuid": "^9.0.0",
"zod": "^3.20.6"
}
}
import { PutObjectCommand, type S3ClientConfig, S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { v4 as uuid } from 'uuid';
const bucketName = 'sample-bucket';
const main = async (): Promise<void> => {
const clientOptions = process.env.USE_LOCALSTACK === 'true'
? { endpoint: 'http://localhost:4566', forcePathStyle: true }
: {} satisfies S3ClientConfig;
const client = new S3Client({
...clientOptions
});
{
const command = new PutObjectCommand({
Bucket: bucketName,
Key: 'path/to/obj',
Body: 'BODY',
});
const putUrl = await getSignedUrl(client, command, {
expiresIn: 3600,
});
console.log('URL for PutObject: ', putUrl);
}
console.log(`
============================================================
`);
{
const objPath = 'test-path/data.json';
await client.send(new PutObjectCommand({
Bucket: bucketName,
Key: objPath,
Body: JSON.stringify({
id: uuid(),
description: 'test for S3 presigned URL',
createdDate: (new Date()).toISOString(),
}, null, 2)
}));
const command = new GetObjectCommand({
Bucket: bucketName,
Key: objPath,
})
const getUrl = await getSignedUrl(client, command, {
expiresIn: 3600,
});
console.log('URL for GetObject: ', getUrl);
}
}
await main();
{
"compilerOptions": {
"target": "es2022",
"lib": [
"esnext"
],
"module": "es2022",
"moduleResolution": "nodenext",
"noEmit": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment