Exam Room · Advanced GenAI

Governing Model Access Across Many Teams

August 03, 2026 · 35 min read

Generative AI Development · part of The Exam Room

The situation

A company has standardised on Amazon Bedrock and the demand is now organisation-wide. A dozen product teams, spread across separate AWS accounts under one AWS Organization, all want to invoke foundation models. Some teams have a genuine need for the most capable and most expensive models; most do not. One team handles regulated data and must be pinned to an approved shortlist. Finance wants a monthly figure per team, not one undifferentiated Bedrock line on the consolidated bill.

The platform team owns the problem. They have been fielding a ticket per team asking to turn on model access, hand-writing IAM policies, and guessing at who spent what when the bill arrives. It does not scale, and it is not safe: nothing today stops a team from invoking a model nobody signed off on, and nothing attributes the cost of that call to the team that made it.

What they want is three things at once. Least privilege at the level of an individual model, so a team can reach exactly the models it was approved for and no others. An organisation-wide policy floor that holds even if a team account is misconfigured. And cost that is visible per team without reading tea leaves. These pull on different controls, and the account structure is the frame that holds them together.

What actually matters

The first thing that matters is that access to a foundation model is two gates, not one, and both are per account and per region. Before any principal can invoke a model, that model has to be enabled for the account in the region you are calling, through Bedrock model access. That enablement is an account-level switch, separate from any IAM permission. On top of it sits the IAM identity-based policy that says which principal may perform which Bedrock action on which resource. A team account that never enabled a model cannot reach it however permissive its IAM is; a role with no invoke permission cannot reach an enabled model either. Governing access at scale means being deliberate about both gates in every account.

The second thing is granularity. Bedrock invocation permissions can be scoped to a specific model resource ARN, so a policy grants invoking one named model rather than the service as a whole. This is the difference between least privilege and a blanket grant. The same discipline lets a policy point at an Inference profileA Bedrock resource wrapping a model so calls to it can be tagged, routed across regions, or repointed without changing app code. ARN instead of, or in addition to, the bare model, which becomes the hook for both cost attribution and cross-region routing. Scoping at model granularity is the control that answers can this team reach this model.

The third thing is that in a multi-account organisation you have a control the individual account does not: the organisation itself. AWS Organizations service control policies set the maximum available permissions for the accounts beneath them. An SCP does not grant anything; it draws the ceiling. A well-placed SCP can deny Bedrock actions the organisation never wants anyone to perform, or deny invocation of specific models everywhere, or deny it except under a stated condition, and no IAM policy in a member account can climb over that ceiling. This is how a policy floor holds even when a single account is misconfigured, and it is the difference between hoping every team gets its IAM right and enforcing that they cannot get it dangerously wrong.

The fourth thing is that cost has to be made visible on purpose. Bedrock spend does not attribute itself to a team. Cost allocation tags are the mechanism, and application inference profiles are what makes them bite for invocation cost: a per-team application inference profile carries tags, teams invoke through the profile ARN, and the usage and cost meter against that tagged profile so Cost Explorer and the cost allocation report can slice spend by team. Without this the bill is one Bedrock number; with it, each team has its own.

The fifth thing is that the runtime policy and the audit trail should be centralised rather than reinvented per team. Guardrails filter and constrain inputs and outputs at invocation time, and a guardrail is a versioned resource that many applications can reference by identifier, so one central definition becomes the organisation policy every team applies rather than a dozen local variants. Model invocation logging to S3 or CloudWatch gives the audit record of what was asked and answered, and pointing every account at a central log destination turns scattered logs into one reviewable trail. Guardrails-as-policy and central logging are how the organisation both enforces and evidences the rules.

Hold these together and a pattern falls out. The platform team stops vending access ticket by ticket and starts vending a shared configuration: the organisation ceiling, the central guardrail, the log destination, and a self-service way for a team to get a scoped role and a tagged inference profile without the platform team writing each one by hand.

What we’ll filter on

  1. Access enablement: is the foundation model turned on for this account and region before any principal tries to use it, as a gate separate from IAM?
  2. Least privilege at model granularity: does the identity-based policy scope invocation to specific model or inference-profile ARNs rather than the whole Bedrock service?
  3. Organisation-wide floor: is there a service control policy that denies unwanted Bedrock actions or specific models across all accounts, that no member-account IAM can override?
  4. Per-team cost visibility: are cost allocation tags and per-team application inference profiles in place so spend meters back to the team that incurred it?
  5. Central policy and audit: is there one shared guardrail definition applied everywhere and one central invocation-logging destination, rather than per-team reinvention?

The governance landscape

Model access enablement is the account-and-region gate underneath everything else. A foundation model has to be enabled in Bedrock for the account before it can be invoked there, and enablement in one region does not carry to another. At organisation scale this is a decision to make deliberately per account: the regulated team account enables only its approved shortlist, a general team account enables the common models, and no account has an expensive model turned on unless someone chose to. Because enablement is distinct from IAM, it acts as a coarse first filter even before policy is considered, and leaving a model disabled is itself a governance control.

