# RAG on ServiceNow: the connector that erases user criteria

Amazon Bedrock Managed Knowledge Base got a native ServiceNow connector on September 4, 2026, and it removes weeks of hand-rolled pipeline. It also tells you to use a service account with knowledge_admin, which bypasses per-knowledge-base user criteria — and the connector ingests no document-level ACL. This is the retro of the pilot where those two lines of documentation met.

- URL: https://fernando.moretes.com/blog/rag-sobre-servicenow-o-conector-que-apaga-o-user-criteria-amazon-bedro

- Markdown: https://fernando.moretes.com/blog/rag-sobre-servicenow-o-conector-que-apaga-o-user-criteria-amazon-bedro/article.md?lang=en

- Published: 2026-09-06T10:16:58.083Z

- Category: AI & Agents

- Tags: bedrock, rag, servicenow, seguranca, iam, knowledge-base, governanca, finops

- Reading time: 8 min

- Source: [Amazon Bedrock Managed Knowledge Base now supports ServiceNow as a native data source connector](https://aws.amazon.com/about-aws/whats-new/2026/09/amazon-bedrock-managed-knowledge-base-servicenow-native-data-source-connector/)

---

The documentation for Amazon Bedrock Managed Knowledge Base's ServiceNow connector carries two sentences that look like implementation detail when read apart. The first tells you to grant `knowledge_admin` to the service account, and explains why: the role bypasses per-knowledge-base user criteria restrictions. The second warns that ServiceNow data sources don't support document-level ACLs — every authenticated user who can query the knowledge base sees every crawled document. Together they describe an enterprise assistant that answers anything for anyone. This is the retro of the pilot where I found that out the cheap way: in staging, four hours after the first sync.

## What happened

## What happened

I stood the connector up the day it shipped, September 4, 2026, against a staging instance loaded with a real export: roughly 12,000 knowledge articles spread across six separate knowledge bases, and 40,000 active catalog items. The goal was to measure sync time and retrieval quality for an internal IT assistant — the exact use case AWS names in the announcement.

I followed the documentation line by line. The `glide.oauth.inbound.client.credential.grant_type.enabled` property set to `true`. A service account flagged *Web service access only*, no interactive sign-in. The OAuth application registered through the interceptor page — not by inserting straight into `oauth_entity`, as the guide itself warns. An Inbound Authentication Profile wired to a REST API Access Policy over `now/table`, because without it the token is valid and the Table API still returns `401`. Step 3 asks for exactly two roles: `knowledge_admin` and `catalog_admin`. I assigned both, and ServiceNow inherited around fourteen contained roles.

The sync finished. Then I asked the question I ask of every enterprise RAG before anything ships: I queried the assistant about a subject I knew was restricted to one group on the source instance. The answer came back whole, citing the article, for an identity that held no role there at all. It wasn't a hallucination — it was correct retrieval of a document ServiceNow would never have rendered for that user.

The pilot stopped there. What follows is the retro, blameless: the configuration was right per the documentation, and that is precisely the point.

## Timeline

1. **T+0h — service account created with the roles from the guide** — `knowledge_admin` and `catalog_admin` assigned per step 3. The documentation note says, in plain letters, that these roles bypass per-KB and per-catalog user criteria restrictions. I read it and complied.

2. **T+0h20 — OAuth verified with curl** — `POST /oauth_token.do` with `grant_type=client_credentials`, then `GET /api/now/table/kb_knowledge?sysparm_limit=1`. HTTP 200 with data. AWS's verification table reads an empty array as a symptom of an insufficient role — meaning success here is already success *with bypass*.

3. **T+0h35 — data source created with no filter** — `crawlKnowledgeArticles`, `crawlServiceCatalogs` and both attachment fields set to `true`; `filterConfiguration` omitted. With no filter the connector crawls every published article and every active item the account can see — which is now everything.

4. **T+3h50 — sync completes slower than planned** — The troubleshooting page explains it: without `inclusionServiceCatalogSysIds`, the crawl sweeps the 100,000-plus active items of an enterprise instance. I had 40,000 and it still took hours.

5. **T+4h05 — the control query returns restricted content** — A natural-language question, no `userContext`, about an article restricted to one group. Chunk and citation came back normally. Nothing in the trace flags an anomaly, because nothing anomalous happened.

6. **T+4h15 — data source deleted, retro opened** — Index destroyed in staging, with no end-user exposure. The real cost of the incident was one day of work and a few dollars of storage — the design, not so much.

> **Root cause: two controls removed at different points of the path:** ServiceNow's user criteria isn't ignored at query time — it is ignored at **ingestion**, by a role the documentation instructs you to assign, and never rebuilt afterwards, because the ServiceNow connector isn't in Managed Knowledge Base's ACL matrix. SharePoint, OneDrive, Google Drive and Confluence support pre-retrieval filtering plus real-time verification; S3 and Custom support pre-retrieval filtering from metadata you supply; Web Crawler and ServiceNow support neither. The rule that seals the hole is unforgiving: non-ACL data sources in a mixed knowledge base return results to every user, with or without `userContext` on the `Retrieve` call. This is not a connector bug — it is its published contract, and designing around it is your job.

## Where user criteria dies

The path of a restricted article, from the `kb_knowledge` table to the assistant's answer. The two red points in the drawing aren't failures: they are documented behaviors that, added together, remove the only access control the source ever had.

### 🏢 ServiceNow — origem do conteúdo

- kb_knowledge ~12k artigos, user criteria por KB (external)
- sc_cat_item ~40k itens ativos + anexos (external)
- svc account (2LO) knowledge_admin + catalog_admin (security)

### 🟧 AWS — Ingestão

- Secrets Manager clientId / clientSecret / instanceUrl (security)
- ServiceNow connector v1 incremental por sys_updated_on (compute)
- Managed Knowledge Base chunks + embeddings, sem ACL (ai)

### 🟧 AWS — Recuperação

- Retrieve / AgenticRetrieveStream userContext sem efeito aqui (ai)
- Assistente de TI autentica no IdP corporativo (compute)

### 🔐 Fronteira que sobra depois do retro

- KB 'publica' crawlPublicKnowledgeArticlesOnly = true (storage)
- KB 'restrita' sys IDs isolados + IAM por grupo (storage)
- IAM na chamada Retrieve Condition por tag de audiência (security)

### Flows

- svc -> kb: 1. knowledge_admin bypasses user criteria
- svc -> cat: 2. catalog_admin bypasses catalog restrictions
- sm -> conn: secret in the same Region as the KB
- conn -> svc: 2LO token + Table API /now/table
- conn -> mkb: 3. ingests text and metadata — permissions not
- mkb -> ret: hybrid search, top-k over everything
- emp -> app: natural-language question
- app -> ret: 4. query with no per-document boundary
- ret -> app: chunk + citation from any crawled article
- conn -> kbpub: fix: public articles only
- conn -> kbres: fix: single-audience sys IDs
- app -> iam: fix: role per audience, not per app
- iam -> kbres: bedrock:Retrieve conditioned by tag

## The fix: scope at ingestion, because there is none at query time

## The fix: scope at ingestion, because there is none at query time

When the access boundary doesn't exist at retrieval time, it has to exist earlier — in what enters the index. Four concrete changes.

**One knowledge base per audience, not one per system.** `Retrieve` takes a `knowledgeBaseId`; that is the only unit IAM can see. I split into two bases: one fed with `crawlPublicKnowledgeArticlesOnly` set to `true`, another with `inclusionKnowledgeBaseSysIds` listing only the sys IDs whose audience matches an IdP group. The 10,000-knowledge-bases-per-account-per-Region quota isn't the constraint here; the constraint is operational, which is why granularity stopped at audience rather than group.

**Authorization moves back into the application.** The `bedrock:Retrieve` permission is now granted through a distinct role per audience, with a `Condition` on the knowledge base's resource tag. The service answering the user resolves the group from the IdP token and assumes the matching role. That is more code than I would like — and it is the price of using a source with no ACL.

**sys ID filtering stopped being an optimization.** `inclusionServiceCatalogSysIds` and `inclusionKnowledgeArticleCategorySysIds` are scope control and sync-time control at once: the troubleshooting page attributes hours-long syncs precisely to their absence.

**Protected deletion.** I enabled `deletionProtectionConfiguration` with `deletionProtectionThreshold` at 15. If a sync tries to remove more than 15% of the index — which a user criteria mistake at the source triggers easily — the delete phase is skipped instead of emptying the assistant in production.

## ACL support by connector — what it changes in the design
| Criterion | Pre-retrieval ACL filter | Real-time verification | What it forces on you |
| --- | --- | --- | --- |
| ServiceNow | Not supported | Not supported | Segregate per knowledge base and authorize in IAM/the application; never mix audiences in one index. |
| SharePoint / OneDrive | Supported | Supported | Requires app-only auth (`ENTRA_ID_APP_ONLY` / `ENTRA_APP_ID`) and an email identical to the source's. |
| Google Drive | Supported | Supported | Domain-wide delegation with `SERVICE_ACCOUNT`; permission changes between syncs are caught at verification. |
| Confluence | Supported | Supported | Admin token for the real-time check, with `BASIC` auth — rotation becomes a runbook item. |
| Amazon S3 / Custom | Supported | Not supported | The ACL is your own file/metadata: permission freshness becomes your pipeline's responsibility. |
| Web Crawler | Not supported | Not applicable | Public content only; anything else is a leak by construction. |

## Identity: the detail that decides whether the mitigation works

## Identity: the detail that decides whether the mitigation works

Even on connectors that do carry ACLs, Managed Knowledge Base's identity model is narrower than most enterprise designs assume — worth knowing before you promise fine-grained segregation to the risk team.

**The universal identifier is email.** `userContext.userId` on `Retrieve` is always the user's email, and it must match exactly the email associated with that user in each connected data source. There is no alias resolution and no cross-identity-provider mapping. If the company carries two domains from an acquisition, half the people get zero results — silently, which is the worst failure mode available.

**Groups come from the last sync.** User-to-group membership is crawled at ingestion and resolved at query time from that snapshot. Real-time verification covers the window between syncs on the four connectors that support it; third-party IdP credentials are cached for up to one hour, and permission changes are eventually consistent, typically within minutes. For a termination, that is exposure time — treat revocation as an IdP and application event, not a knowledge base one.

**Missing ACL means inaccessible, not public.** A document with no extracted permissions in an ACL-enabled source is returned to nobody, and evaluation fails closed: a group-resolution error yields fewer results, never more. That is the correct behavior, and it is also the most common explanation for "the assistant got dumber after the deploy".

And the sentence the documentation insists on repeating: ACL-aware is filtering, not authorization. Authentication is yours.

## Reading it through the pillars

- **security**: The connector concentrates power in one service account holding `knowledge_admin` and `catalog_admin` — the documentation explicitly asks you **not** to add `admin`, `itil` or `snc_read_only`, and that restriction is the little least-privilege you get. The Secrets Manager secret holds `clientId`, `clientSecret` and `instanceUrl` in the same Region as the knowledge base; rotating means regenerating the client secret in the Application Registry, which is shown only once. Treat `knowledgeBaseId` as a security boundary and condition `bedrock:Retrieve` by tag.
- **reliability**: Incremental sync keys on `sys_updated_on`, so an article restored from backup at the source may never return to the index if the timestamp doesn't move. `deletionProtectionThreshold` (default 15%) keeps a bad sync from emptying the index. The ceilings that matter on a bad day: 200 data sources per knowledge base, 50 concurrent ingestion jobs, 10 TB of raw data per knowledge base, 600 RPM of `Retrieve` with a 25 RPS burst, and 300 RPM of `AgenticRetrieveStream` per account.

## Anti-patterns this retro put in writing

- **One knowledge base for the whole company:** mixing ServiceNow (no ACL) with SharePoint (ACL) in the same index lets the weakest source set the access level — non-ACL documents return to everyone, even with `userContext` on the call.
- **Treating `userContext` as access control:** it filters by the identity you assert, verifying nothing. Without upstream authentication it is a query parameter, not a boundary.
- **Crawling with no `filterConfiguration` on an enterprise instance:** it turns into an hours-long sync over 100,000-plus catalog items and fills the index with content nobody will ask about — at US$ 5.00 per GB per month to keep it.
- **Registering the OAuth application by inserting straight into `oauth_entity`:** the documentation requires the interceptor page; the shortcut yields a record that authenticates and then fails at the Table API, and you debug `401` in the wrong place.
- **Trusting source-side user criteria as an outbound control:** it is evaluated per user session inside ServiceNow. An integration account with `knowledge_admin` doesn't violate it — it is simply never subjected to it.

## What now gets measured before any release

## What now gets measured before any release

The retro doesn't end at a configuration fix; it ends at a signal. A RAG leak throws no error, shows no latency anomaly and never lands on an availability dashboard — it shows up as a useful answer for the wrong person. Three things joined the release checklist.

**A canary query suite.** A small set of questions whose correct answer is *silence*, one per audience, run against each knowledge base after every sync. It is access regression testing, it runs in seconds and it costs US$ 1.00 per thousand calls. The alternative is learning about it from the ombudsman.

**Document counts per sync, with an expected band.** The `statistics` object from `GetIngestionJob` reports how many documents were added, failed and removed. A sharp swing usually means a scope change at the source — a category moved, a catalog reactivated — before it means a platform problem. With `deletionProtectionThreshold` enabled, the sync that would skip its delete phase is exactly the event you want alarming.

**The origin of cited chunks.** Because the assistant returns citations, the `dataSourceId` of each retrieved chunk is free telemetry. If a restricted-audience knowledge base shows up in an open-channel answer, the alarm fires without anyone having to read the answer.

The connector saves weeks of hand-rolled pipeline — what it does not save is the design of who may see what. That part was never outsourceable.

> **Curator's note:** If I were putting this into production in a financial-grade environment tomorrow, I'd start with a single knowledge base fed by `crawlPublicKnowledgeArticlesOnly` set to `true` and nothing else — the set of articles already public to every employee — and only then open additional bases per audience, each with its own role and tag. The hard-won lesson this pilot reinforced: when a connector erases the source's permission model, the damage doesn't surface as a failure, it surfaces as quality. The assistant gets *better* when it leaks, because it has more context, and that is why nobody files a ticket. I learned to read the ACL support matrix before the connector's feature list, and to treat the sentence "all authenticated users who can query the knowledge base can see all crawled content" as an architecture requirement, not a footnote.

## References

- [AWS What's New — Amazon Bedrock Managed Knowledge Base now supports ServiceNow as a native data source connector (Sep 4,](https://aws.amazon.com/about-aws/whats-new/2026/09/amazon-bedrock-managed-knowledge-base-servicenow-native-data-source-connector/)
- [Amazon Bedrock User Guide — ServiceNow data source (supported features, ACL warning)](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-servicenow.html)
- [Amazon Bedrock User Guide — Set up OAuth 2.0 Client Credentials authentication for ServiceNow](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-servicenow-oauth2-setup.html)
- [Amazon Bedrock User Guide — Connect a ServiceNow data source (connector parameters, sys ID filters)](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-servicenow-connect.html)
- [Amazon Bedrock User Guide — Access Control Lists awareness enablement (connector support matrix)](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-acl.html)
- [Amazon Bedrock User Guide — Sync a data source and set a sync schedule](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-sync.html)
- [Amazon Bedrock User Guide — Service quotas for managed knowledge bases](https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-quotas.html)
- [AWS Machine Learning Blog — Build enterprise search for agents with Amazon Bedrock Managed Knowledge Base](https://aws.amazon.com/blogs/machine-learning/build-enterprise-search-for-agents-with-amazon-bedrock-managed-knowledge-base/)

## Verdict

Adopt the connector when the ServiceNow content you want indexed is already visible to the assistant's entire audience — public IT knowledge bases, an open service catalog, unrestricted HR FAQs — and when the cost of maintaining your own Table API pipeline, pagination, attachments and `sys_updated_on` incremental sync is real for your team. In that slice it is a good deal: weeks less code, native scheduling, and bulk-deletion protection by configuration. Don't adopt it as-is when the instance uses user criteria to separate audiences, when risk, legal or fraud runbook articles live in the same `kb_knowledge`, or when a regulatory requirement forces you to trace who could see what — because then the boundary isn't in the connector, it's in your knowledge base layout and the IAM around `Retrieve`. What AWS shipped is not outsourced access control — it is outsourced ingestion, and those two keep charging their maintenance cost to whoever always paid it: you.

**Rating:** Adotar com escopo explícito / Adopt with
