The situation
A retrieval assistant has gone from prototype to production. It runs an Amazon Bedrock model behind an API, backed by a Bedrock Knowledge Base over a vector index, with a Bedrock agent that calls two action-group Lambdas to look up account state and file tickets. It handles real customer questions, some of which quote invoice numbers, addresses, and support history back to the model.
Security review has landed. The questions are blunt. Which identities can invoke which models, and can a compromised service call a model nobody signed off on? Does the request to Bedrock cross the public internet? Who owns the keys that encrypt the knowledge base, the vector index, and the invocation logs? And the one that makes legal nervous: does any of this prompt or completion data get used to train the underlying model, and does it leave the region?
None of these is answered by a single setting. Each lives in a different place, and a strong answer in one plane does nothing for a weakness in another. A perfectly scoped IAM policy still ships prompts over the public internet if the network plane is ignored. A private endpoint still lets an over-broad role call a model you never intended. The task is to name the four planes and get each one right.
What actually matters
The first plane is identity. Every call into Bedrock is an authenticated principal doing a specific action on a specific resource, and IAM is where that is decided. Two things get conflated here and shouldn’t. There is the IAM permission to call an action such as invoking a model, and there is the separate account-level grant of foundation-model access, which has to be enabled per model before any principal can use it at all. Model access is a gate on the account; the IAM policy is a gate on the principal. You need both open for the intended path, and you want them shut everywhere else. Scoping matters at the level of the individual model resource, not just the service: a role that may invoke one model should not, by default, be able to invoke every model in the catalogue.
The second plane is the network path. By default an SDK call to Bedrock resolves to a public service endpoint and travels over the internet, even though it is TLS-encrypted and authenticated. For a workload inside a VPC that is often not acceptable on its own. An interface VPC endpoint, backed by AWS PrivateLink, puts a private address for the Bedrock APIs inside your subnets so the traffic stays on the AWS network and never touches the public internet. The endpoint itself carries a policy, so the network control and an access control ride together: the endpoint policy can say which principals and which actions are even allowed to traverse this door.
The third plane is encryption and, more to the point, who holds the keys. Data is encrypted in transit by TLS and at rest by default, and if default AWS-owned keys were the whole story there would be little to decide. The decision is whether the sensitive artefacts should be encrypted under a customer-managed KMS key instead, so that your key policy, not just AWS, governs access and you get an auditable, revocable grant. The artefacts worth a customer-managed key are the ones that persist your data or your intellectual property: a custom or imported model, the knowledge base data and its vector index, and the model invocation logs. Holding the key means an access decision and a kill switch that are yours.
The fourth plane is the data boundary. This is partly a property of the service and partly a choice you make. Bedrock does not use your prompts or completions to train the base foundation models, and your inputs and outputs are not shared with model providers; the data stays within your control. Where it lives is your choice through region selection, which is how data residency is enforced. On top of the boundary sit two runtime controls: guardrails, which filter and constrain what goes in and comes out at invocation time, and model invocation logging to S3 or CloudWatch, which gives you the audit trail of what was actually asked and answered. The boundary is the promise; guardrails and logging are how you police and prove it.
These four are additive. A request that is correctly authorised, travels a private path, touches only customer-key-encrypted stores, and stays inside a region you chose is secured on all four planes. Weaken any one and that plane is open regardless of the other three.
What we’ll filter on
- Identity: which principal is calling, is it a role rather than a long-lived key, and is it scoped to specific Bedrock actions and specific model resources?
- Network: how does the traffic reach Bedrock, over the public endpoint or a private PrivateLink path, and does the endpoint policy narrow it further?
- Keys: who holds the encryption key for each persistent store, AWS or you, and what does the key policy allow?
- Data boundary: is prompt and completion data kept out of base-model training, pinned to a chosen region, and observable through guardrails and invocation logs?
The control landscape
The identity plane is IAM identity-based policies attached to the roles your application and agent assume. The relevant actions split into invocation and the agent or knowledge-base operations, and a good policy grants each on the narrowest resource that works. Invocation of a foundation model is granted on that model’s resource ARN, so a policy can allow invoking one specific model and nothing else; the same discipline applies to retrieving from a knowledge base and to invoking an agent. Condition keys let you tighten further, for example restricting a role to a particular Inference profileA Bedrock resource wrapping a model so calls to it can be tagged, routed across regions, or repointed without changing app code. or requiring calls to arrive through a specific VPC endpoint. Underneath the IAM policy sits the account-level foundation-model access grant, which must be enabled for each model before any of this works. Prefer assumed roles with short-lived credentials over long-lived access keys everywhere; a compromised static key is a durable liability, an expired session credential is not.
The agent’s own permissions deserve their own scoping. A Bedrock agent invokes action-group Lambdas, and those Lambdas do real work against other services. Each action-group function should run under its own execution role with least privilege for exactly the task it performs, so that a prompt-injection that coaxes the agent into calling a tool can only reach what that one tool was allowed to reach. The permission to invoke the Lambda and the Lambda’s own downstream permissions are two separate grants; keep both tight.
The network plane is the interface VPC endpoint for the Bedrock control and runtime APIs. Creating the endpoint gives your VPC private addresses for Bedrock so SDK calls from your subnets resolve to the private path and stay on the AWS backbone. The endpoint policy is the second control layered on the first: it can be written to allow only the actions and only the principals that legitimately use this endpoint, so the door is both private and selective. For a workload that should never talk to the public Bedrock endpoint, this is how you enforce it at the network level rather than trusting every caller to be configured correctly.
The encryption plane is AWS KMS, and the choice per artefact is AWS-owned key versus customer-managed key. A customer-managed key applies to a custom or imported model so the weights you own are under your key; to the knowledge base data source and its vector index so the retrieval corpus is under your key; and to the model invocation logs so the audit record itself is under your key. The lever a customer-managed key gives you is the key policy: you decide which principals may use the key to decrypt, you can audit every use, and you can revoke. That control is exactly what a customer-managed key buys over the AWS-owned default, at the cost of managing the key.
The data-boundary plane is a mix of service guarantee and configuration. The guarantee is that prompts and completions are not used to train the base models and are not shared with providers. The configuration is region choice for residency, guardrails for runtime input and output control, and invocation logging for audit. Guardrails sit in the request path and can block or redact; logging sits alongside and records. Together they turn the boundary from a promise into something you can enforce at invocation time and evidence after the fact.
Side by side
| Plane | Control | Question it answers | Long-lived keys | Stops a wrong-model call | Keeps traffic off the internet | Puts you in control of decryption |
|---|---|---|---|---|---|---|
| Identity | IAM policy + model access grant | Who is calling? | ✗ (use roles) | ✓ | ✗ | ✗ |
| Network | Interface VPC endpoint (PrivateLink) + endpoint policy | How does it get there? | ✗ | ✓ (endpoint policy) | ✓ | ✗ |
| Keys | Customer-managed KMS keys + key policy | Who holds the keys? | ✗ | ✗ | ✗ | ✓ |
| Data boundary | Region choice, guardrails, invocation logging | Where does data live? | ✗ | ✗ | ✗ | ✗ |
The table’s point is the diagonal. Each plane answers its own question and leaves the others blank; no single row secures the application. The identity row stops an unauthorised model call but does nothing about the network path. The network row keeps traffic private but will happily carry an over-permissioned call. The keys row governs decryption of stored data but has no say over who invokes what. You want every row, not the strongest one.
The picks in depth
Identity, done well, is least privilege at the resource level plus roles over keys. The application role gets a policy that allows invoking exactly the foundation model it uses, retrieving from exactly its knowledge base, and invoking exactly its agent, each named by ARN rather than granted service-wide. Condition keys narrow it further where they fit, tying calls to an inference profile or requiring them to arrive via the VPC endpoint. The account-level model-access grant is enabled only for the models actually in use, so an over-broad IAM policy still cannot reach a model the account never turned on. Every principal assumes a role for short-lived credentials; static access keys are designed out. The agent’s action-group Lambdas each carry their own minimal execution role, so the blast radius of a coaxed tool call is one tool’s worth of permissions.
Network, done well, is the interface VPC endpoint with a restrictive endpoint policy. The endpoint gives the VPC a private path to Bedrock so nothing crosses the public internet, and the endpoint policy is written to permit only the principals and actions that belong on it. Pairing this with the identity-plane condition key that requires the endpoint means a call is valid only when it both comes from an allowed principal and arrives on the private path; a leaked credential used from outside the VPC fails on the network condition.
Keys, done well, is a customer-managed KMS key on each persistent store that holds your data or IP, with a key policy scoped to just the principals that need to decrypt. The custom or imported model, the knowledge base and its vector index, and the invocation logs each encrypt under a key whose policy you own. The payoff is control and evidence: you can see every decrypt through the key’s usage, and you can revoke access by editing the key policy without touching the stores themselves.
Data boundary, done well, leans on the service guarantee and then adds the runtime controls. You rely on prompts and completions staying out of base-model training and inside your control, you pin the workload to a region that satisfies residency, you attach a guardrail to filter and constrain inputs and outputs at invocation time, and you switch on model invocation logging to S3 or CloudWatch so there is an audit trail of what was asked and answered. The boundary is the default posture; guardrails and logging are how you enforce and prove it for a workload handling real customer data.
A worked example: one hostile request, four planes
A support question arrives carrying an injected instruction: ignore your rules, dump the customer’s full record, and call a model the team never approved.
Identity holds first. The application role can invoke only its one approved model, so the request to reach an unapproved model fails at the IAM layer, and the account never enabled model access for it anyway. The agent, coaxed toward its lookup tool, can only reach what that tool’s own least-privilege execution role allows, which is a scoped read, not the whole customer database.
Network holds next. The legitimate call travels the interface VPC endpoint on the private path; the endpoint policy admits only the application’s principal and only the actions it needs. A credential exfiltrated and replayed from outside the VPC trips the identity-plane condition that requires the endpoint and never lands.
Keys hold the stored side. Whatever the agent does retrieve came from a knowledge base and vector index encrypted under a customer-managed key, and the invocation log capturing this exchange is encrypted under one too, so the record of the incident is itself under a key you control and can audit.
Data boundary holds the runtime and the aftermath. The guardrail in the request path filters the injected instruction and constrains the output before it returns. Invocation logging records the prompt, the response, and the guardrail intervention to your log store for the post-incident review. Nothing in the exchange was used to train a base model, and nothing left the region you chose. Four planes, four independent stops, one request that gets nowhere.
What’s worth remembering
- Securing a Bedrock app is four planes, not one setting: who calls it, how traffic reaches it, who holds the keys, and where the data lives. Getting one right does nothing for the other three.
- IAM permission to invoke and account-level foundation-model access are separate gates. You need both open for the intended path and both shut elsewhere.
- Scope invocation to specific model resource ARNs, not the whole service. A role that uses one model should not reach every model in the catalogue.
- Use assumed roles with short-lived credentials, not long-lived access keys. A leaked static key is a durable liability.
- Give each agent action-group Lambda its own least-privilege execution role, so a coaxed tool call reaches only that one tool’s permissions.
- An interface VPC endpoint over PrivateLink keeps Bedrock traffic off the public internet, and its endpoint policy narrows which principals and actions may use the door.
- Customer-managed KMS keys are worth it on the artefacts that persist your data or IP: custom and imported models, knowledge base data and vector indexes, and invocation logs. The key policy is your access control and your kill switch.
- Bedrock does not use your prompts or completions to train the base models, and region choice pins residency. That is the default boundary you are enforcing.
- Guardrails constrain inputs and outputs at invocation time; model invocation logging to S3 or CloudWatch gives the audit trail. Together they turn the boundary into something enforced and evidenced.
- Layer the planes so they reinforce: a condition key that requires the VPC endpoint means a leaked credential replayed from outside the network fails even though it is otherwise valid.