IAM identity-based policies are where the fine-grained decision lives. A role gets a policy that allows the Bedrock invoke actions on the specific model resource ARNs, or the inference-profile ARNs, that the team is approved for, and nothing broader. Condition keys tighten it further where they fit. Permission boundaries are the companion control for a self-service organisation: a boundary caps the maximum permissions a role can have, so the platform team can let each team create and manage its own Bedrock roles while guaranteeing those roles can never exceed the boundary the platform team set. That is what makes delegation safe rather than a loophole.

Service control policies are the organisation-level lever. Attached to the organisation root or to an organisational unit, an SCP denies actions across every account beneath it and cannot be overridden from inside a member account. The governance uses of this are direct: deny Bedrock actions the organisation does not sanction anywhere, deny invocation of named model ARNs so an expensive or unapproved model is off-limits organisation-wide, or scope a regulated OU to an approved set by denying everything outside it. Because an SCP only ever removes permission and never grants it, it is a ceiling, and the member-account IAM operates in the space below that ceiling.

Cost allocation tags plus application inference profiles are the attribution layer. A cross-region or single-region inference profile defines how a model call is routed; an application inference profile wraps that and adds tags you control. Give each team its own application inference profile, tag it with the team identifier, and have the team invoke through that profile ARN. The invocation cost meters against the tagged profile, and once the relevant cost allocation tags are activated in the billing console the spend shows up sliced by team in Cost Explorer and the cost allocation report. The same tags on the profile double as an IAM scoping target, so the object that attributes cost is also the object a policy can pin a team to.

Central guardrails and invocation logging are the shared policy and audit. A guardrail is a standalone, versioned resource that constrains inputs and outputs; defining it once centrally and having every team reference it by identifier means the organisation ships one policy rather than trusting each team to rebuild it. The ApplyGuardrail path lets a guardrail be evaluated independently of the model call, which helps when the platform team wants the policy enforced consistently regardless of how a team wired its application. Model invocation logging captures the request and response to S3 or CloudWatch, and directing accounts at a central destination gives one organisation-wide trail to review. Together they are guardrails-as-policy: the rules live centrally and the evidence collects centrally.

The self-service vending pattern is what ties the landscape into something operable. The platform team owns the organisation ceiling, the central guardrail, the log destination, the permission boundary, and a template that stamps out a scoped role plus a tagged application inference profile for a new team. A team requesting access gets the shared configuration applied rather than a bespoke hand-built one, which is what lets governance scale past the dozen teams to the next dozen.

Side by side

Control Scope Enables a model Restricts which model a principal invokes Holds even if an account is misconfigured Attributes cost per team Central policy and audit
Model access enablement Per account, per region
IAM identity-based policy + permission boundary Per principal in an account
Service control policy Whole organisation or OU ✓ (as a deny ceiling)
Cost allocation tags + application inference profiles Per team ✗ (but scopable)
Central guardrail + invocation logging Organisation-wide policy

The table’s point is that no single row governs the organisation. Enablement is a gate but not a policy; IAM is fine-grained but lives inside one account and can be misconfigured there; the SCP is the floor that holds regardless but only ever denies, so it cannot turn a model on or attribute a cost; the inference profile attributes spend but does not by itself stop a wrong call; the central guardrail and logging carry policy and audit but say nothing about who may invoke what. A working governance posture is the whole column, layered so each control does the job the others cannot.

Management & platform account the platform team vends one shared configuration SCP: deny unapproved models central guardrail + log destination permission-boundary template Team A account model access: approved shortlist enabled IAM role scoped to model ARNs (boundary-capped) app inference profile, tagged team=A Team B account model access: approved shortlist enabled IAM role scoped to model ARNs (boundary-capped) app inference profile, tagged team=B Regulated team account model access: narrow approved set only IAM role scoped to model ARNs (boundary-capped) app inference profile, tagged team=Reg Consolidated billing activated cost allocation tags slice Bedrock spend by team Cost Explorer: team=A, team=B, team=Reg, each its own figure vends shared config SCP ceiling: no account below can exceed it tagged spend rolls up
The organisation frames the controls. The platform team vends a shared configuration down into each team account, the SCP draws a ceiling none of them can exceed, and each team's tagged inference profile rolls its spend up to a per-team figure.

The picks in depth

Least privilege at model granularity is the core of the identity work. Each team’s role carries an IAM policy that allows the Bedrock invoke actions on the specific model or inference-profile ARNs the team is approved for, named explicitly rather than granted across the service. The account-level model access enablement backs this up as a second gate, turned on only for the models the team actually uses, so an over-broad policy still cannot reach a model the account never enabled. The permission boundary caps the whole thing: whatever role a team creates for itself, the boundary the platform team attached means that role can never grant itself more Bedrock reach than the organisation allowed. Fine-grained grant, coarse enablement gate, and a hard cap on delegation, working together.

