Skip to content

Commit acbbea3

Browse files
authored
Merge pull request #3 from aws-ia/v0.0.1
V0.0.1
2 parents 7d08228 + bd4f014 commit acbbea3

File tree

10 files changed

+184
-7
lines changed

10 files changed

+184
-7
lines changed

.header.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,19 @@ Integrate Amazon Bedrock to your HashiCorp Cloud Platform Terraform (Terraform C
1010

1111
### Terraform plan summary
1212

13+
Summarize Terraform plan output in human friendly natural language.
1314
![Example](./images/example.png)
1415

1516
### Function calling (AMI analysis)
1617

18+
Use function calling to execute other tools, such as analyzing AMI data.
1719
![Example2](./images/example2.png)
1820

21+
### Responsible AI
22+
23+
Implement safeguards using Amazon Bedrock guardrails customized to your organization requirements and responsible AI policies
24+
![Example3](./images/example3.png)
25+
1926
## Architecture
2027

2128
![Diagram](./images/arch.png)
@@ -29,6 +36,7 @@ Please refer to the [best-practice](#best-practice) section below for more detai
2936
To use this module you need have the following:
3037

3138
1. AWS account and credentials
39+
1. Amazon Bedrock model access (default model is `Claude 3 Sonnet`)
3240
1. HCP Terraform account
3341

3442
## Usage
@@ -39,6 +47,8 @@ To use this module you need have the following:
3947
make all
4048
```
4149

50+
* Enable Bedrock model access for `Claude 3 Sonnet`. Refer to [this guide for more info](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html).
51+
4252
* Reference the `examples/basic` folder on how to use this module
4353

4454
```sh
@@ -57,3 +67,5 @@ To use this module you need have the following:
5767
* Enable the AWS WAF setup by setting variable `deploy_waf` to `true` (additional cost will apply). This will add WAF protection to the Run Tasks URL endpoint.
5868

5969
* We recommend you to setup additional CloudWatch alarm to monitor Lambda concurrency and WAF rules.
70+
71+
* We recommend to add additional topic to the Bedrock Guardrail to fit your organization requirements.

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,19 @@ Integrate Amazon Bedrock to your HashiCorp Cloud Platform Terraform (Terraform C
1111

1212
### Terraform plan summary
1313

14+
Summarize Terraform plan output in human friendly natural language.
1415
![Example](./images/example.png)
1516

1617
### Function calling (AMI analysis)
1718

19+
Use function calling to execute other tools, such as analyzing AMI data.
1820
![Example2](./images/example2.png)
1921

22+
### Responsible AI
23+
24+
Implement safeguards using Amazon Bedrock guardrails customized to your organization requirements and responsible AI policies
25+
![Example3](./images/example3.png)
26+
2027
## Architecture
2128

2229
![Diagram](./images/arch.png)
@@ -30,6 +37,7 @@ Please refer to the [best-practice](#best-practice) section below for more detai
3037
To use this module you need have the following:
3138

3239
1. AWS account and credentials
40+
1. Amazon Bedrock model access (default model is `Claude 3 Sonnet`)
3341
1. HCP Terraform account
3442

3543
## Usage
@@ -40,6 +48,8 @@ To use this module you need have the following:
4048
make all
4149
```
4250

51+
* Enable Bedrock model access for `Claude 3 Sonnet`. Refer to [this guide for more info](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html).
52+
4353
* Reference the `examples/basic` folder on how to use this module
4454

4555
```sh
@@ -59,13 +69,16 @@ To use this module you need have the following:
5969

6070
* We recommend you to setup additional CloudWatch alarm to monitor Lambda concurrency and WAF rules.
6171

72+
* We recommend to add additional topic to the Bedrock Guardrail to fit your organization requirements.
73+
6274
## Requirements
6375

6476
| Name | Version |
6577
|------|---------|
6678
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.0 |
6779
| <a name="requirement_archive"></a> [archive](#requirement\_archive) | ~>2.2.0 |
6880
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.47.0 |
81+
| <a name="requirement_awscc"></a> [awscc](#requirement\_awscc) | >= 1.11.0 |
6982
| <a name="requirement_random"></a> [random](#requirement\_random) | >=3.4.0 |
7083

7184
## Providers
@@ -75,6 +88,7 @@ To use this module you need have the following:
7588
| <a name="provider_archive"></a> [archive](#provider\_archive) | ~>2.2.0 |
7689
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.47.0 |
7790
| <a name="provider_aws.cloudfront_waf"></a> [aws.cloudfront\_waf](#provider\_aws.cloudfront\_waf) | >= 5.47.0 |
91+
| <a name="provider_awscc"></a> [awscc](#provider\_awscc) | >= 1.11.0 |
7892
| <a name="provider_random"></a> [random](#provider\_random) | >=3.4.0 |
7993
| <a name="provider_terraform"></a> [terraform](#provider\_terraform) | n/a |
8094
| <a name="provider_time"></a> [time](#provider\_time) | n/a |
@@ -136,6 +150,8 @@ To use this module you need have the following:
136150
| [aws_sfn_state_machine.runtask_states](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sfn_state_machine) | resource |
137151
| [aws_wafv2_web_acl.runtask_waf](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl) | resource |
138152
| [aws_wafv2_web_acl_logging_configuration.runtask_waf](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_logging_configuration) | resource |
153+
| [awscc_bedrock_guardrail.runtask_fulfillment](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/bedrock_guardrail) | resource |
154+
| [awscc_bedrock_guardrail_version.runtask_fulfillment](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/bedrock_guardrail_version) | resource |
139155
| [random_string.solution_prefix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource |
140156
| [random_uuid.runtask_cloudfront](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |
141157
| [random_uuid.runtask_hmac](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.0.0
1+
v0.0.1

bedrock.tf

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
resource "awscc_bedrock_guardrail" "runtask_fulfillment" {
2+
name = "${local.solution_prefix}-guardrail"
3+
blocked_input_messaging = "Unfortunately we are unable to provide response for this input"
4+
blocked_outputs_messaging = "Unfortunately we are unable to provide response for this input"
5+
description = "Basic Bedrock Guardrail for sensitive info exfiltration"
6+
7+
# detect and filter harmful user inputs and FM-generated outputs
8+
content_policy_config = {
9+
filters_config = [
10+
{
11+
input_strength = "HIGH"
12+
output_strength = "HIGH"
13+
type = "SEXUAL"
14+
},
15+
{
16+
input_strength = "HIGH"
17+
output_strength = "HIGH"
18+
type = "VIOLENCE"
19+
},
20+
{
21+
input_strength = "HIGH"
22+
output_strength = "HIGH"
23+
type = "HATE"
24+
},
25+
{
26+
input_strength = "HIGH"
27+
output_strength = "HIGH"
28+
type = "INSULTS"
29+
},
30+
{
31+
input_strength = "HIGH"
32+
output_strength = "HIGH"
33+
type = "MISCONDUCT"
34+
},
35+
{
36+
input_strength = "NONE"
37+
output_strength = "NONE"
38+
type = "PROMPT_ATTACK"
39+
}
40+
]
41+
}
42+
43+
# block / mask potential PII information
44+
sensitive_information_policy_config = {
45+
pii_entities_config = [
46+
{
47+
action = "BLOCK"
48+
type = "DRIVER_ID"
49+
},
50+
{
51+
action = "BLOCK"
52+
type = "PASSWORD"
53+
},
54+
{
55+
action = "ANONYMIZE"
56+
type = "EMAIL"
57+
},
58+
{
59+
action = "ANONYMIZE"
60+
type = "USERNAME"
61+
},
62+
{
63+
action = "BLOCK"
64+
type = "AWS_ACCESS_KEY"
65+
},
66+
{
67+
action = "BLOCK"
68+
type = "AWS_SECRET_KEY"
69+
},
70+
]
71+
}
72+
73+
# block select word / profanity
74+
word_policy_config = {
75+
managed_word_lists_config = [{
76+
type = "PROFANITY"
77+
}]
78+
}
79+
80+
tags = [for k, v in local.combined_tags :
81+
{
82+
key : k,
83+
value : v
84+
}
85+
]
86+
87+
}
88+
89+
resource "awscc_bedrock_guardrail_version" "runtask_fulfillment" {
90+
guardrail_identifier = awscc_bedrock_guardrail.runtask_fulfillment.guardrail_id
91+
description = "Initial version"
92+
}

examples/basic/.header.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Usage Example
22

3-
Follow the steps below to deploy the module and attach it to your Terraform Cloud organization.
3+
Follow the steps below to deploy the module and attach it to your HCP Terraform (Terraform Cloud) organization.
44

55
* Build and package the Lambda files
66

examples/basic/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- BEGIN_TF_DOCS -->
22
# Usage Example
33

4-
Follow the steps below to deploy the module and attach it to your Terraform Cloud organization.
4+
Follow the steps below to deploy the module and attach it to your HCP Terraform (Terraform Cloud) organization.
55

66
* Build and package the Lambda files
77

images/example3.png

51 KB
Loading

lambda.tf

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,10 @@ resource "aws_lambda_function" "runtask_fulfillment" {
163163
}
164164
environment {
165165
variables = {
166-
CW_LOG_GROUP_NAME = local.cloudwatch_log_group_name
167-
BEDROCK_LLM_MODEL = var.bedrock_llm_model
166+
CW_LOG_GROUP_NAME = local.cloudwatch_log_group_name
167+
BEDROCK_LLM_MODEL = var.bedrock_llm_model
168+
BEDROCK_GUARDRAIL_ID = awscc_bedrock_guardrail.runtask_fulfillment.guardrail_id
169+
BEDROCK_GUARDRAIL_VERSION = awscc_bedrock_guardrail_version.runtask_fulfillment.version
168170
}
169171
}
170172
tags = local.combined_tags

lambda/runtask_fulfillment/ai.py

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# Initialize model_id and region
1313
default_model_id = "anthropic.claude-3-sonnet-20240229-v1:0"
1414
model_id = os.environ.get("BEDROCK_LLM_MODEL", default_model_id)
15+
guardrail_id = os.environ.get("BEDROCK_GUARDRAIL_ID", None)
16+
guardrail_version = os.environ.get("BEDROCK_GUARDRAIL_VERSION", None)
1517

1618
# Config to avoid timeouts when using long prompts
1719
config = botocore.config.Config(
@@ -207,6 +209,55 @@ def eval(tf_plan_json):
207209
logger.info("Terraform plan summary: {}".format(description))
208210

209211
results = []
210-
results.append(generate_runtask_result(outcome_id="Plan-Summary", description="Summary of Terraform plan", result=description[:700]))
211-
results.append(generate_runtask_result(outcome_id="AMI-Summary", description="Summary of AMI changes", result=result[:700]))
212+
213+
guardrail_status, guardrail_response = guardrail_inspection(str(description))
214+
if guardrail_status:
215+
results.append(generate_runtask_result(outcome_id="Plan-Summary", description="Summary of Terraform plan", result=description[:700]))
216+
else:
217+
results.append(generate_runtask_result(outcome_id="Plan-Summary", description="Summary of Terraform plan", result="Output omitted due to : {}".format(guardrail_response)))
218+
description = "Bedrock guardrail triggered : {}".format(guardrail_response)
219+
220+
guardrail_status, guardrail_response = guardrail_inspection(str(result))
221+
if guardrail_status:
222+
results.append(generate_runtask_result(outcome_id="AMI-Summary", description="Summary of AMI changes", result=result[:700]))
223+
else:
224+
results.append(generate_runtask_result(outcome_id="AMI-Summary", description="Summary of AMI changes", result="Output omitted due to : {}".format(guardrail_response)))
225+
212226
return description, results
227+
228+
def guardrail_inspection(input_text, input_mode = 'OUTPUT'):
229+
230+
#####################################################################
231+
##### Inspect input / output against Bedrock Guardrail #####
232+
#####################################################################
233+
234+
if guardrail_id and guardrail_version:
235+
logger.info("##### Scanning Terraform plan output with Amazon Bedrock Guardrail #####")
236+
237+
response = bedrock_client.apply_guardrail(
238+
guardrailIdentifier=guardrail_id,
239+
guardrailVersion=guardrail_version,
240+
source=input_mode,
241+
content=[
242+
{
243+
'text': {
244+
'text': input_text,
245+
}
246+
},
247+
]
248+
)
249+
250+
logger.debug("Guardrail inspection result : {}".format(json.dumps(response)))
251+
252+
if response["action"] in ["GUARDRAIL_INTERVENED"]:
253+
logger.info("Guardrail action : {}".format(response["action"]))
254+
logger.info("Guardrail output : {}".format(response["outputs"]))
255+
logger.debug("Guardrail assessments : {}".format(response["assessments"]))
256+
return False, response["outputs"][0]["text"]
257+
258+
elif response["action"] in ["NONE"]:
259+
logger.info("No Guardrail action required")
260+
return True, "No Guardrail action required"
261+
262+
else:
263+
return True, "Guardrail inspection skipped"

providers.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ terraform {
66
source = "hashicorp/aws"
77
version = ">= 5.47.0"
88
}
9+
awscc = {
10+
source = "hashicorp/awscc"
11+
version = ">= 1.11.0"
12+
}
913
random = {
1014
source = "hashicorp/random"
1115
version = ">=3.4.0"

0 commit comments

Comments
 (0)