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

V0.0.1 #3

Merged
merged 28 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ To use this module you need have the following:
| <a name="provider_archive"></a> [archive](#provider\_archive) | ~>2.2.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.47.0 |
| <a name="provider_aws.cloudfront_waf"></a> [aws.cloudfront\_waf](#provider\_aws.cloudfront\_waf) | >= 5.47.0 |
| <a name="provider_awscc"></a> [awscc](#provider\_awscc) | n/a |
| <a name="provider_random"></a> [random](#provider\_random) | >=3.4.0 |
| <a name="provider_terraform"></a> [terraform](#provider\_terraform) | n/a |
| <a name="provider_time"></a> [time](#provider\_time) | n/a |
Expand Down Expand Up @@ -136,6 +137,8 @@ To use this module you need have the following:
| [aws_sfn_state_machine.runtask_states](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sfn_state_machine) | resource |
| [aws_wafv2_web_acl.runtask_waf](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl) | resource |
| [aws_wafv2_web_acl_logging_configuration.runtask_waf](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_logging_configuration) | resource |
| [awscc_bedrock_guardrail.runtask_fulfillment](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/bedrock_guardrail) | resource |
| [awscc_bedrock_guardrail_version.runtask_fulfillment](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/bedrock_guardrail_version) | resource |
| [random_string.solution_prefix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource |
| [random_uuid.runtask_cloudfront](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |
| [random_uuid.runtask_hmac](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource |
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.0.0
v0.0.1
92 changes: 92 additions & 0 deletions bedrock.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
resource "awscc_bedrock_guardrail" "runtask_fulfillment" {
name = "${local.solution_prefix}-guardrail"
blocked_input_messaging = "Unfortunately we are unable to provide response for this input"
blocked_outputs_messaging = "Unfortunately we are unable to provide response for this input"
description = "Basic Bedrock Guardrail for sensitive info exfiltration"

# detect and filter harmful user inputs and FM-generated outputs
content_policy_config = {
filters_config = [
{
input_strength = "HIGH"
output_strength = "HIGH"
type = "SEXUAL"
},
{
input_strength = "HIGH"
output_strength = "HIGH"
type = "VIOLENCE"
},
{
input_strength = "HIGH"
output_strength = "HIGH"
type = "HATE"
},
{
input_strength = "HIGH"
output_strength = "HIGH"
type = "INSULTS"
},
{
input_strength = "HIGH"
output_strength = "HIGH"
type = "MISCONDUCT"
},
{
input_strength = "NONE"
output_strength = "NONE"
type = "PROMPT_ATTACK"
}
]
}

# block / mask potential PII information
sensitive_information_policy_config = {
pii_entities_config = [
{
action = "BLOCK"
type = "DRIVER_ID"
},
{
action = "BLOCK"
type = "PASSWORD"
},
{
action = "ANONYMIZE"
type = "EMAIL"
},
{
action = "ANONYMIZE"
type = "USERNAME"
},
{
action = "BLOCK"
type = "AWS_ACCESS_KEY"
},
{
action = "BLOCK"
type = "AWS_SECRET_KEY"
},
]
}

# block select word / profanity
word_policy_config = {
managed_word_lists_config = [{
type = "PROFANITY"
}]
}

tags = [for k, v in local.combined_tags :
{
key : k,
value : v
}
]

}

resource "awscc_bedrock_guardrail_version" "runtask_fulfillment" {
guardrail_identifier = awscc_bedrock_guardrail.runtask_fulfillment.guardrail_id
description = "Initial version"
}
2 changes: 1 addition & 1 deletion examples/basic/.header.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Usage Example

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

* Build and package the Lambda files

Expand Down
2 changes: 1 addition & 1 deletion examples/basic/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- BEGIN_TF_DOCS -->
# Usage Example

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

* Build and package the Lambda files

Expand Down
6 changes: 4 additions & 2 deletions lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,10 @@ resource "aws_lambda_function" "runtask_fulfillment" {
}
environment {
variables = {
CW_LOG_GROUP_NAME = local.cloudwatch_log_group_name
BEDROCK_LLM_MODEL = var.bedrock_llm_model
CW_LOG_GROUP_NAME = local.cloudwatch_log_group_name
BEDROCK_LLM_MODEL = var.bedrock_llm_model
BEDROCK_GUARDRAIL_ID = awscc_bedrock_guardrail.runtask_fulfillment.guardrail_id
BEDROCK_GUARDRAIL_VERSION = awscc_bedrock_guardrail_version.runtask_fulfillment.version
}
}
tags = local.combined_tags
Expand Down
55 changes: 53 additions & 2 deletions lambda/runtask_fulfillment/ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# Initialize model_id and region
default_model_id = "anthropic.claude-3-sonnet-20240229-v1:0"
model_id = os.environ.get("BEDROCK_LLM_MODEL", default_model_id)
guardrail_id = os.environ.get("BEDROCK_GUARDRAIL_ID", None)
guardrail_version = os.environ.get("BEDROCK_GUARDRAIL_VERSION", None)

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

results = []
results.append(generate_runtask_result(outcome_id="Plan-Summary", description="Summary of Terraform plan", result=description[:700]))
results.append(generate_runtask_result(outcome_id="AMI-Summary", description="Summary of AMI changes", result=result[:700]))

guardrail_status, guardrail_response = guardrail_inspection(str(description))
if guardrail_status:
results.append(generate_runtask_result(outcome_id="Plan-Summary", description="Summary of Terraform plan", result=description[:700]))
else:
results.append(generate_runtask_result(outcome_id="Plan-Summary", description="Summary of Terraform plan", result="Output omitted due to : {}".format(guardrail_response)))
description = "Bedrock guardrail triggered : {}".format(guardrail_response)

guardrail_status, guardrail_response = guardrail_inspection(str(result))
if guardrail_status:
results.append(generate_runtask_result(outcome_id="AMI-Summary", description="Summary of AMI changes", result=result[:700]))
else:
results.append(generate_runtask_result(outcome_id="AMI-Summary", description="Summary of AMI changes", result="Output omitted due to : {}".format(guardrail_response)))

return description, results

def guardrail_inspection(input_text, input_mode = 'OUTPUT'):

#####################################################################
##### Inspect input / output against Bedrock Guardrail #####
#####################################################################

if guardrail_id and guardrail_version:
logger.info("##### Scanning Terraform plan output with Amazon Bedrock Guardrail #####")

response = bedrock_client.apply_guardrail(
guardrailIdentifier=guardrail_id,
guardrailVersion=guardrail_version,
source=input_mode,
content=[
{
'text': {
'text': input_text,
}
},
]
)

logger.debug("Guardrail inspection result : {}".format(json.dumps(response)))

if response["action"] in ["GUARDRAIL_INTERVENED"]:
logger.info("Guardrail action : {}".format(response["action"]))
logger.info("Guardrail output : {}".format(response["outputs"]))
logger.debug("Guardrail assessments : {}".format(response["assessments"]))
return False, response["outputs"][0]["text"]

elif response["action"] in ["NONE"]:
logger.info("No Guardrail action required")
return True, "No Guardrail action required"

else:
return True, "Guardrail inspection skipped"