The organisation-wide floor is the SCP, and its value is that it holds no matter what happens inside a member account. Deny statements at the root or an OU take the most expensive or most sensitive models off the table everywhere, or fence a regulated OU to an approved set, and because an SCP only removes permission there is no IAM policy a team can write to climb back over it. This is what turns governance from a per-account hope into an organisation guarantee. The SCP does not enable anything or grant anything; it is purely the ceiling, and the member-account IAM lives beneath it.

Per-team cost visibility is the pairing of cost allocation tags with application inference profiles. Each team invokes through its own application inference profile, tagged with the team identifier, so the invocation cost meters against that tagged profile. Once the corresponding cost allocation tags are activated in the billing console, Cost Explorer and the cost allocation report break Bedrock spend out by team instead of showing one lump. The profile is doing double duty: it is the cost-attribution object and, because a policy can be scoped to its ARN, also a natural place to pin a team’s access. One object, two governance jobs.

Central policy and audit is the guardrail plus logging, defined once and applied broadly. A single versioned guardrail becomes the organisation’s input-and-output policy, referenced by identifier from every team’s application rather than rebuilt locally, and evaluated consistently including via the standalone apply path when the platform team wants it enforced regardless of how a team wired its calls. Model invocation logging pointed at a central destination collects one trail of what was asked and answered across the organisation. The rules and the evidence both live in the middle, which is what makes them auditable.

The self-service vending pattern is the operating model that carries the rest. The platform team owns the ceiling, the guardrail, the log destination, the boundary, and a template that stamps out a scoped role and a tagged inference profile per team, so onboarding a team is applying the shared configuration rather than hand-building a bespoke one. This is what lets the governance hold its shape as the number of teams grows, which was the point of the account structure in the first place.

A worked example: onboarding a new team

A new team asks for Bedrock access to build a summarisation feature, and requests one of the pricier models for it.

The organisation ceiling is checked first. The SCP on the root already denies invocation of the most expensive models except in named accounts, so the request is really a request to either use an already-sanctioned model or to have the account added to the exception. The platform team decides the standard model is sufficient and the pricier one stays denied for this account, and no IAM anyone writes in that account can undo that.

Enablement and identity come next through the template. In the new team’s account the platform team enables model access for the approved shortlist and nothing else, stamps out a role whose policy allows invoking exactly those model ARNs, and attaches the permission boundary so the team can manage its own roles without ever exceeding that reach. The pricier model is doubly out of range: the SCP denies it and the account never enabled it.

Cost attribution is wired at the same time. The template creates an application inference profile tagged with the new team’s identifier and hands the team the profile ARN to invoke through. From the first call, that team’s spend meters against its own tag, and once the tag is activated it appears as its own figure in Cost Explorer rather than blurring into the total.

Policy and audit are inherited, not rebuilt. The team’s application references the central guardrail by identifier, so it ships the organisation’s input-and-output policy on day one, and invocation logging in the account points at the central destination, so the new team’s calls join the one organisation-wide audit trail. The team is productive in an afternoon, and every governance property held without a single hand-written exception.

What’s worth remembering

  1. Access to a foundation model is two gates: account-and-region model access enablement, and the IAM permission to invoke. Both are per account and per region, and you need both open on the intended path and shut elsewhere.
  2. Scope invocation to specific model or inference-profile ARNs, not the whole Bedrock service. That is what makes access least privilege at the granularity of a single model.
  3. Leaving a model disabled in an account is itself a control. Enablement is a coarse gate that bites before IAM is even consulted.
  4. Service control policies draw the organisation ceiling. They only ever deny, never grant, and no member-account IAM can climb over them, so they are how a policy floor holds even when an account is misconfigured.
  5. Use an SCP to deny expensive or unapproved models organisation-wide, or to fence a regulated OU to an approved shortlist. The member-account IAM operates in the space beneath that ceiling.
  6. Permission boundaries cap the maximum permissions a role can hold, which is what makes self-service safe: teams can create their own Bedrock roles without ever exceeding the reach the platform team allowed.
  7. Per-team application inference profiles carry tags; teams invoke through the profile ARN, and the cost meters against the tag. Activate the cost allocation tags and Cost Explorer slices Bedrock spend by team.
  8. The tagged inference profile does double duty: it attributes cost and it is a natural ARN to scope a team’s IAM policy to.
  9. Define one central, versioned guardrail and reference it everywhere, and point every account’s invocation logging at one destination. That is guardrails-as-policy plus a single audit trail, rather than a dozen local reinventions.
  10. The scalable operating model is a platform team that vends a shared configuration, the SCP ceiling, central guardrail and logging, a permission boundary, and a template for a scoped role and a tagged profile, so onboarding a team applies the standard rather than hand-building an exception. For the single-application view of these same controls, see securing a Bedrock app across identity, network, keys, and data boundary.

These posts are LLM-aided. Backbone, original writing, and structure by Craig. Research and editing by Craig + LLM. Proof-reading by Craig.