Support AWS profile to configure Bedrock Authentication

Added support for configurations under ~/.aws/credentials or ~/.aws/config.
This commit is contained in:
Lunchb0ne
2025-01-16 18:01:49 +00:00
parent 084599c9d0
commit 7a61e6ab74
6 changed files with 145 additions and 27 deletions

View File

@@ -1,7 +1,16 @@
// Mock AWS SDK credential providers
jest.mock("@aws-sdk/credential-providers", () => ({
fromIni: jest.fn().mockReturnValue({
accessKeyId: "profile-access-key",
secretAccessKey: "profile-secret-key",
}),
}))
import { AwsBedrockHandler } from "../bedrock"
import { MessageContent } from "../../../shared/api"
import { BedrockRuntimeClient } from "@aws-sdk/client-bedrock-runtime"
import { Anthropic } from "@anthropic-ai/sdk"
import { fromIni } from "@aws-sdk/credential-providers"
describe("AwsBedrockHandler", () => {
let handler: AwsBedrockHandler
@@ -30,6 +39,65 @@ describe("AwsBedrockHandler", () => {
})
expect(handlerWithoutCreds).toBeInstanceOf(AwsBedrockHandler)
})
it("should initialize with AWS profile credentials", () => {
const handlerWithProfile = new AwsBedrockHandler({
apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
awsRegion: "us-east-1",
awsUseProfile: true,
awsProfile: "test-profile",
})
expect(handlerWithProfile).toBeInstanceOf(AwsBedrockHandler)
expect(handlerWithProfile["options"].awsUseProfile).toBe(true)
expect(handlerWithProfile["options"].awsProfile).toBe("test-profile")
})
it("should initialize with AWS profile enabled but no profile set", () => {
const handlerWithoutProfile = new AwsBedrockHandler({
apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
awsRegion: "us-east-1",
awsUseProfile: true,
})
expect(handlerWithoutProfile).toBeInstanceOf(AwsBedrockHandler)
expect(handlerWithoutProfile["options"].awsUseProfile).toBe(true)
expect(handlerWithoutProfile["options"].awsProfile).toBeUndefined()
})
})
describe("AWS SDK client configuration", () => {
it("should configure client with profile credentials when profile mode is enabled", async () => {
// Import the fromIni function to mock it
jest.mock("@aws-sdk/credential-providers", () => ({
fromIni: jest.fn().mockReturnValue({
accessKeyId: "profile-access-key",
secretAccessKey: "profile-secret-key",
}),
}))
const handlerWithProfile = new AwsBedrockHandler({
apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
awsRegion: "us-east-1",
awsUseProfile: true,
awsProfile: "test-profile",
})
// Mock a simple API call to verify credentials are used
const mockResponse = {
output: new TextEncoder().encode(JSON.stringify({ content: "test" })),
}
const mockSend = jest.fn().mockResolvedValue(mockResponse)
handlerWithProfile["client"] = {
send: mockSend,
} as unknown as BedrockRuntimeClient
await handlerWithProfile.completePrompt("test")
// Verify the client was configured with profile credentials
expect(mockSend).toHaveBeenCalled()
expect(fromIni).toHaveBeenCalledWith({
profile: "test-profile",
})
})
})
describe("createMessage", () => {

View File

@@ -4,6 +4,7 @@ import {
ConverseCommand,
BedrockRuntimeClientConfig,
} from "@aws-sdk/client-bedrock-runtime"
import { fromIni } from "@aws-sdk/credential-providers"
import { Anthropic } from "@anthropic-ai/sdk"
import { ApiHandler, SingleCompletionHandler } from "../"
import { ApiHandlerOptions, BedrockModelId, ModelInfo, bedrockDefaultModelId, bedrockModels } from "../../shared/api"
@@ -50,13 +51,17 @@ export class AwsBedrockHandler implements ApiHandler, SingleCompletionHandler {
constructor(options: ApiHandlerOptions) {
this.options = options
// Only include credentials if they actually exist
const clientConfig: BedrockRuntimeClientConfig = {
region: this.options.awsRegion || "us-east-1",
}
if (this.options.awsAccessKey && this.options.awsSecretKey) {
// Create credentials object with all properties at once
if (this.options.awsUseProfile && this.options.awsProfile) {
// Use profile-based credentials if enabled and profile is set
clientConfig.credentials = fromIni({
profile: this.options.awsProfile,
})
} else if (this.options.awsAccessKey && this.options.awsSecretKey) {
// Use direct credentials if provided
clientConfig.credentials = {
accessKeyId: this.options.awsAccessKey,
secretAccessKey: this.options.awsSecretKey,