Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security solution] AWS Bedrock connector #166662

Merged
merged 54 commits into from
Sep 27, 2023
Merged

Conversation

stephmilovic
Copy link
Contributor

@stephmilovic stephmilovic commented Sep 18, 2023

Summary

New Generative AI connector to support AWS Bedrock. This change will need name change follow up as described here: #166960

Implemented with the sub actions framework. The actions are runApi and invokeAI. runApi is the action attached to the test sub action. runApi is responsible for making a POST request to the Bedrock API endpoint and returning the response data. This is an example payload of what Bedrock is expecting:

{
  "prompt": "\n\Human: Hello world! \n\nAssistant:",
  "max_tokens_to_sample": 300,
  "stop_sequences": ["\n\nAssistant:"],
}

Create connector

Screenshot 2023-09-21 at 4 05 48 PM Screenshot 2023-09-21 at 4 06 16 PM

Test connector

Screenshot 2023-09-21 at 4 07 24 PM

Testing for ResponseOps team

My apologies for doing this all in one PR. Hopefully clear testing expectations will win me points back?
Bedrock credentials
ResponseOps should test that a connector can be created and tested from the Stack Management > Connectors page

  1. Create Bedrock connectors with Bedrock credentials
  2. Test the connector by sending example payload
  3. Confirm results in Network tab. Should look like:
    Screenshot 2023-09-21 at 4 10 47 PM

Testing for Security Solution team

Bedrock credentials
Security Solution should test that a connectors can be created 3 places within the AI assistant, that multiple connectors can be used in a single conversation, and that the connectors work with both Langchain and non-langchain:

  1. Start fresh with no connectors and a cleared local storage (no conversation history)
  2. Through the welcome conversation, create a Bedrock connector using the button in the conversation:
Screenshot 2023-09-21 at 4 14 15 PM Screenshot 2023-09-21 at 4 14 25 PM Screenshot 2023-09-21 at 4 14 59 PM
  1. Send a message to confirm the connection
  2. Create another Bedrock connector from the top left connector selector
Screenshot 2023-09-21 at 4 17 14 PM
  1. Create an OpenAI/GenA connector from the settings
Screenshot 2023-09-21 at 4 16 10 PM
  1. Ensure that the connectors are listed with the proper description:
Screenshot 2023-09-20 at 11 55 31 AM
  1. Switch between connectors and have a chat with each, ensure that we can switch between Bedrock and OpenAI without issues
  2. If you've had the setting assistantLangChain={false}, switch it to true or vice versa. You do not need to test the connector creation with langchain and non-langchain, but test sending messages with both langchain and non-langchain to both connector types

@stephmilovic stephmilovic added release_note:enhancement WIP Work in progress Team:Threat Hunting Security Solution Threat Hunting Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. v8.11.0 labels Sep 18, 2023
@@ -838,6 +838,7 @@
"antlr4ts": "^0.5.0-alpha.3",
"archiver": "^5.3.1",
"async": "^3.2.3",
"aws4": "^1.12.0",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to add aws4 module in order to sign requests to new AWS Bedrock connector. https://www.npmjs.com/package/aws4

Copy link
Contributor

