Skip to main content
CloudArq
topicbedrock
scopeaws · ai
typehow-to
guide · aws · amazon bedrock

Set up Amazon Bedrock Guardrails & logging

If you run generative AI on Amazon Bedrock, two controls do the heavy lifting: model-invocation logging so you have a record of what was asked and answered, and a Guardrail so harmful content and PII are blocked before they reach — or leave — the model. This is the practical setup: turn logging on, keep its sink private, attach a Guardrail, and tighten your agent IAM.

Updated 2026-07-20 · ~9 minute read

4
Guardrail policy types
3
checks cover Bedrock config
163
read-only checks in total
0
agents installed
why it matters

Two controls, two different jobs

A generative-AI workload has a blind spot that a traditional service does not: the prompts and completions themselves. Model-invocation logging gives you the durable record — what was asked, what came back, which model, from which principal — that you need for audit and incident response. A Guardrail is the active control: it inspects every request and response against your policies and blocks or redacts harmful categories, denied topics, banned words, and PII. Logging tells you what happened; the Guardrail stops the bad thing from happening. Turn on both — then make sure the log's destination is not itself a leak.

step 1 · observability

Turn on model-invocation logging

Bedrock can deliver a record of every invocation to Amazon CloudWatch Logs, to an S3 bucket, or to both. Configure it once per region (in the console: Bedrock → Settings → Model invocation logging), and enable the data-delivery flags for the payload types you use. Read the current state first — an empty configuration means it has never been turned on, which is the risk.

aws cli · bedrock
# Is logging configured in this region? (empty = never enabled)
aws bedrock get-model-invocation-logging-configuration --region eu-north-1

# Enable it, delivering to BOTH CloudWatch Logs and a private S3 bucket
aws bedrock put-model-invocation-logging-configuration --region eu-north-1 \
  --logging-config '{
    "cloudWatchConfig": {
      "logGroupName": "/aws/bedrock/model-invocations",
      "roleArn": "arn:aws:iam::111122223333:role/BedrockLoggingRole"
    },
    "s3Config": {
      "bucketName": "example-bedrock-logs-private",
      "keyPrefix": "invocations/"
    },
    "textDataDeliveryEnabled": true,
    "imageDataDeliveryEnabled": true,
    "embeddingDataDeliveryEnabled": true
  }'
step 2 · keep it private

Lock down the log destination

This is the step people skip. Because the invocation log can contain raw prompts and completions — potentially PII or secrets — a public bucket or an over-shared log group turns your safety audit trail into a data-leak surface. Block public access on the bucket, confirm it is not public, and encrypt it. Grant read access only to the roles that genuinely need it.

aws cli · s3api
# Block Public Access on the log bucket (all four flags)
aws s3api put-public-access-block --bucket example-bedrock-logs-private \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

# Confirm S3 does not consider it public (it computes IsPublic for you)
aws s3api get-bucket-policy-status --bucket example-bedrock-logs-private
# => {"PolicyStatus": {"IsPublic": false}}
step 3 · active control

Create a Guardrail — content and PII filters

A Guardrail bundles several policy types you can mix and match. Configure the ones your use case needs, then publish a version. The console wizard is the quickest path (Bedrock → Guardrails → Create guardrail); the CLI equivalent is below, with a content filter and a PII policy set to block.

aws cli · bedrock
aws bedrock create-guardrail --region eu-north-1 \
  --name example-support-guardrail \
  --blocked-input-messaging "Sorry, I can't help with that request." \
  --blocked-outputs-messaging "Sorry, I can't share that." \
  --content-policy-config '{
    "filtersConfig": [
      {"type": "HATE",       "inputStrength": "HIGH", "outputStrength": "HIGH"},
      {"type": "INSULTS",    "inputStrength": "HIGH", "outputStrength": "HIGH"},
      {"type": "PROMPT_ATTACK", "inputStrength": "HIGH", "outputStrength": "NONE"}
    ]
  }' \
  --sensitive-information-policy-config '{
    "piiEntitiesConfig": [
      {"type": "EMAIL",             "action": "BLOCK"},
      {"type": "CREDIT_DEBIT_CARD_NUMBER", "action": "BLOCK"},
      {"type": "US_SOCIAL_SECURITY_NUMBER", "action": "BLOCK"}
    ]
  }'
Content filters

Filter harmful categories (hate, insults, sexual, violence, misconduct, and prompt attacks) at configurable strengths on both input and output.

Denied topics

Define topics the assistant must refuse — described in natural language and blocked on request and response.

Word filters

Block a custom list of words and phrases, plus a managed profanity list.

Sensitive information (PII)

Detect and either block or redact PII (names, emails, SSNs, card numbers) and custom regex patterns.

Contextual grounding

Score responses for grounding against the source and relevance to the query, to reduce hallucination in RAG answers.

step 4 · parity

Actually attach it — everywhere it should run

A Guardrail only protects a request that references it. For a direct InvokeModel call you pass the guardrail identifier and version; for a Bedrock Agent you associate the Guardrail with the agent. It is easy to build a strong Guardrail and still leave a code path or an agent that never invokes it — the parity gap. Pass it explicitly on every model call, and verify each agent has it configured.

aws cli · bedrock-runtime
# A direct model call MUST reference the guardrail to be protected
aws bedrock-runtime invoke-model --region eu-north-1 \
  --model-id anthropic.claude-3-5-sonnet-20241022-v2:0 \
  --guardrail-identifier gr-example123 \
  --guardrail-version 1 \
  --body '{"messages":[{"role":"user","content":[{"type":"text","text":"..."}]}]}' \
  /dev/stdout
step 5 · least privilege

Review the agent execution role

