🔧 WIP: Enhance Bedrock endpoint configuration with user-provided credentials. (Still needs to implement user_provided bearer token support, but the UI is there for it)

- Added support for user-provided AWS credentials (Access Key ID, Secret Access Key, Session Token, Bearer Token) in the Bedrock endpoint configuration.
- Localized new strings for Bedrock configuration in translation files.
This commit is contained in:
Dustin Healy 2025-07-24 05:53:38 -07:00
parent f4facb7d35
commit 66dc48c8a0
8 changed files with 280 additions and 15 deletions

View file

@ -45,7 +45,9 @@ module.exports = {
EModelEndpoint.azureAssistants,
),
[EModelEndpoint.bedrock]: generateConfig(
process.env.BEDROCK_AWS_SECRET_ACCESS_KEY ?? process.env.BEDROCK_AWS_DEFAULT_REGION,
process.env.BEDROCK_AWS_SECRET_ACCESS_KEY ??
process.env.BEDROCK_AWS_BEARER_TOKEN ??
process.env.BEDROCK_AWS_DEFAULT_REGION,
),
/* key will be part of separate config */
[EModelEndpoint.agents]: generateConfig('true', undefined, EModelEndpoint.agents),

View file

@ -74,6 +74,23 @@ async function getEndpointsConfig(req) {
};
}
// Add individual credential flags for Bedrock
if (mergedConfig[EModelEndpoint.bedrock]) {
const userProvideAccessKeyId = process.env.BEDROCK_AWS_ACCESS_KEY_ID === 'user_provided';
const userProvideSecretAccessKey =
process.env.BEDROCK_AWS_SECRET_ACCESS_KEY === 'user_provided';
const userProvideSessionToken = process.env.BEDROCK_AWS_SESSION_TOKEN === 'user_provided';
const userProvideBearerToken = process.env.BEDROCK_AWS_BEARER_TOKEN === 'user_provided';
mergedConfig[EModelEndpoint.bedrock] = {
...mergedConfig[EModelEndpoint.bedrock],
userProvideAccessKeyId,
userProvideSecretAccessKey,
userProvideSessionToken,
userProvideBearerToken,
};
}
const endpointsConfig = orderEndpointsConfig(mergedConfig);
await cache.set(CacheKeys.ENDPOINT_CONFIG, endpointsConfig);

View file

@ -8,27 +8,43 @@ const {
bedrockOutputParser,
removeNullishValues,
} = require('librechat-data-provider');
const { getUserKey, checkUserKeyExpiry } = require('~/server/services/UserService');
const { getUserKeyValues, checkUserKeyExpiry } = require('~/server/services/UserService');
const getOptions = async ({ req, overrideModel, endpointOption }) => {
const {
BEDROCK_AWS_SECRET_ACCESS_KEY,
BEDROCK_AWS_ACCESS_KEY_ID,
BEDROCK_AWS_SESSION_TOKEN,
BEDROCK_AWS_BEARER_TOKEN,
BEDROCK_REVERSE_PROXY,
BEDROCK_AWS_DEFAULT_REGION,
PROXY,
} = process.env;
const expiresAt = req.body.key;
const isUserProvided = BEDROCK_AWS_SECRET_ACCESS_KEY === AuthType.USER_PROVIDED;
const isUserProvided =
BEDROCK_AWS_SECRET_ACCESS_KEY === AuthType.USER_PROVIDED ||
BEDROCK_AWS_BEARER_TOKEN === AuthType.USER_PROVIDED;
let credentials = isUserProvided
? await getUserKey({ userId: req.user.id, name: EModelEndpoint.bedrock })
: {
accessKeyId: BEDROCK_AWS_ACCESS_KEY_ID,
secretAccessKey: BEDROCK_AWS_SECRET_ACCESS_KEY,
...(BEDROCK_AWS_SESSION_TOKEN && { sessionToken: BEDROCK_AWS_SESSION_TOKEN }),
};
let userValues = null;
if (isUserProvided) {
if (expiresAt) {
checkUserKeyExpiry(expiresAt, EModelEndpoint.bedrock);
}
userValues = await getUserKeyValues({ userId: req.user.id, name: EModelEndpoint.bedrock });
}
let credentials;
if (isUserProvided) {
credentials = JSON.parse(userValues.apiKey);
} else if (BEDROCK_AWS_BEARER_TOKEN) {
credentials = { bearerToken: BEDROCK_AWS_BEARER_TOKEN };
} else {
credentials = {
accessKeyId: BEDROCK_AWS_ACCESS_KEY_ID,
secretAccessKey: BEDROCK_AWS_SECRET_ACCESS_KEY,
...(BEDROCK_AWS_SESSION_TOKEN && { sessionToken: BEDROCK_AWS_SESSION_TOKEN }),
};
}
if (!credentials) {
throw new Error('Bedrock credentials not provided. Please provide them again.');
@ -36,6 +52,7 @@ const getOptions = async ({ req, overrideModel, endpointOption }) => {
if (
!isUserProvided &&
!credentials.bearerToken &&
(credentials.accessKeyId === undefined || credentials.accessKeyId === '') &&
(credentials.secretAccessKey === undefined || credentials.secretAccessKey === '')
) {