@ymao1 ymao1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Response Ops LGTM! Left a few minor nits but overall looks great.

) => {
try {
assertURL(configObject.apiUrl);
urlAllowListValidator('apiUrl')(configObject, validatorServices);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the region always a part of the apiUrl? Is it worth doing any validation that the apiUrl includes the specified region?

Copy link
Contributor Author

@stephmilovic stephmilovic Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so i was playing around with the signature yesterday to see if I really needed to send all those arguments and discovered that i can omit method, service and region and still have successful results.

Screenshot 2023-09-26 at 10 02 24 AM

Looks like they can correctly infer the values from RequestSigner.matchHost().Therefore, I think it would be ok to omit the region from the config. WDYT?

FYI, I still need to send host, it seems the RequestSigner.createHost() does not get us what we need, here is the error:

Message: Unexpected API Error: ERR_TLS_CERT_ALTNAME_INVALID - Hostname/IP does not match certificate's altnames: Host: .us-east-1.amazonaws.com. is not in the cert's altnames: DNS:bedrock.us-east-1.amazonaws.com

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if we can omit the region from the connector config, that'd be great. Less chance of user error entering a region that doesn't match the api url

const variables = { domain: 'm0zepcuuu2' };

describe('Bedrock - renderParameterTemplates', () => {
it('should not render body on test action', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in render, you're returning if the subaction doesn't equal run or test, so I'm not sure what the correct behavior is? This test passes because you're using test but no template to render in the param body

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh I'm not sure I understand the purpose of renderParameterTemplates, I was following other connector types... in case there are mustache variables used in the test/run json form?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renderParameterTemplates is an optional function that you can register with the connector type if you need special escaping for some of the parameter values, typically while running or testing the action. This function as is is saying to only use this function for the run or test subaction and to not worry about mustache templating for any of the other subactions. Maybe you want to change it so it only renders the mustache templates during the run subaction? Then this unit test would make sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test and run action are the same

export type BedrockConfig = TypeOf<typeof BedrockConfigSchema>;
export type BedrockSecrets = TypeOf<typeof BedrockSecretsSchema>;
export type BedrockRunActionParams = TypeOf<typeof BedrockRunActionParamsSchema>;
export type InvokeAIActionParams = TypeOf<typeof InvokeAIActionParamsSchema>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: BedrockInvokeAIActionParams and BedrockInvokeAIActionResponse for consistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -23,7 +23,7 @@ export function getConnectorType(): GenerativeAiConnector {
selectMessage: i18n.translate('xpack.stackConnectors.components.genAi.selectMessageText', {
defaultMessage: 'Send a request to generative AI systems.',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be Send a request to Open AI systems?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to fix all the language/naming in a follow up: #166960

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can preview that PR here: stephmilovic#12

I will reopen against main once this PR is merged

return 'Unauthorized API Error';
}
return `API Error: ${error.response?.status} - ${error.response?.statusText}${
error.response?.data?.error?.message ? ` - ${error.response.data.error?.message}` : ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I use an invalid model, right now it just returns Error: Status code: 400. Message: API Error: 400 - Bad Request but there is a more informative error message inside error.response.data.message that would be useful The provided model identifier is invalid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely, i kind of breezed over error handling because I have another ticket to clean it up in GenAI connector so I was going to handle all of that at once if that is ok? https://github.com/elastic/security-team/issues/7373

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the preview of that PR: stephmilovic#13

I will reopen against main once this PR + stephmilovic#12 are merged

@stephmilovic
Copy link
Contributor Author

@elasticmachine merge upstream

@stephmilovic
Copy link
Contributor Author

@elasticmachine merge upstream

@stephmilovic
Copy link
Contributor Author

@elasticmachine merge upstream

@stephmilovic
Copy link
Contributor Author

@elasticmachine merge upstream

@stephmilovic
Copy link
Contributor Author

@elasticmachine merge upstream

@kibana-ci
Copy link
Collaborator

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #59 / serverless observability UI landing page "before all" hook for "has quickstart badge"

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
securitySolution 4549 4550 +1
stackConnectors 239 247 +8
total +9

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
securitySolution 12.8MB 12.8MB -4.5KB
stackConnectors 467.0KB 485.4KB +18.4KB
total +13.8KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
stackConnectors 36.5KB 37.8KB +1.3KB
Unknown metric groups

async chunk count

id before after diff
stackConnectors 71 75 +4

ESLint disabled line counts

id before after diff
@kbn/elastic-assistant 19 18 -1
elasticAssistant 18 10 -8
stackConnectors 94 98 +4
total -5

Total ESLint disabled count

id before after diff
@kbn/elastic-assistant 20 19 -1
elasticAssistant 18 10 -8
stackConnectors 99 103 +4
total -5

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting release_note:enhancement Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Team:Threat Hunting Security Solution Threat Hunting Team v8.11.0
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

8 participants