A Bedrock Agent acts through an IAM execution role, and an agent can be steered by its input. The narrower that role, the smaller the damage a prompt-injection or a misbehaving action group can do — its blast radius. Pull the role's attached and inline policies and look for wildcards: "Action": "*", broad service admin, or write access to data the agent never needs. Scope it to the specific actions and resources the agent actually uses.

aws cli · iam
# List what the agent's execution role can do
aws iam list-attached-role-policies --role-name example-agent-exec
aws iam list-role-policies          --role-name example-agent-exec

# Inspect an inline policy for wildcard actions / resources
aws iam get-role-policy --role-name example-agent-exec \
  --policy-name example-agent-inline --query PolicyDocument
step 6 · make it stick

Codify the Guardrail so it can't regress

A console-only Guardrail drifts and is hard to review. Put it in Terraform so changes to the filters show up in a plan and a new environment gets the same protection by default.

terraform · aws provider
resource "aws_bedrock_guardrail" "support" {
  name                      = "example-support-guardrail"
  blocked_input_messaging   = "Sorry, I can't help with that request."
  blocked_outputs_messaging = "Sorry, I can't share that."

  content_policy_config {
    filters_config {
      type            = "HATE"
      input_strength  = "HIGH"
      output_strength = "HIGH"
    }
    filters_config {
      type            = "PROMPT_ATTACK"
      input_strength  = "HIGH"
      output_strength = "NONE"
    }
  }

  sensitive_information_policy_config {
    pii_entities_config {
      type   = "EMAIL"
      action = "BLOCK"
    }
    pii_entities_config {
      type   = "CREDIT_DEBIT_CARD_NUMBER"
      action = "BLOCK"
    }
  }
}

Keep the invocation-logging configuration and the log bucket's Block Public Access block in the same Terraform, so a reviewer sees any change to your AI audit trail before it ships.

product · detection

How CloudArq detects this for you

CloudArq runs the same checks on a schedule across every region, as part of its AI-workload lens. Of its 192 read-only checks, 4 cover this directly: bedrock_invocation_logging_off (logging off), invocation_log_sink_exposure (the log sink is public), bedrock_guardrail_parity (a model path with no Guardrail attached), and agentic_blast_radius (an over-permissioned agent role). It reads Bedrock control-plane and configuration metadata only — never your prompts, completions, or invocation logs — and each finding ships with the exact console, CLI, and Terraform fix from the steps above. It detects and hands you the fix; it never changes your account.

findings · lens · ai-workloadillustrative example
Critical1High3
invocation_log_sink_exposure
Invocation-log S3 bucket is world-readable
arn:aws:s3:::example-bedrock-logs
fix →
bedrock_invocation_logging_off
Model-invocation logging disabled in a region
bedrock · eu-west-1
fix →
bedrock_guardrail_parity
Agent invokes a model with no Guardrail attached
agent example-support · eu-north-1
fix →
agentic_blast_radius
Agent execution role holds broad write permissions
role example-agent-exec
fix →

Each finding carries a copy-paste console / CLI / Terraform fix. Read-only — CloudArq never touches agent data or auto-changes your account.

faq

Frequently asked

01What does Bedrock model-invocation logging capture, and where should it go?
It records the metadata of every model invocation — and, when you enable the text, image, and embedding data-delivery flags, the prompt and completion payloads too. You can deliver it to Amazon CloudWatch Logs, to an S3 bucket, or to both at once. Because those payloads can contain sensitive input, the destination is itself sensitive: send it to a private bucket or log group, encrypted, with access tightly scoped.
02What's the difference between a Guardrail and model-invocation logging?
They solve different problems. Logging is observability — a durable record of what was asked and answered, for audit and incident response. A Guardrail is an active control that inspects each request and response and can block or redact content: harmful categories, denied topics, banned words, and PII. You want both — the log tells you what happened, the Guardrail stops the bad thing from happening in the first place.
03Why does keeping the log sink private matter so much?
The invocation log can contain the raw prompts and completions your users sent to a model — potentially PII, secrets, or proprietary data. A public S3 bucket or an over-shared log group turns your safety audit trail into a data-leak surface. Treat the sink like the crown-jewel data it holds: block public access on the bucket, encrypt it, and grant read access only to the roles that genuinely need it.
04Does a Guardrail apply to every invocation automatically?
No — a Guardrail only protects a request that references it. For direct InvokeModel calls you pass the guardrailIdentifier and guardrailVersion; for a Bedrock Agent you associate the Guardrail with the agent. So it is possible to create a strong Guardrail and still have agents or code paths that never invoke it. That parity gap — a Guardrail exists but is not attached everywhere — is exactly the kind of thing worth checking for.
05Is CloudArq read-only, and does it read my prompts or model outputs?
Read-only, and no. CloudArq connects through a read-only IAM role with an ExternalId and inspects only Bedrock control-plane and configuration metadata — whether invocation logging is on, whether the log sink is public, whether a Guardrail is attached, and what an agent role can do. It never reads, copies, or stores your prompts, completions, or invocation logs. Findings are encrypted at rest with AES-256-GCM and hosted in the EU (Helsinki). It detects and hands you the fix; it never changes your account.
06Which CloudArq checks flag Bedrock logging and Guardrail gaps?
bedrock_invocation_logging_off flags an account or region with model-invocation logging disabled; invocation_log_sink_exposure flags a log destination (S3 bucket) that is publicly reachable; bedrock_guardrail_parity flags model access paths that run without a Guardrail attached; and agentic_blast_radius flags a Bedrock agent execution role with broader permissions than the agent needs. All four are read-only control-plane checks and each finding ships with the exact console, CLI, and Terraform steps to close it.

Guardrails and logging are the start of the AI lens

Bedrock config is one slice of a wider picture. See how CloudArq audits generative-AI workloads on the AI-workload lens and the Bedrock security overview, or find more walkthroughs in the guides library.