1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-19 17:52:45 +02:00

chore: add proxy-aware regional STS authentication for AWS IAM DB auth (#10643)

https://linear.app/unleash/issue/2-3875/add-proxy-aware-regional-sts-authentication-for-aws-iam-db-auth

Adds proxy-aware regional STS authentication for AWS IAM DB auth.

We also added optional support for explicit IAM role assumption through
the `DATABASE_AWS_ROLE_ARN` environment variable.
This commit is contained in:
Nuno Góis 2025-09-10 10:50:39 +01:00 committed by GitHub
parent 7cec4d6923
commit 86530bcfbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 254 additions and 23 deletions

View File

@ -121,6 +121,7 @@
"pg-connection-string": "^2.5.0",
"pkginfo": "^0.4.1",
"prom-client": "^15.0.0",
"proxy-agent": "^6.5.0",
"sanitize-filename": "^1.6.3",
"semver": "^7.6.3",
"serve-favicon": "^2.5.0",

View File

@ -34,6 +34,7 @@ exports[`should create default config 1`] = `
"applicationName": "unleash",
"awsIamAuth": false,
"awsRegion": undefined,
"awsRoleArn": undefined,
"database": "unleash_db",
"disableMigration": false,
"driver": "postgres",

View File

@ -268,6 +268,7 @@ const defaultDbOptions: WithOptional<IDBOption, 'user' | 'password' | 'host'> =
applicationName: process.env.DATABASE_APPLICATION_NAME || 'unleash',
awsIamAuth: parseEnvVarBoolean(process.env.DATABASE_AWS_IAM, false),
awsRegion: process.env.AWS_REGION,
awsRoleArn: process.env.DATABASE_AWS_ROLE_ARN,
};
const defaultSessionOption = (isEnterprise: boolean): ISessionOption => ({

View File

@ -1,25 +1,63 @@
import { Signer } from '@aws-sdk/rds-signer';
import {
fromTemporaryCredentials,
fromNodeProviderChain,
} from '@aws-sdk/credential-providers';
import { NodeHttpHandler } from '@smithy/node-http-handler';
import { ProxyAgent } from 'proxy-agent';
import type { IDBOption } from '../types/option.js';
type PasswordResolver = () => Promise<string>;
export const getDBPasswordResolver = (db: IDBOption): PasswordResolver => {
if (db.awsIamAuth) {
if (!db.awsRegion)
throw new Error(
'AWS_REGION is required when DATABASE_AWS_IAM=true',
);
if (!db.awsIamAuth) return async () => db.password;
if (!db.awsRegion)
throw new Error('AWS_REGION is required when DATABASE_AWS_IAM=true');
const signer = new Signer({
region: db.awsRegion,
hostname: db.host,
port: db.port,
username: db.user,
});
return async () => signer.getAuthToken();
}
const needProxy = Boolean(
process.env.HTTPS_PROXY ||
process.env.HTTP_PROXY ||
process.env.NO_PROXY,
);
const proxyAgent = needProxy ? new ProxyAgent() : undefined;
return async () => db.password;
const requestHandler = needProxy
? new NodeHttpHandler({
httpAgent: proxyAgent,
httpsAgent: proxyAgent,
})
: undefined;
const clientConfig = {
region: db.awsRegion,
endpoint: `https://sts.${db.awsRegion}.amazonaws.com`,
requestHandler,
};
const baseCreds = fromNodeProviderChain({
clientConfig,
});
const credentials = db.awsRoleArn
? fromTemporaryCredentials({
params: {
RoleArn: db.awsRoleArn,
RoleSessionName: 'unleash-db-session',
},
clientConfig,
masterCredentials: baseCreds,
})
: baseCreds;
const signer = new Signer({
region: db.awsRegion,
hostname: db.host,
port: db.port,
username: db.user,
credentials,
});
return async () => signer.getAuthToken();
};
export const getDBPassword = (db: IDBOption): Promise<string> =>

View File

