From 2eaea9276d19ac87aac423577fd2db859fffc494 Mon Sep 17 00:00:00 2001 From: Vecto0rdecay Date: Wed, 17 Jun 2026 09:57:16 -0400 Subject: [PATCH 1/2] Add bedrock-agents module for AWS Bedrock agent enumeration Enumerates Bedrock agents across all regions, extracting system prompts, action group details (Lambda ARNs, API schemas, function definitions), collaborator topology, aliases, guardrail config, and memory settings. Generates loot files with follow-up commands and full agent details. --- README.md | 3 +- aws/bedrock-agents.go | 507 ++++++++++++++++++++++++++++++++++ aws/bedrock-agents_test.go | 69 +++++ aws/sdk/bedrockagent.go | 318 +++++++++++++++++++++ aws/sdk/bedrockagent_mocks.go | 151 ++++++++++ cli/aws.go | 52 ++++ go.mod | 9 +- go.sum | 10 + 8 files changed, 1114 insertions(+), 5 deletions(-) create mode 100644 aws/bedrock-agents.go create mode 100644 aws/bedrock-agents_test.go create mode 100644 aws/sdk/bedrockagent.go create mode 100644 aws/sdk/bedrockagent_mocks.go diff --git a/README.md b/README.md index b6070219..11d06da0 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ For the full documentation please refer to our [wiki](https://github.com/BishopF | Provider| CloudFox Commands | | - | - | -| AWS | 34 | +| AWS | 35 | | Azure | 4 | | GCP | 60 | | Kubernetes | Support Planned | @@ -160,6 +160,7 @@ For detailed setup instructions, see the [GCP Setup Guide](https://github.com/Bi | AWS | [all-checks](https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#all-checks) | Run all of the other commands using reasonable defaults. You'll still want to check out the non-default options of each command, but this is a great place to start. | | AWS | [access-keys](https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#access-keys) | Lists active access keys for all users. Useful for cross referencing a key you found with which in-scope account it belongs to. | | AWS | [api-gw](https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#api-gw) | Lists API gateway endpoints and gives you custom curl commands including API tokens if they are stored in metadata. | +| AWS | [bedrock-agents](https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#bedrock-agents) | Enumerate Bedrock agents, action groups, collaborators, and aliases. Extracts system prompts, Lambda integrations, and API schemas. | | AWS | [buckets](https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#filesystems) | Lists the buckets in the account and gives you handy commands for inspecting them further. | | AWS | [cape](https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#cape) | Enumerates cross-account privilege escalation paths. Requires `pmapper` to be run first | | AWS | [cloudformation](https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#cloudformation) | Lists the cloudformation stacks in the account. Generates loot file with stack details, stack parameters, and stack output - look for secrets. | diff --git a/aws/bedrock-agents.go b/aws/bedrock-agents.go new file mode 100644 index 00000000..18f8a3d1 --- /dev/null +++ b/aws/bedrock-agents.go @@ -0,0 +1,507 @@ +package aws + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "sync" + + "github.com/BishopFox/cloudfox/aws/sdk" + "github.com/BishopFox/cloudfox/internal" + "github.com/aws/aws-sdk-go-v2/aws" + bedrockagentTypes "github.com/aws/aws-sdk-go-v2/service/bedrockagent/types" + "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/bishopfox/awsservicemap" + "github.com/sirupsen/logrus" +) + +type BedrockAgentsModule struct { + BedrockAgentClient sdk.BedrockAgentClientInterface + + Caller sts.GetCallerIdentityOutput + AWSRegions []string + AWSProfile string + Goroutines int + WrapTable bool + AWSOutputType string + AWSTableCols string + ServiceMap *awsservicemap.AwsServiceMap + + Agents []BedrockAgent + CommandCounter internal.CommandCounter + output internal.OutputData2 + modLog *logrus.Entry +} + +type BedrockAgent struct { + Region string + Name string + AgentId string + AgentArn string + Status string + FoundationModel string + RoleArn string + Instruction string + ActionGroups int + Collaborators int + Aliases int + MemoryEnabled string + GuardrailId string + IdleSessionTTL int32 + LatestVersion string + ActionGroupDetails []BedrockActionGroupDetail +} + +type BedrockActionGroupDetail struct { + Name string + Id string + Description string + ExecutorType string + ExecutorArn string + ApiSchema string + Functions []BedrockActionGroupFunction +} + +type BedrockActionGroupFunction struct { + Name string + Description string + Parameters map[string]string +} + +func (m *BedrockAgentsModule) PrintBedrockAgents(outputDirectory string, verbosity int) { + m.output.Verbosity = verbosity + m.output.Directory = outputDirectory + m.output.CallingModule = "bedrock-agents" + m.modLog = internal.TxtLog.WithFields(logrus.Fields{ + "module": m.output.CallingModule, + }) + if m.AWSProfile == "" { + m.AWSProfile = internal.BuildAWSPath(m.Caller) + } + + fmt.Printf("[%s][%s] Enumerating Bedrock agents for account %s.\n", cyan(m.output.CallingModule), cyan(m.AWSProfile), aws.ToString(m.Caller.Account)) + + wg := new(sync.WaitGroup) + semaphore := make(chan struct{}, m.Goroutines) + + spinnerDone := make(chan bool) + go internal.SpinUntil(m.output.CallingModule, &m.CommandCounter, spinnerDone, "regions") + + dataReceiver := make(chan BedrockAgent) + receiverDone := make(chan bool) + go m.Receiver(dataReceiver, receiverDone) + + for _, region := range m.AWSRegions { + wg.Add(1) + m.CommandCounter.IncrPending() + go m.executeChecks(region, wg, semaphore, dataReceiver) + } + wg.Wait() + + spinnerDone <- true + <-spinnerDone + receiverDone <- true + <-receiverDone + + m.output.Headers = []string{ + "Account", + "Region", + "Name", + "AgentId", + "Status", + "FoundationModel", + "RoleArn", + "ActionGroups", + "Collaborators", + "AgentArn", + "IdleSessionTTL", + "Aliases", + "MemoryEnabled", + "GuardrailId", + } + + var tableCols []string + if m.AWSTableCols != "" { + m.AWSTableCols = strings.ReplaceAll(m.AWSTableCols, ", ", ",") + m.AWSTableCols = strings.ReplaceAll(m.AWSTableCols, ", ", ",") + tableCols = strings.Split(m.AWSTableCols, ",") + } else if m.AWSOutputType == "wide" { + tableCols = []string{ + "Account", + "Region", + "Name", + "Status", + "FoundationModel", + "RoleArn", + "ActionGroups", + "Collaborators", + "AgentArn", + "IdleSessionTTL", + "Aliases", + "MemoryEnabled", + "GuardrailId", + } + } else { + tableCols = []string{ + "Account", + "Region", + "Name", + "Status", + "FoundationModel", + "RoleArn", + "ActionGroups", + "Collaborators", + } + } + + for _, agent := range m.Agents { + m.output.Body = append( + m.output.Body, + []string{ + aws.ToString(m.Caller.Account), + agent.Region, + agent.Name, + agent.AgentId, + agent.Status, + agent.FoundationModel, + agent.RoleArn, + strconv.Itoa(agent.ActionGroups), + strconv.Itoa(agent.Collaborators), + agent.AgentArn, + strconv.Itoa(int(agent.IdleSessionTTL)), + strconv.Itoa(agent.Aliases), + agent.MemoryEnabled, + agent.GuardrailId, + }, + ) + } + + if len(m.output.Body) > 0 { + m.output.FilePath = filepath.Join(outputDirectory, "cloudfox-output", "aws", fmt.Sprintf("%s-%s", m.AWSProfile, aws.ToString(m.Caller.Account))) + o := internal.OutputClient{ + Verbosity: verbosity, + CallingModule: m.output.CallingModule, + Table: internal.TableClient{ + Wrap: m.WrapTable, + }, + } + o.Table.TableFiles = append(o.Table.TableFiles, internal.TableFile{ + Header: m.output.Headers, + Body: m.output.Body, + TableCols: tableCols, + Name: m.output.CallingModule, + }) + o.PrefixIdentifier = m.AWSProfile + o.Table.DirectoryName = filepath.Join(outputDirectory, "cloudfox-output", "aws", fmt.Sprintf("%s-%s", m.AWSProfile, aws.ToString(m.Caller.Account))) + o.WriteFullOutput(o.Table.TableFiles, nil) + m.writeLoot(o.Table.DirectoryName, verbosity) + fmt.Printf("[%s][%s] %s Bedrock agents found.\n", cyan(m.output.CallingModule), cyan(m.AWSProfile), strconv.Itoa(len(m.output.Body))) + } else { + fmt.Printf("[%s][%s] No Bedrock agents found, skipping the creation of an output file.\n", cyan(m.output.CallingModule), cyan(m.AWSProfile)) + } + fmt.Printf("[%s][%s] For context and next steps: https://github.com/BishopFox/cloudfox/wiki/AWS-Commands#%s\n", cyan(m.output.CallingModule), cyan(m.AWSProfile), m.output.CallingModule) +} + +func (m *BedrockAgentsModule) executeChecks(r string, wg *sync.WaitGroup, semaphore chan struct{}, dataReceiver chan BedrockAgent) { + defer wg.Done() + + servicemap := m.ServiceMap + if servicemap == nil { + servicemap = &awsservicemap.AwsServiceMap{ + JsonFileSource: "DOWNLOAD_FROM_AWS", + } + } + res, err := servicemap.IsServiceInRegion("bedrock", r) + if err != nil { + m.modLog.Error(err) + } + if res { + m.CommandCounter.IncrTotal() + wg.Add(1) + m.getBedrockAgentsPerRegion(r, wg, semaphore, dataReceiver) + } +} + +func (m *BedrockAgentsModule) Receiver(receiver chan BedrockAgent, receiverDone chan bool) { + defer close(receiverDone) + for { + select { + case data := <-receiver: + m.Agents = append(m.Agents, data) + case <-receiverDone: + receiverDone <- true + return + } + } +} + +func (m *BedrockAgentsModule) getBedrockAgentsPerRegion(r string, wg *sync.WaitGroup, semaphore chan struct{}, dataReceiver chan BedrockAgent) { + defer func() { + m.CommandCounter.DecrExecuting() + m.CommandCounter.IncrComplete() + wg.Done() + }() + semaphore <- struct{}{} + defer func() { + <-semaphore + }() + + agents, err := sdk.CachedBedrockAgentListAgents(m.BedrockAgentClient, aws.ToString(m.Caller.Account), r) + if err != nil { + m.modLog.Error(err.Error()) + m.CommandCounter.IncrError() + return + } + + for _, agentSummary := range agents { + agentID := aws.ToString(agentSummary.AgentId) + agentVersion := aws.ToString(agentSummary.LatestAgentVersion) + if agentVersion == "" { + agentVersion = "DRAFT" + } + + agent, err := sdk.CachedBedrockAgentGetAgent(m.BedrockAgentClient, aws.ToString(m.Caller.Account), r, agentID) + if err != nil { + m.modLog.Error(err.Error()) + m.CommandCounter.IncrError() + continue + } + + aliases, _ := sdk.CachedBedrockAgentListAgentAliases(m.BedrockAgentClient, aws.ToString(m.Caller.Account), r, agentID) + actionGroupSummaries, _ := sdk.CachedBedrockAgentListAgentActionGroups(m.BedrockAgentClient, aws.ToString(m.Caller.Account), r, agentID, agentVersion) + collaborators, _ := sdk.CachedBedrockAgentListAgentCollaborators(m.BedrockAgentClient, aws.ToString(m.Caller.Account), r, agentID, agentVersion) + + var actionGroupDetails []BedrockActionGroupDetail + for _, agSummary := range actionGroupSummaries { + agDetail := m.getActionGroupDetail(r, agentID, agentVersion, agSummary) + actionGroupDetails = append(actionGroupDetails, agDetail) + } + + memoryEnabled := "No" + if agent.MemoryConfiguration != nil && len(agent.MemoryConfiguration.EnabledMemoryTypes) > 0 { + memoryEnabled = "Yes" + } + + guardrailId := "" + if agent.GuardrailConfiguration != nil { + guardrailId = aws.ToString(agent.GuardrailConfiguration.GuardrailIdentifier) + } + + var idleSessionTTL int32 + if agent.IdleSessionTTLInSeconds != nil { + idleSessionTTL = *agent.IdleSessionTTLInSeconds + } + + dataReceiver <- BedrockAgent{ + Region: r, + Name: aws.ToString(agent.AgentName), + AgentId: agentID, + AgentArn: aws.ToString(agent.AgentArn), + Status: string(agent.AgentStatus), + FoundationModel: aws.ToString(agent.FoundationModel), + RoleArn: aws.ToString(agent.AgentResourceRoleArn), + Instruction: aws.ToString(agent.Instruction), + ActionGroups: len(actionGroupSummaries), + Collaborators: len(collaborators), + Aliases: len(aliases), + MemoryEnabled: memoryEnabled, + GuardrailId: guardrailId, + IdleSessionTTL: idleSessionTTL, + LatestVersion: agentVersion, + ActionGroupDetails: actionGroupDetails, + } + } +} + +func (m *BedrockAgentsModule) getActionGroupDetail(region string, agentID string, agentVersion string, summary bedrockagentTypes.ActionGroupSummary) BedrockActionGroupDetail { + agID := aws.ToString(summary.ActionGroupId) + detail := BedrockActionGroupDetail{ + Name: aws.ToString(summary.ActionGroupName), + Id: agID, + } + + ag, err := sdk.CachedBedrockAgentGetAgentActionGroup(m.BedrockAgentClient, aws.ToString(m.Caller.Account), region, agentID, agentVersion, agID) + if err != nil { + m.modLog.Error(err.Error()) + return detail + } + detail.Description = aws.ToString(ag.Description) + + switch v := ag.ActionGroupExecutor.(type) { + case *bedrockagentTypes.ActionGroupExecutorMemberLambda: + detail.ExecutorType = "Lambda" + detail.ExecutorArn = v.Value + case *bedrockagentTypes.ActionGroupExecutorMemberCustomControl: + detail.ExecutorType = "ReturnControl" + } + + switch v := ag.ApiSchema.(type) { + case *bedrockagentTypes.APISchemaMemberPayload: + detail.ApiSchema = v.Value + case *bedrockagentTypes.APISchemaMemberS3: + detail.ApiSchema = fmt.Sprintf("s3://%s/%s", aws.ToString(v.Value.S3BucketName), aws.ToString(v.Value.S3ObjectKey)) + } + + switch v := ag.FunctionSchema.(type) { + case *bedrockagentTypes.FunctionSchemaMemberFunctions: + for _, fn := range v.Value { + f := BedrockActionGroupFunction{ + Name: aws.ToString(fn.Name), + Description: aws.ToString(fn.Description), + Parameters: make(map[string]string), + } + for paramName, paramDetail := range fn.Parameters { + required := "" + if paramDetail.Required != nil && *paramDetail.Required { + required = ",required" + } + f.Parameters[paramName] = fmt.Sprintf("%s%s", paramDetail.Type, required) + } + detail.Functions = append(detail.Functions, f) + } + } + + return detail +} + +func (m *BedrockAgentsModule) writeLoot(outputDirectory string, verbosity int) { + path := filepath.Join(outputDirectory, "loot") + err := os.MkdirAll(path, os.ModePerm) + if err != nil { + m.modLog.Error(err.Error()) + m.CommandCounter.IncrError() + } + + m.writeLootCommands(path, verbosity) + m.writeLootDetails(path, verbosity) +} + +func (m *BedrockAgentsModule) writeLootCommands(lootDir string, verbosity int) { + commandsFile := filepath.Join(lootDir, "bedrock-agents-commands.txt") + + var out string + out += fmt.Sprintln("#############################################") + out += fmt.Sprintln("# The profile you will use to perform these commands is most likely not the profile you used to run CloudFox") + out += fmt.Sprintln("# Set the $profile environment variable to the profile you are going to use.") + out += fmt.Sprintln("# E.g., export profile=dev-prod.") + out += fmt.Sprintln("#############################################") + out += fmt.Sprintln("") + + for _, agent := range m.Agents { + out += fmt.Sprintln("=============================================") + out += fmt.Sprintf("# Agent: %s (%s) in %s\n\n", agent.Name, agent.AgentId, agent.Region) + + out += "# Get full agent configuration including instruction/system prompt\n" + out += fmt.Sprintf("aws --profile $profile --region %s bedrock-agent get-agent --agent-id %s\n\n", agent.Region, agent.AgentId) + + out += "# List agent aliases (production routing)\n" + out += fmt.Sprintf("aws --profile $profile --region %s bedrock-agent list-agent-aliases --agent-id %s\n\n", agent.Region, agent.AgentId) + + out += "# List action groups (tool integrations)\n" + out += fmt.Sprintf("aws --profile $profile --region %s bedrock-agent list-agent-action-groups --agent-id %s --agent-version %s\n\n", agent.Region, agent.AgentId, agent.LatestVersion) + + for _, ag := range agent.ActionGroupDetails { + out += fmt.Sprintf("# Get action group detail: %s\n", ag.Name) + out += fmt.Sprintf("aws --profile $profile --region %s bedrock-agent get-agent-action-group --agent-id %s --agent-version %s --action-group-id %s\n\n", agent.Region, agent.AgentId, agent.LatestVersion, ag.Id) + } + + if agent.Collaborators > 0 { + out += "# List collaborators (supervisor/worker topology)\n" + out += fmt.Sprintf("aws --profile $profile --region %s bedrock-agent list-agent-collaborators --agent-id %s --agent-version %s\n\n", agent.Region, agent.AgentId, agent.LatestVersion) + } + } + + err := os.WriteFile(commandsFile, []byte(out), 0644) + if err != nil { + m.modLog.Error(err.Error()) + m.CommandCounter.IncrError() + } + + if verbosity > 2 { + fmt.Println() + fmt.Printf("[%s][%s] %s \n\n", cyan(m.output.CallingModule), cyan(m.AWSProfile), green("Beginning of commands loot file.")) + fmt.Print(out) + fmt.Printf("[%s][%s] %s \n\n", cyan(m.output.CallingModule), cyan(m.AWSProfile), green("End of commands loot file.")) + } + fmt.Printf("[%s][%s] Loot written to [%s]\n", cyan(m.output.CallingModule), cyan(m.AWSProfile), commandsFile) +} + +func (m *BedrockAgentsModule) writeLootDetails(lootDir string, verbosity int) { + detailsFile := filepath.Join(lootDir, "bedrock-agents-details.txt") + + var out string + for _, agent := range m.Agents { + out += fmt.Sprintln("=============================================") + out += fmt.Sprintf("# Agent: %s\n", agent.Name) + out += fmt.Sprintf("# ID: %s | Region: %s\n", agent.AgentId, agent.Region) + out += fmt.Sprintf("# ARN: %s\n", agent.AgentArn) + out += fmt.Sprintf("# Status: %s\n", agent.Status) + out += fmt.Sprintf("# Foundation Model: %s\n", agent.FoundationModel) + out += fmt.Sprintf("# Execution Role: %s\n", agent.RoleArn) + out += fmt.Sprintf("# Memory Enabled: %s\n", agent.MemoryEnabled) + out += fmt.Sprintf("# Guardrail: %s\n", agent.GuardrailId) + out += fmt.Sprintf("# Idle Session TTL: %ds\n", agent.IdleSessionTTL) + out += fmt.Sprintf("# Action Groups: %d | Collaborators: %d | Aliases: %d\n", agent.ActionGroups, agent.Collaborators, agent.Aliases) + out += fmt.Sprintln("") + out += fmt.Sprintln("## Instruction / System Prompt:") + if agent.Instruction != "" { + out += fmt.Sprintln(agent.Instruction) + } else { + out += fmt.Sprintln("(none)") + } + out += fmt.Sprintln("") + + if len(agent.ActionGroupDetails) > 0 { + out += fmt.Sprintln("## Action Groups:") + for _, ag := range agent.ActionGroupDetails { + out += fmt.Sprintf(" [%s] %s\n", ag.Id, ag.Name) + if ag.Description != "" { + out += fmt.Sprintf(" Description: %s\n", ag.Description) + } + if ag.ExecutorType != "" { + out += fmt.Sprintf(" Executor: %s", ag.ExecutorType) + if ag.ExecutorArn != "" { + out += fmt.Sprintf(" -> %s", ag.ExecutorArn) + } + out += "\n" + } + if ag.ApiSchema != "" { + out += fmt.Sprintf(" API Schema:\n%s\n", indentBlock(ag.ApiSchema, " ")) + } + for _, fn := range ag.Functions { + out += fmt.Sprintf(" Function: %s\n", fn.Name) + if fn.Description != "" { + out += fmt.Sprintf(" Description: %s\n", fn.Description) + } + if len(fn.Parameters) > 0 { + params, _ := json.Marshal(fn.Parameters) + out += fmt.Sprintf(" Parameters: %s\n", string(params)) + } + } + out += fmt.Sprintln("") + } + } + } + + err := os.WriteFile(detailsFile, []byte(out), 0644) + if err != nil { + m.modLog.Error(err.Error()) + m.CommandCounter.IncrError() + } + + fmt.Printf("[%s][%s] Loot written to [%s]\n", cyan(m.output.CallingModule), cyan(m.AWSProfile), detailsFile) +} + +func indentBlock(text string, prefix string) string { + lines := strings.Split(text, "\n") + for i, line := range lines { + if line != "" { + lines[i] = prefix + line + } + } + return strings.Join(lines, "\n") +} + diff --git a/aws/bedrock-agents_test.go b/aws/bedrock-agents_test.go new file mode 100644 index 00000000..8a04b064 --- /dev/null +++ b/aws/bedrock-agents_test.go @@ -0,0 +1,69 @@ +package aws + +import ( + "log" + "testing" + + "github.com/BishopFox/cloudfox/aws/sdk" + "github.com/BishopFox/cloudfox/internal" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/sts" +) + +func TestBedrockAgents(t *testing.T) { + subtests := []struct { + name string + outputDirectory string + verbosity int + testModule BedrockAgentsModule + expectedResult []BedrockAgent + }{ + { + name: "test_bedrock_agents", + outputDirectory: ".", + verbosity: 2, + testModule: BedrockAgentsModule{ + BedrockAgentClient: &sdk.MockedBedrockAgentClient{}, + Caller: sts.GetCallerIdentityOutput{Arn: aws.String("arn:aws:iam::123456789012:user/test"), Account: aws.String("123456789012")}, + AWSProfile: "test", + Goroutines: 3, + AWSRegions: AWSRegions, + }, + expectedResult: []BedrockAgent{ + { + Name: "LabAgent01", + AgentId: "AGENT001", + Status: "PREPARED", + FoundationModel: "us.anthropic.claude-sonnet-4-6", + ActionGroups: 1, + Collaborators: 1, + }, + { + Name: "ResearchWorker01", + AgentId: "AGENT002", + Status: "PREPARED", + FoundationModel: "us.anthropic.claude-sonnet-4-6", + ActionGroups: 1, + Collaborators: 0, + }, + }, + }, + } + internal.MockFileSystem(true) + for _, subtest := range subtests { + t.Run(subtest.name, func(t *testing.T) { + subtest.testModule.PrintBedrockAgents(subtest.outputDirectory, subtest.verbosity) + for index, expectedAgent := range subtest.expectedResult { + if index >= len(subtest.testModule.Agents) { + log.Fatalf("Expected %d agents but only found %d", len(subtest.expectedResult), len(subtest.testModule.Agents)) + } + if expectedAgent.Name != subtest.testModule.Agents[index].Name { + log.Fatalf("Agent name %s does not match expected name %s", subtest.testModule.Agents[index].Name, expectedAgent.Name) + } + if expectedAgent.ActionGroups != subtest.testModule.Agents[index].ActionGroups { + log.Fatalf("Agent %s action groups count %d does not match expected %d", expectedAgent.Name, subtest.testModule.Agents[index].ActionGroups, expectedAgent.ActionGroups) + } + } + }) + } +} diff --git a/aws/sdk/bedrockagent.go b/aws/sdk/bedrockagent.go new file mode 100644 index 00000000..d5b52b31 --- /dev/null +++ b/aws/sdk/bedrockagent.go @@ -0,0 +1,318 @@ +package sdk + +import ( + "context" + "encoding/gob" + "fmt" + + "github.com/BishopFox/cloudfox/internal" + "github.com/aws/aws-sdk-go-v2/service/bedrockagent" + bedrockagentTypes "github.com/aws/aws-sdk-go-v2/service/bedrockagent/types" + "github.com/patrickmn/go-cache" + "github.com/sirupsen/logrus" +) + +type BedrockAgentClientInterface interface { + ListAgents(context.Context, *bedrockagent.ListAgentsInput, ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentsOutput, error) + GetAgent(context.Context, *bedrockagent.GetAgentInput, ...func(*bedrockagent.Options)) (*bedrockagent.GetAgentOutput, error) + ListAgentAliases(context.Context, *bedrockagent.ListAgentAliasesInput, ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentAliasesOutput, error) + ListAgentActionGroups(context.Context, *bedrockagent.ListAgentActionGroupsInput, ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentActionGroupsOutput, error) + GetAgentActionGroup(context.Context, *bedrockagent.GetAgentActionGroupInput, ...func(*bedrockagent.Options)) (*bedrockagent.GetAgentActionGroupOutput, error) + ListAgentCollaborators(context.Context, *bedrockagent.ListAgentCollaboratorsInput, ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentCollaboratorsOutput, error) + GetAgentCollaborator(context.Context, *bedrockagent.GetAgentCollaboratorInput, ...func(*bedrockagent.Options)) (*bedrockagent.GetAgentCollaboratorOutput, error) +} + +func init() { + gob.Register([]bedrockagentTypes.AgentSummary{}) + gob.Register([]bedrockagentTypes.AgentAliasSummary{}) + gob.Register([]bedrockagentTypes.ActionGroupSummary{}) + gob.Register([]bedrockagentTypes.AgentCollaboratorSummary{}) + gob.Register(bedrockagentTypes.Agent{}) + gob.Register(&bedrockagentTypes.AgentActionGroup{}) + gob.Register(&bedrockagentTypes.ActionGroupExecutorMemberLambda{}) + gob.Register(&bedrockagentTypes.ActionGroupExecutorMemberCustomControl{}) + gob.Register(&bedrockagentTypes.APISchemaMemberPayload{}) + gob.Register(&bedrockagentTypes.APISchemaMemberS3{}) + gob.Register(&bedrockagentTypes.FunctionSchemaMemberFunctions{}) +} + +func CachedBedrockAgentListAgents(client BedrockAgentClientInterface, accountID string, region string) ([]bedrockagentTypes.AgentSummary, error) { + var PaginationControl *string + var agents []bedrockagentTypes.AgentSummary + cacheKey := fmt.Sprintf("%s-bedrockagent-ListAgents-%s", accountID, region) + cached, found := internal.Cache.Get(cacheKey) + if found { + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgents", + "account": accountID, + "region": region, + "cache": "hit", + }).Info("AWS API call") + return cached.([]bedrockagentTypes.AgentSummary), nil + } + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgents", + "account": accountID, + "region": region, + "cache": "miss", + }).Info("AWS API call") + + for { + ListAgents, err := client.ListAgents( + context.TODO(), + &bedrockagent.ListAgentsInput{ + NextToken: PaginationControl, + }, + func(o *bedrockagent.Options) { + o.Region = region + }, + ) + if err != nil { + return agents, err + } + + agents = append(agents, ListAgents.AgentSummaries...) + + if ListAgents.NextToken == nil { + break + } + PaginationControl = ListAgents.NextToken + } + internal.Cache.Set(cacheKey, agents, cache.DefaultExpiration) + + return agents, nil +} + +func CachedBedrockAgentListAgentAliases(client BedrockAgentClientInterface, accountID string, region string, agentID string) ([]bedrockagentTypes.AgentAliasSummary, error) { + var PaginationControl *string + var aliases []bedrockagentTypes.AgentAliasSummary + cacheKey := fmt.Sprintf("%s-bedrockagent-ListAgentAliases-%s-%s", accountID, region, agentID) + cached, found := internal.Cache.Get(cacheKey) + if found { + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgentAliases", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "hit", + }).Info("AWS API call") + return cached.([]bedrockagentTypes.AgentAliasSummary), nil + } + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgentAliases", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "miss", + }).Info("AWS API call") + + for { + ListAliases, err := client.ListAgentAliases( + context.TODO(), + &bedrockagent.ListAgentAliasesInput{ + AgentId: &agentID, + NextToken: PaginationControl, + }, + func(o *bedrockagent.Options) { + o.Region = region + }, + ) + if err != nil { + return aliases, err + } + + aliases = append(aliases, ListAliases.AgentAliasSummaries...) + + if ListAliases.NextToken == nil { + break + } + PaginationControl = ListAliases.NextToken + } + internal.Cache.Set(cacheKey, aliases, cache.DefaultExpiration) + + return aliases, nil +} + +func CachedBedrockAgentListAgentActionGroups(client BedrockAgentClientInterface, accountID string, region string, agentID string, agentVersion string) ([]bedrockagentTypes.ActionGroupSummary, error) { + var PaginationControl *string + var actionGroups []bedrockagentTypes.ActionGroupSummary + cacheKey := fmt.Sprintf("%s-bedrockagent-ListAgentActionGroups-%s-%s", accountID, region, agentID) + cached, found := internal.Cache.Get(cacheKey) + if found { + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgentActionGroups", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "hit", + }).Info("AWS API call") + return cached.([]bedrockagentTypes.ActionGroupSummary), nil + } + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgentActionGroups", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "miss", + }).Info("AWS API call") + + for { + ListActionGroups, err := client.ListAgentActionGroups( + context.TODO(), + &bedrockagent.ListAgentActionGroupsInput{ + AgentId: &agentID, + AgentVersion: &agentVersion, + NextToken: PaginationControl, + }, + func(o *bedrockagent.Options) { + o.Region = region + }, + ) + if err != nil { + return actionGroups, err + } + + actionGroups = append(actionGroups, ListActionGroups.ActionGroupSummaries...) + + if ListActionGroups.NextToken == nil { + break + } + PaginationControl = ListActionGroups.NextToken + } + internal.Cache.Set(cacheKey, actionGroups, cache.DefaultExpiration) + + return actionGroups, nil +} + +func CachedBedrockAgentListAgentCollaborators(client BedrockAgentClientInterface, accountID string, region string, agentID string, agentVersion string) ([]bedrockagentTypes.AgentCollaboratorSummary, error) { + var PaginationControl *string + var collaborators []bedrockagentTypes.AgentCollaboratorSummary + cacheKey := fmt.Sprintf("%s-bedrockagent-ListAgentCollaborators-%s-%s", accountID, region, agentID) + cached, found := internal.Cache.Get(cacheKey) + if found { + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgentCollaborators", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "hit", + }).Info("AWS API call") + return cached.([]bedrockagentTypes.AgentCollaboratorSummary), nil + } + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:ListAgentCollaborators", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "miss", + }).Info("AWS API call") + + for { + ListCollaborators, err := client.ListAgentCollaborators( + context.TODO(), + &bedrockagent.ListAgentCollaboratorsInput{ + AgentId: &agentID, + AgentVersion: &agentVersion, + NextToken: PaginationControl, + }, + func(o *bedrockagent.Options) { + o.Region = region + }, + ) + if err != nil { + return collaborators, err + } + + collaborators = append(collaborators, ListCollaborators.AgentCollaboratorSummaries...) + + if ListCollaborators.NextToken == nil { + break + } + PaginationControl = ListCollaborators.NextToken + } + internal.Cache.Set(cacheKey, collaborators, cache.DefaultExpiration) + + return collaborators, nil +} + +func CachedBedrockAgentGetAgent(client BedrockAgentClientInterface, accountID string, region string, agentID string) (bedrockagentTypes.Agent, error) { + var agent bedrockagentTypes.Agent + cacheKey := fmt.Sprintf("%s-bedrockagent-GetAgent-%s-%s", accountID, region, agentID) + cached, found := internal.Cache.Get(cacheKey) + if found { + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:GetAgent", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "hit", + }).Info("AWS API call") + return cached.(bedrockagentTypes.Agent), nil + } + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:GetAgent", + "account": accountID, + "region": region, + "agent": agentID, + "cache": "miss", + }).Info("AWS API call") + + resp, err := client.GetAgent( + context.TODO(), + &bedrockagent.GetAgentInput{ + AgentId: &agentID, + }, + func(o *bedrockagent.Options) { + o.Region = region + }, + ) + if err != nil { + return agent, err + } + agent = *resp.Agent + internal.Cache.Set(cacheKey, agent, cache.DefaultExpiration) + + return agent, nil +} + +func CachedBedrockAgentGetAgentActionGroup(client BedrockAgentClientInterface, accountID string, region string, agentID string, agentVersion string, actionGroupID string) (*bedrockagentTypes.AgentActionGroup, error) { + cacheKey := fmt.Sprintf("%s-bedrockagent-GetAgentActionGroup-%s-%s-%s", accountID, region, agentID, actionGroupID) + cached, found := internal.Cache.Get(cacheKey) + if found { + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:GetAgentActionGroup", + "account": accountID, + "region": region, + "agent": agentID, + "actionGroup": actionGroupID, + "cache": "hit", + }).Info("AWS API call") + return cached.(*bedrockagentTypes.AgentActionGroup), nil + } + sharedLogger.WithFields(logrus.Fields{ + "api": "bedrockagent:GetAgentActionGroup", + "account": accountID, + "region": region, + "agent": agentID, + "actionGroup": actionGroupID, + "cache": "miss", + }).Info("AWS API call") + + resp, err := client.GetAgentActionGroup( + context.TODO(), + &bedrockagent.GetAgentActionGroupInput{ + AgentId: &agentID, + AgentVersion: &agentVersion, + ActionGroupId: &actionGroupID, + }, + func(o *bedrockagent.Options) { + o.Region = region + }, + ) + if err != nil { + return nil, err + } + internal.Cache.Set(cacheKey, resp.AgentActionGroup, cache.DefaultExpiration) + + return resp.AgentActionGroup, nil +} diff --git a/aws/sdk/bedrockagent_mocks.go b/aws/sdk/bedrockagent_mocks.go new file mode 100644 index 00000000..7d3d7213 --- /dev/null +++ b/aws/sdk/bedrockagent_mocks.go @@ -0,0 +1,151 @@ +package sdk + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/bedrockagent" + bedrockagentTypes "github.com/aws/aws-sdk-go-v2/service/bedrockagent/types" +) + +type MockedBedrockAgentClient struct{} + +func (m *MockedBedrockAgentClient) ListAgents(ctx context.Context, input *bedrockagent.ListAgentsInput, options ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentsOutput, error) { + return &bedrockagent.ListAgentsOutput{ + AgentSummaries: []bedrockagentTypes.AgentSummary{ + { + AgentId: aws.String("AGENT001"), + AgentName: aws.String("LabAgent01"), + AgentStatus: bedrockagentTypes.AgentStatusPrepared, + LatestAgentVersion: aws.String("1"), + }, + { + AgentId: aws.String("AGENT002"), + AgentName: aws.String("ResearchWorker01"), + AgentStatus: bedrockagentTypes.AgentStatusPrepared, + LatestAgentVersion: aws.String("1"), + }, + }, + }, nil +} + +func (m *MockedBedrockAgentClient) GetAgent(ctx context.Context, input *bedrockagent.GetAgentInput, options ...func(*bedrockagent.Options)) (*bedrockagent.GetAgentOutput, error) { + agents := map[string]*bedrockagent.GetAgentOutput{ + "AGENT001": { + Agent: &bedrockagentTypes.Agent{ + AgentId: aws.String("AGENT001"), + AgentName: aws.String("LabAgent01"), + AgentArn: aws.String("arn:aws:bedrock:us-east-1:123456789012:agent/AGENT001"), + AgentStatus: bedrockagentTypes.AgentStatusPrepared, + FoundationModel: aws.String("us.anthropic.claude-sonnet-4-6"), + AgentResourceRoleArn: aws.String("arn:aws:iam::123456789012:role/AgentExecutionRole-Lab"), + Instruction: aws.String("You are a helpful order management assistant."), + IdleSessionTTLInSeconds: aws.Int32(600), + }, + }, + "AGENT002": { + Agent: &bedrockagentTypes.Agent{ + AgentId: aws.String("AGENT002"), + AgentName: aws.String("ResearchWorker01"), + AgentArn: aws.String("arn:aws:bedrock:us-east-1:123456789012:agent/AGENT002"), + AgentStatus: bedrockagentTypes.AgentStatusPrepared, + FoundationModel: aws.String("us.anthropic.claude-sonnet-4-6"), + AgentResourceRoleArn: aws.String("arn:aws:iam::123456789012:role/WorkerExecutionRole-Lab"), + Instruction: aws.String("You are a read-only research agent."), + IdleSessionTTLInSeconds: aws.Int32(300), + }, + }, + } + if out, ok := agents[aws.ToString(input.AgentId)]; ok { + return out, nil + } + return agents["AGENT001"], nil +} + +func (m *MockedBedrockAgentClient) ListAgentAliases(ctx context.Context, input *bedrockagent.ListAgentAliasesInput, options ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentAliasesOutput, error) { + return &bedrockagent.ListAgentAliasesOutput{ + AgentAliasSummaries: []bedrockagentTypes.AgentAliasSummary{ + { + AgentAliasId: aws.String("ALIAS001"), + AgentAliasName: aws.String("lab-v1"), + }, + }, + }, nil +} + +func (m *MockedBedrockAgentClient) ListAgentActionGroups(ctx context.Context, input *bedrockagent.ListAgentActionGroupsInput, options ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentActionGroupsOutput, error) { + return &bedrockagent.ListAgentActionGroupsOutput{ + ActionGroupSummaries: []bedrockagentTypes.ActionGroupSummary{ + { + ActionGroupId: aws.String("AG001"), + ActionGroupName: aws.String("OrderLookupActionGroup"), + ActionGroupState: bedrockagentTypes.ActionGroupStateEnabled, + }, + }, + }, nil +} + +func (m *MockedBedrockAgentClient) GetAgentActionGroup(ctx context.Context, input *bedrockagent.GetAgentActionGroupInput, options ...func(*bedrockagent.Options)) (*bedrockagent.GetAgentActionGroupOutput, error) { + return &bedrockagent.GetAgentActionGroupOutput{ + AgentActionGroup: &bedrockagentTypes.AgentActionGroup{ + ActionGroupId: aws.String("AG001"), + ActionGroupName: aws.String("OrderLookupActionGroup"), + ActionGroupState: bedrockagentTypes.ActionGroupStateEnabled, + AgentId: input.AgentId, + AgentVersion: input.AgentVersion, + ActionGroupExecutor: &bedrockagentTypes.ActionGroupExecutorMemberLambda{ + Value: "arn:aws:lambda:us-east-1:123456789012:function:order_lookup_fn", + }, + Description: aws.String("Looks up order status by order ID"), + FunctionSchema: &bedrockagentTypes.FunctionSchemaMemberFunctions{ + Value: []bedrockagentTypes.Function{ + { + Name: aws.String("lookupOrder"), + Description: aws.String("Look up an order by its ID"), + Parameters: map[string]bedrockagentTypes.ParameterDetail{ + "orderId": { + Type: bedrockagentTypes.TypeString, + Description: aws.String("The order identifier"), + Required: aws.Bool(true), + }, + }, + }, + }, + }, + }, + }, nil +} + +func (m *MockedBedrockAgentClient) ListAgentCollaborators(ctx context.Context, input *bedrockagent.ListAgentCollaboratorsInput, options ...func(*bedrockagent.Options)) (*bedrockagent.ListAgentCollaboratorsOutput, error) { + if aws.ToString(input.AgentId) == "AGENT001" { + return &bedrockagent.ListAgentCollaboratorsOutput{ + AgentCollaboratorSummaries: []bedrockagentTypes.AgentCollaboratorSummary{ + { + AgentDescriptor: &bedrockagentTypes.AgentDescriptor{ + AliasArn: aws.String("arn:aws:bedrock:us-east-1:123456789012:agent-alias/AGENT002/ALIAS002"), + }, + CollaboratorId: aws.String("COLLAB001"), + CollaboratorName: aws.String("ResearchWorker01"), + RelayConversationHistory: bedrockagentTypes.RelayConversationHistoryDisabled, + }, + }, + }, nil + } + return &bedrockagent.ListAgentCollaboratorsOutput{ + AgentCollaboratorSummaries: []bedrockagentTypes.AgentCollaboratorSummary{}, + }, nil +} + +func (m *MockedBedrockAgentClient) GetAgentCollaborator(ctx context.Context, input *bedrockagent.GetAgentCollaboratorInput, options ...func(*bedrockagent.Options)) (*bedrockagent.GetAgentCollaboratorOutput, error) { + return &bedrockagent.GetAgentCollaboratorOutput{ + AgentCollaborator: &bedrockagentTypes.AgentCollaborator{ + AgentDescriptor: &bedrockagentTypes.AgentDescriptor{ + AliasArn: aws.String("arn:aws:bedrock:us-east-1:123456789012:agent-alias/AGENT002/ALIAS002"), + }, + CollaboratorId: aws.String("COLLAB001"), + CollaboratorName: aws.String("ResearchWorker01"), + CollaborationInstruction: aws.String("Route research and read-only queries to this worker"), + RelayConversationHistory: bedrockagentTypes.RelayConversationHistoryDisabled, + }, + }, nil +} diff --git a/cli/aws.go b/cli/aws.go index d1646708..cd263691 100644 --- a/cli/aws.go +++ b/cli/aws.go @@ -13,6 +13,7 @@ import ( "github.com/BishopFox/cloudfox/aws/sdk" "github.com/BishopFox/cloudfox/internal" "github.com/BishopFox/cloudfox/internal/common" + "github.com/aws/aws-sdk-go-v2/service/bedrockagent" "github.com/aws/aws-sdk-go-v2/service/apigateway" "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" "github.com/aws/aws-sdk-go-v2/service/apprunner" @@ -103,6 +104,17 @@ var ( }, } + BedrockAgentsCommand = &cobra.Command{ + Use: "bedrock-agents", + Aliases: []string{"bedrock-agent", "agents"}, + Short: "Enumerate Bedrock agents, action groups, collaborators, and aliases", + Long: "\nUse case examples:\n" + + os.Args[0] + " aws bedrock-agents --profile readonly_profile", + PreRun: awsPreRun, + Run: runBedrockAgentsCommand, + PostRun: awsPostRun, + } + AccessKeysFilter string AccessKeysCommand = &cobra.Command{ Use: "access-keys", @@ -1796,6 +1808,32 @@ func runSecretsCommand(cmd *cobra.Command, args []string) { } } +func runBedrockAgentsCommand(cmd *cobra.Command, args []string) { + for _, profile := range AWSProfiles { + sharedServiceMap := &awsservicemap.AwsServiceMap{ + JsonFileSource: "DOWNLOAD_FROM_AWS", + } + var AWSConfig = internal.AWSConfigFileLoader(profile, cmd.Root().Version, AWSMFAToken) + caller, err := internal.AWSWhoami(profile, cmd.Root().Version, AWSMFAToken) + if err != nil { + continue + } + m := aws.BedrockAgentsModule{ + BedrockAgentClient: bedrockagent.NewFromConfig(AWSConfig), + + Caller: *caller, + AWSRegions: internal.GetEnabledRegions(profile, cmd.Root().Version, AWSMFAToken), + AWSProfile: profile, + Goroutines: Goroutines, + WrapTable: AWSWrapTable, + AWSOutputType: AWSOutputType, + AWSTableCols: AWSTableCols, + ServiceMap: sharedServiceMap, + } + m.PrintBedrockAgents(AWSOutputDirectory, Verbosity) + } +} + func runTagsCommand(cmd *cobra.Command, args []string) { for _, profile := range AWSProfiles { var AWSConfig = internal.AWSConfigFileLoader(profile, cmd.Root().Version, AWSMFAToken) @@ -1971,6 +2009,7 @@ func runAllChecksCommand(cmd *cobra.Command, args []string) { apiGatewayClient := apigateway.NewFromConfig(AWSConfig) apiGatewayv2Client := apigatewayv2.NewFromConfig(AWSConfig) appRunnerClient := apprunner.NewFromConfig(AWSConfig) + bedrockAgentClient := bedrockagent.NewFromConfig(AWSConfig) athenaClient := athena.NewFromConfig(AWSConfig) cloud9Client := cloud9.NewFromConfig(AWSConfig) cloudFormationClient := cloudformation.NewFromConfig(AWSConfig) @@ -2306,6 +2345,18 @@ func runAllChecksCommand(cmd *cobra.Command, args []string) { } buckets.PrintBuckets(AWSOutputDirectory, Verbosity) + bedrockAgents := aws.BedrockAgentsModule{ + BedrockAgentClient: bedrockAgentClient, + Caller: *caller, + AWSRegions: internal.GetEnabledRegions(profile, cmd.Root().Version, AWSMFAToken), + AWSProfile: profile, + Goroutines: Goroutines, + WrapTable: AWSWrapTable, + AWSOutputType: AWSOutputType, + AWSTableCols: AWSTableCols, + } + bedrockAgents.PrintBedrockAgents(AWSOutputDirectory, Verbosity) + ecr := aws.ECRModule{ ECRClient: ecrClient, Caller: *caller, @@ -2558,6 +2609,7 @@ func init() { AWSCommands.AddCommand( AccessKeysCommand, AllChecksCommand, + BedrockAgentsCommand, ApiGwCommand, BucketsCommand, CapeCommand, diff --git a/go.mod b/go.mod index 6d3e9e7e..cae64a5f 100644 --- a/go.mod +++ b/go.mod @@ -16,13 +16,14 @@ require ( github.com/Azure/go-autorest/autorest v0.11.30 github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 github.com/aquasecurity/table v1.11.0 - github.com/aws/aws-sdk-go-v2 v1.41.5 + github.com/aws/aws-sdk-go-v2 v1.42.0 github.com/aws/aws-sdk-go-v2/config v1.32.5 github.com/aws/aws-sdk-go-v2/credentials v1.19.5 github.com/aws/aws-sdk-go-v2/service/apigateway v1.38.3 github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.33.4 github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9 github.com/aws/aws-sdk-go-v2/service/athena v1.56.4 + github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.54.6 github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15 github.com/aws/aws-sdk-go-v2/service/cloudformation v1.71.4 github.com/aws/aws-sdk-go-v2/service/cloudfront v1.58.3 @@ -68,7 +69,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sqs v1.42.20 github.com/aws/aws-sdk-go-v2/service/ssm v1.67.7 github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 - github.com/aws/smithy-go v1.24.2 + github.com/aws/smithy-go v1.27.1 github.com/bishopfox/awsservicemap v1.1.0 github.com/bishopfox/knownawsaccountslookup v0.0.0-20231228165844-c37ef8df33cb github.com/dominikbraun/graph v0.23.0 @@ -170,8 +171,8 @@ require ( github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect diff --git a/go.sum b/go.sum index cce23aea..d28dbd42 100644 --- a/go.sum +++ b/go.sum @@ -116,6 +116,8 @@ github.com/aquasecurity/table v1.11.0 h1:SzgCAv7dZcv/gyAyzxorS6OgEk7w/WU5iT2pStI github.com/aquasecurity/table v1.11.0/go.mod h1:eqOmvjjB7AhXFgFqpJUEE/ietg7RrMSJZXyTN8E/wZw= github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2 v1.42.0 h1:XvXMJTkFQtpBKIWZnmr9ZEOc2InWM2yldjXEJ/bymhA= +github.com/aws/aws-sdk-go-v2 v1.42.0/go.mod h1:27+ACypSLljLAEKsCYOmrjKh83vuTRkuAe9Uv/3A4bg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= github.com/aws/aws-sdk-go-v2/config v1.32.5 h1:pz3duhAfUgnxbtVhIK39PGF/AHYyrzGEyRD9Og0QrE8= @@ -126,8 +128,12 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 h1:80+uETIWS1BqjnN9uJ0dBU github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16/go.mod h1:wOOsYuxYuB/7FlnVtzeBYRcjSRtQpAW0hCP7tIULMwo= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 h1:f3vKqSo13fhTYb+JEcXwXefZQE26I1FB5eTSniU67ko= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29/go.mod h1:MzoLFUArKGpGD+ukmPiTPG1X5x4o6M2kq4v2dr1FiEc= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 h1:RdwIf/CuUsvJX3RgJagbOyotl/cxoLY4xviKuE7p2GY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29/go.mod h1:71wt8W2EgswdZy9Mf9KNnzxZ3TiZlv4caKghPktDOkA= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= @@ -140,6 +146,8 @@ github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9 h1:3MgcobMoBK3IqP2TbuySbd github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9/go.mod h1:n6b+O7QJ6E37dXZYPdLnC4S7Cc5HUYOQPZijLeDKIGY= github.com/aws/aws-sdk-go-v2/service/athena v1.56.4 h1:kCHAYlcGKCKKDGMRUfnY6pI992vC3UdA3+oPdfDBSHE= github.com/aws/aws-sdk-go-v2/service/athena v1.56.4/go.mod h1:Whob/cKMykIKxGMQVhPhGEC1+D+bgEDOL7brjSB4ju8= +github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.54.6 h1:4Z9EIZUF8dkVDYTEt7NxKhA3yE3S/x7iWYL/C+reRgw= +github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.54.6/go.mod h1:GlwXK7c/0CMTSU4a0PAAp5jiYXH55DRYT3mliKlqf6M= github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15 h1:VKLLGKz1jfsQMf/tCjqiqzwha+5n8bcndAqH4/yMJEk= github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15/go.mod h1:6eUG6qcUwAACFF/b0fIlZF0sSUwRwY2yJaJ0KoRNjF8= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.71.4 h1:9dwMueqbHIp0KTw2Zt0rhVobiPMlAI8UgyxiaBzM+1E= @@ -250,6 +258,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk= github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/smithy-go v1.27.1 h1:4T340VFndXtADGF52gYa1POyL7s9E4Z1OeZ1hCscIw8= +github.com/aws/smithy-go v1.27.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= From 56ab2f3c10d4cc86d51e55d48246e7965b06c086 Mon Sep 17 00:00:00 2001 From: Vecto0rdecay Date: Wed, 17 Jun 2026 10:04:00 -0400 Subject: [PATCH 2/2] Remove bedrock-agents from all-checks command This module should be run standalone, not as part of all-checks. --- cli/aws.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/cli/aws.go b/cli/aws.go index cd263691..57b9c133 100644 --- a/cli/aws.go +++ b/cli/aws.go @@ -2009,7 +2009,6 @@ func runAllChecksCommand(cmd *cobra.Command, args []string) { apiGatewayClient := apigateway.NewFromConfig(AWSConfig) apiGatewayv2Client := apigatewayv2.NewFromConfig(AWSConfig) appRunnerClient := apprunner.NewFromConfig(AWSConfig) - bedrockAgentClient := bedrockagent.NewFromConfig(AWSConfig) athenaClient := athena.NewFromConfig(AWSConfig) cloud9Client := cloud9.NewFromConfig(AWSConfig) cloudFormationClient := cloudformation.NewFromConfig(AWSConfig) @@ -2345,18 +2344,6 @@ func runAllChecksCommand(cmd *cobra.Command, args []string) { } buckets.PrintBuckets(AWSOutputDirectory, Verbosity) - bedrockAgents := aws.BedrockAgentsModule{ - BedrockAgentClient: bedrockAgentClient, - Caller: *caller, - AWSRegions: internal.GetEnabledRegions(profile, cmd.Root().Version, AWSMFAToken), - AWSProfile: profile, - Goroutines: Goroutines, - WrapTable: AWSWrapTable, - AWSOutputType: AWSOutputType, - AWSTableCols: AWSTableCols, - } - bedrockAgents.PrintBedrockAgents(AWSOutputDirectory, Verbosity) - ecr := aws.ECRModule{ ECRClient: ecrClient, Caller: *caller,