@ -40,6 +40,7 @@ export interface IDBOption {
applicationName?: string;
awsIamAuth?: boolean;
awsRegion?: string;
awsRoleArn?: string;
}
export interface ISessionOption {

207
yarn.lock
View File

@ -2354,6 +2354,13 @@ __metadata:
languageName: node
linkType: hard
"@tootallnate/quickjs-emscripten@npm:^0.23.0":
version: 0.23.0
resolution: "@tootallnate/quickjs-emscripten@npm:0.23.0"
checksum: 10c0/2a939b781826fb5fd3edd0f2ec3b321d259d760464cf20611c9877205aaca3ccc0b7304dea68416baa0d568e82cd86b17d29548d1e5139fa3155a4a86a2b4b49
languageName: node
linkType: hard
"@tsconfig/node10@npm:^1.0.7":
version: 1.0.9
resolution: "@tsconfig/node10@npm:1.0.9"
@ -2927,6 +2934,13 @@ __metadata:
languageName: node
linkType: hard
"agent-base@npm:^7.1.2":
version: 7.1.4
resolution: "agent-base@npm:7.1.4"
checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe
languageName: node
linkType: hard
"aggregate-error@npm:^3.0.0":
version: 3.1.0
resolution: "aggregate-error@npm:3.1.0"
@ -3090,6 +3104,15 @@ __metadata:
languageName: node
linkType: hard
"ast-types@npm:^0.13.4":
version: 0.13.4
resolution: "ast-types@npm:0.13.4"
dependencies:
tslib: "npm:^2.0.1"
checksum: 10c0/3a1a409764faa1471601a0ad01b3aa699292991aa9c8a30c7717002cabdf5d98008e7b53ae61f6e058f757fc6ba965e147967a93c13e62692c907d79cfb245f8
languageName: node
linkType: hard
"async@npm:^3.2.4":
version: 3.2.6
resolution: "async@npm:3.2.6"
@ -3133,6 +3156,13 @@ __metadata:
languageName: node
linkType: hard
"basic-ftp@npm:^5.0.2":
version: 5.0.5
resolution: "basic-ftp@npm:5.0.5"
checksum: 10c0/be983a3997749856da87b839ffce6b8ed6c7dbf91ea991d5c980d8add275f9f2926c19f80217ac3e7f353815be879371d636407ca72b038cea8cab30e53928a6
languageName: node
linkType: hard
"bcrypt-pbkdf@npm:^1.0.2":
version: 1.0.2
resolution: "bcrypt-pbkdf@npm:1.0.2"
@ -3747,6 +3777,13 @@ __metadata:
languageName: node
linkType: hard
"data-uri-to-buffer@npm:^6.0.2":
version: 6.0.2
resolution: "data-uri-to-buffer@npm:6.0.2"
checksum: 10c0/f76922bf895b3d7d443059ff278c9cc5efc89d70b8b80cd9de0aa79b3adc6d7a17948eefb8692e30398c43635f70ece1673d6085cc9eba2878dbc6c6da5292ac
languageName: node
linkType: hard
"date-fns@npm:^2.30.0":
version: 2.30.0
resolution: "date-fns@npm:2.30.0"
@ -3916,6 +3953,17 @@ __metadata:
languageName: node
linkType: hard
"degenerator@npm:^5.0.0":
version: 5.0.1
resolution: "degenerator@npm:5.0.1"
dependencies:
ast-types: "npm:^0.13.4"
escodegen: "npm:^2.1.0"
esprima: "npm:^4.0.1"
checksum: 10c0/e48d8a651edeb512a648711a09afec269aac6de97d442a4bb9cf121a66877e0eec11b9727100a10252335c0666ae1c84a8bc1e3a3f47788742c975064d2c7b1c
languageName: node
linkType: hard
"del-cli@npm:6.0.0":
version: 6.0.0
resolution: "del-cli@npm:6.0.0"
@ -4328,6 +4376,24 @@ __metadata:
languageName: node
linkType: hard
"escodegen@npm:^2.1.0":
version: 2.1.0
resolution: "escodegen@npm:2.1.0"
dependencies:
esprima: "npm:^4.0.1"
estraverse: "npm:^5.2.0"
esutils: "npm:^2.0.2"
source-map: "npm:~0.6.1"
dependenciesMeta:
source-map:
optional: true
bin:
escodegen: bin/escodegen.js
esgenerate: bin/esgenerate.js
checksum: 10c0/e1450a1f75f67d35c061bf0d60888b15f62ab63aef9df1901cffc81cffbbb9e8b3de237c5502cf8613a017c1df3a3003881307c78835a1ab54d8c8d2206e01d3
languageName: node
linkType: hard
"esm@npm:^3.2.25":
version: 3.2.25
resolution: "esm@npm:3.2.25"
@ -4347,6 +4413,23 @@ __metadata:
languageName: node
linkType: hard
"esprima@npm:^4.0.1":
version: 4.0.1
resolution: "esprima@npm:4.0.1"
bin:
esparse: ./bin/esparse.js
esvalidate: ./bin/esvalidate.js
checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3
languageName: node
linkType: hard
"estraverse@npm:^5.2.0":
version: 5.3.0
resolution: "estraverse@npm:5.3.0"
checksum: 10c0/1ff9447b96263dec95d6d67431c5e0771eb9776427421260a3e2f0fdd5d6bd4f8e37a7338f5ad2880c9f143450c9b1e4fc2069060724570a49cf9cf0312bd107
languageName: node
linkType: hard
"estree-walker@npm:^3.0.3":
version: 3.0.3
resolution: "estree-walker@npm:3.0.3"
@ -4356,6 +4439,13 @@ __metadata:
languageName: node
linkType: hard
"esutils@npm:^2.0.2":
version: 2.0.3
resolution: "esutils@npm:2.0.3"
checksum: 10c0/9a2fe69a41bfdade834ba7c42de4723c97ec776e40656919c62cbd13607c45e127a003f05f724a1ea55e5029a4cf2de444b13009f2af71271e42d93a637137c7
languageName: node
linkType: hard
"etag@npm:~1.8.1":
version: 1.8.1
resolution: "etag@npm:1.8.1"
@ -4908,6 +4998,17 @@ __metadata:
languageName: node
linkType: hard
"get-uri@npm:^6.0.1":
version: 6.0.5
resolution: "get-uri@npm:6.0.5"
dependencies:
basic-ftp: "npm:^5.0.2"
data-uri-to-buffer: "npm:^6.0.2"
debug: "npm:^4.3.4"
checksum: 10c0/c7ff5d5d55de53d23ecce7c5108cc3ed0db1174db43c9aa15506d640283d36ee0956fd8ba1fc50b06a718466cc85794ae9d8860193f91318afe846e3e7010f3a
languageName: node
linkType: hard
"getopts@npm:2.3.0":
version: 2.3.0
resolution: "getopts@npm:2.3.0"
@ -5146,7 +5247,7 @@ __metadata:
languageName: node
linkType: hard
"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.2":
"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.1, http-proxy-agent@npm:^7.0.2":
version: 7.0.2
resolution: "http-proxy-agent@npm:7.0.2"
dependencies:
@ -5176,6 +5277,16 @@ __metadata:
languageName: node
linkType: hard
"https-proxy-agent@npm:^7.0.6":
version: 7.0.6
resolution: "https-proxy-agent@npm:7.0.6"
dependencies:
agent-base: "npm:^7.1.2"
debug: "npm:4"
checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac
languageName: node
linkType: hard
"human-signals@npm:^5.0.0":
version: 5.0.0
resolution: "human-signals@npm:5.0.0"
@ -5952,6 +6063,13 @@ __metadata:
languageName: node
linkType: hard
"lru-cache@npm:^7.14.1":
version: 7.18.3
resolution: "lru-cache@npm:7.18.3"
checksum: 10c0/b3a452b491433db885beed95041eb104c157ef7794b9c9b4d647be503be91769d11206bb573849a16b4cc0d03cbd15ffd22df7960997788b74c1d399ac7a4fed
languageName: node
linkType: hard
"lru-cache@npm:^9.1.1":
version: 9.1.1
resolution: "lru-cache@npm:9.1.1"
@ -6489,6 +6607,13 @@ __metadata:
languageName: node
linkType: hard
"netmask@npm:^2.0.2":
version: 2.0.2
resolution: "netmask@npm:2.0.2"
checksum: 10c0/cafd28388e698e1138ace947929f842944d0f1c0b87d3fa2601a61b38dc89397d33c0ce2c8e7b99e968584b91d15f6810b91bef3f3826adf71b1833b61d4bf4f
languageName: node
linkType: hard
"next-tick@npm:1, next-tick@npm:^1.1.0":
version: 1.1.0
resolution: "next-tick@npm:1.1.0"
@ -6765,6 +6890,32 @@ __metadata:
languageName: node
linkType: hard
"pac-proxy-agent@npm:^7.1.0":
version: 7.2.0
resolution: "pac-proxy-agent@npm:7.2.0"
dependencies:
"@tootallnate/quickjs-emscripten": "npm:^0.23.0"
agent-base: "npm:^7.1.2"
debug: "npm:^4.3.4"
get-uri: "npm:^6.0.1"
http-proxy-agent: "npm:^7.0.0"
https-proxy-agent: "npm:^7.0.6"
pac-resolver: "npm:^7.0.1"
socks-proxy-agent: "npm:^8.0.5"
checksum: 10c0/0265c17c9401c2ea735697931a6553a0c6d8b20c4d7d4e3b3a0506080ba69a8d5ad656e2a6be875411212e2b6ed7a4d9526dd3997e08581fdfb1cbcad454c296
languageName: node
linkType: hard
"pac-resolver@npm:^7.0.1":
version: 7.0.1
resolution: "pac-resolver@npm:7.0.1"
dependencies:
degenerator: "npm:^5.0.0"
netmask: "npm:^2.0.2"
checksum: 10c0/5f3edd1dd10fded31e7d1f95776442c3ee51aa098c28b74ede4927d9677ebe7cebb2636750c24e945f5b84445e41ae39093d3a1014a994e5ceb9f0b1b88ebff5
languageName: node
linkType: hard
"package-json-from-dist@npm:^1.0.0":
version: 1.0.0
resolution: "package-json-from-dist@npm:1.0.0"
@ -7147,6 +7298,22 @@ __metadata:
languageName: node
linkType: hard
"proxy-agent@npm:^6.5.0":
version: 6.5.0
resolution: "proxy-agent@npm:6.5.0"
dependencies:
agent-base: "npm:^7.1.2"
debug: "npm:^4.3.4"
http-proxy-agent: "npm:^7.0.1"
https-proxy-agent: "npm:^7.0.6"
lru-cache: "npm:^7.14.1"
pac-proxy-agent: "npm:^7.1.0"
proxy-from-env: "npm:^1.1.0"
socks-proxy-agent: "npm:^8.0.5"
checksum: 10c0/7fd4e6f36bf17098a686d4aee3b8394abfc0b0537c2174ce96b0a4223198b9fafb16576c90108a3fcfc2af0168bd7747152bfa1f58e8fee91d3780e79aab7fd8
languageName: node
linkType: hard
"proxy-from-env@npm:^1.1.0":
version: 1.1.0
resolution: "proxy-from-env@npm:1.1.0"
@ -7885,6 +8052,17 @@ __metadata:
languageName: node
linkType: hard
"socks-proxy-agent@npm:^8.0.5":
version: 8.0.5
resolution: "socks-proxy-agent@npm:8.0.5"
dependencies:
agent-base: "npm:^7.1.2"
debug: "npm:^4.3.4"
socks: "npm:^2.8.3"
checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6
languageName: node
linkType: hard
"socks@npm:^2.7.1":
version: 2.7.1
resolution: "socks@npm:2.7.1"
@ -7895,6 +8073,16 @@ __metadata:
languageName: node
linkType: hard
"socks@npm:^2.8.3":
version: 2.8.7
resolution: "socks@npm:2.8.7"
dependencies:
ip-address: "npm:^10.0.1"
smart-buffer: "npm:^4.2.0"
checksum: 10c0/2805a43a1c4bcf9ebf6e018268d87b32b32b06fbbc1f9282573583acc155860dc361500f89c73bfbb157caa1b4ac78059eac0ef15d1811eb0ca75e0bdadbc9d2
languageName: node
linkType: hard
"source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1":
version: 1.2.1
resolution: "source-map-js@npm:1.2.1"
@ -7912,7 +8100,7 @@ __metadata:
languageName: node
linkType: hard
"source-map@npm:^0.6.0":
"source-map@npm:^0.6.0, source-map@npm:~0.6.1":
version: 0.6.1
resolution: "source-map@npm:0.6.1"
checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011
@ -8459,6 +8647,13 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:^2.0.1, tslib@npm:^2.6.2":
version: 2.8.1
resolution: "tslib@npm:2.8.1"
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
languageName: node
linkType: hard
"tslib@npm:^2.1.0":
version: 2.6.2
resolution: "tslib@npm:2.6.2"
@ -8466,13 +8661,6 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:^2.6.2":
version: 2.8.1
resolution: "tslib@npm:2.8.1"
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
languageName: node
linkType: hard
"tsscmp@npm:1.0.6":
version: 1.0.6
resolution: "tsscmp@npm:1.0.6"
@ -8731,6 +8919,7 @@ __metadata:
pg-connection-string: "npm:^2.5.0"
pkginfo: "npm:^0.4.1"
prom-client: "npm:^15.0.0"
proxy-agent: "npm:^6.5.0"
proxyquire: "npm:2.1.3"
sanitize-filename: "npm:^1.6.3"
semver: "npm:^7.6.3"