The ZERPL_APE Role
A handout for the Basis team asked to authorise CDS extraction through the ABAP Pipeline Engine. By the end of this page you will have:
- ✅ The exact objects, fields and values to grant — no guesswork
- ✅ The one object that must not be granted, and why
- ✅ A single SQL query that verifies the result instead of trusting it
Everything below was read off a live system. The objects and their fields come from TOBJ and
the activities from TACTZ — but the values come from the ABAP classes that perform the
checks, because TOBJ says which fields exist and nothing about what is passed to them. That is
why some values look oddly specific (C1, BR, 16).
Prerequisites
- A dedicated communication/RFC user. Do not reuse
DDICorSAP*. - The list of CDS entities in scope for the engagement. You will need it: the role names them explicitly rather than using a wildcard.
What ERPL installs in SAP
Nothing. It drives the ABAP Pipeline Engine (DHAPE_*) and the ABAP Metadata Browser
(DHAMB_*), both of which ship with the system. No transport, no Z objects, no ABAP.
What the connection needs before anything else
Easy to leave out, and nothing works without them — including the verification query at the bottom of this page, which is how you would find out.
| Object | Field | Value | Why |
|---|---|---|---|
S_RFC | RFC_TYPE / RFC_NAME / ACTVT | FUGR / SRFC / 16 | RFC_PING, RFC_SYSTEM_INFO — the connection itself |
S_RFC | RFC_TYPE / RFC_NAME / ACTVT | FUGR / RFC_METADATA / 16 | The SDK's bulk metadata fetch. Every call needs a descriptor first, so a gap here fails everything |
S_RFC | RFC_TYPE / RFC_NAME / ACTVT | FUGR / RFC1 / 16 | The per-function metadata fallback, used when the bulk fetch is unavailable |
S_RFC | RFC_TYPE / RFC_NAME / ACTVT | FUGR / SDIFRUNTIME / 16 | DDIC lookups behind the metadata fetch |
S_RFC | RFC_TYPE / RFC_NAME / ACTVT | FUGR / SUSR / 16 | AUTHORITY_CHECK, which is how the verification query reaches a verdict |
What the extraction needs
| Object | Field | Value | Why |
|---|---|---|---|
S_RFC | RFC_TYPE / RFC_NAME / ACTVT | FUGR / LT_DHAPE_REMOTE / 16 | Create, drive and stop a pipeline graph |
S_RFC | RFC_TYPE / RFC_NAME / ACTVT | FUGR / LT_DHAMB_REMOTE / 16 | Browse, describe and preview CDS entities |
S_DHAPEAC2 | ACTVT | 16 | Run a graph at all |
S_DHAPEOPR | DHAPEOPNM / ACTVT | com.sap.abap.cds.reader.v2 / 16 | The operator that extracts |
S_DHAPEOPR | DHAPEOPNM / ACTVT | com.sap.abap.internal.outport / 16 | The outport the engine synthesises for every graph |
S_DHAPEOPR | DHAPEOPNM / ACTVT | com.sap.abap.subscr.reader.v1 / 16 | List subscriptions |
S_DHAPEOPR | DHAPEOPNM / ACTVT | com.sap.abap.subscr.eraser.v1 / 16 | Erase a subscription |
S_DHAMBACT | DHAMB_ACVT | BR, DF, PV | Browse, read a definition, preview — the three browser activities used |
S_DHAMBCDS | DHBASCDSNM / DHBASCDSRS / ACTVT | the explicit entity list / C1 / 03, 33 | Display and read each entity in scope |
Two restrictions worth arguing for
DHBASCDSNM should be the explicit list of entities, not *. The extraction is agreed per
engagement, so the role should say which entities that is. A wildcard makes the agreement
unenforceable and turns any later scope question into a code review instead of a role review.
DHBASCDSRS should be C1. The field is the entity's release state, derived per entity by
CL_DHAMB_AUTH_CDS::get_release_state: C1 when the entity is released, NO when it has no
release contract. An unreleased entity may change shape without notice, and ERPL refuses to
extract from one by default for the same reason. Keeping the restriction in the role means the
refusal does not depend on a client-side setting.
Do not grant S_DHAPEOP
Not a typo for S_DHAPEOPR. It is a separate, older object keyed on an operator's
implementation class rather than its name, and it is a fallback: when the S_DHAPEOPR
check fails, CL_DHAPE_AUTHORITY::check_operator looks up the operator's BAdI implementation and
checks S_DHAPEOP on DHAPEOPIMP instead.
A user holding it — from this role or from any other role they happen to have — is authorised for
operators that S_DHAPEOPR denies, and the restriction the rest of this page rests on quietly
stops holding. This is the one row the verification query reports inverted: there,
present = true is the finding.
Objects this role deliberately does not ask for
S_DHAPEACT is not required, though the engine's own factory suggests otherwise. It is the
second pipeline activity object — two-character codes (AC, CR, SF, ST, DE) on its own
field DHAPEACTVT, checked by CL_DHAPE_AUTHORITY::check_activity. Reading the source implies a
role needs both; measuring says it does not. A test user holding none of it passes the entire
extraction test suite, so that method is not on any path this module drives. Granting it would be
granting something unused.
S_DHAMBOBJ is not required. It exists in TOBJ, but no class in the DHAMB stack on current
releases checks it, so asking you for values would be asking you to guess.
What the role deliberately cannot reach
This is the part worth reviewing carefully, because it is where the module's central claim becomes checkable. ERPL's pipeline path exists because SAP Note 3255746 restricts third-party use of the ODP RFC API; it reads CDS entities and nothing else.
The metadata browser has one authorization object per source kind. The role above grants exactly one of them:
| Object | Source | In ZERPL_APE? |
|---|---|---|
S_DHAMBCDS | CDS views | yes |
S_DHAMBSLT | SLT mass transfers | no |
S_DHAMBSAP | ODP_SAPI extractors | no |
S_DHAMBBW | ODP_BW | no |
S_DHAMBTAB | database tables | no |
S_DHAMBVW | database views | no |
S_LTAMBACT is absent for the same reason: the system carries a second metadata browser in the
LTAMB namespace whose authority factory dispatches tables, SLT, views, ODP_BW and ODP_SAPI —
and no CDS. ERPL calls nothing in it.
The restriction is enforced twice over:
- In the software, by a compiled-in allow-list of pipeline operators that no setting widens.
- In your role, by the objects above.
S_DHAPEOPRis checked byCL_DHAPE_OPERATOR_REGISTRYonce per operator a graph names, keyed on the operator name, so a role granting only the four operators listed cannot drive an ODP or SLT operator even if the software tried to — providedS_DHAPEOPis not granted, per above.
The second is the one you can verify without reading our source, and the one that still holds if a future version of the software changes.
Verifying it
From DuckDB, connected as the user you created:
SELECT * FROM sap_ape_check_authorizations('YOUR_CDS_ENTITY');
Read the verdict column, not present:
verdict | Meaning |
|---|---|
ok | Correct — either a required grant is present, or the forbidden one is absent |
missing | A required grant is not there |
granted, and must not be | S_DHAPEOP is held and defeats the operator restriction |
unknown | No verdict was reached. Never read this as a pass; note says why |
So the gaps query is:
SELECT auth_object, checked_values, verdict, note
FROM sap_ape_check_authorizations('YOUR_CDS_ENTITY')
WHERE verdict <> 'ok';
An empty result means the role is complete.
unknown has three ordinary causes, each named in note: no entity was passed and the row is
checked per entity; the user is locked; or the connection or AUTHORITY_CHECK itself could not be
reached — which usually means the S_RFC grant for SUSR is missing. A broken connection reports
every row as unknown with the reason rather than failing the query, because that is exactly when
you need the list.
Each requirement is probed live with AUTHORITY_CHECK, which reports through its exceptions. The
requirement list itself is compiled in, so the query answers "does this user have what the
software needs", not "what did the software feel like asking for today".
Operational notes
- Delta extraction creates trigger-based change capture. A first delta read on an entity
generates DHCDC logging tables and triggers on the underlying tables, and they persist until
the subscription is dropped.
sap_ape_show_subscriptions()lists what exists;PRAGMA sap_ape_drop(entity, subscriber_process)removes one. A snapshot read creates a subscription for the duration of the scan and erases it when the scan ends. - Background jobs. SAP prepares an extraction with a DHCDC job; while it is pending the
engine returns neither data nor an error. Batch work processes must be available or reads
appear to hang. The application log to check is object
DHCDC, subobjectACP_JOB. - Operator verdicts are cached per session.
CL_DHAPE_AUTHORITYholds its operator cache inCLASS-DATA, so a grant you revoke is not observed until the session ends. When testing role changes, use a fresh connection. - A client killed mid-scan leaves its graph running, and the engine then refuses to erase the subscription that graph holds. Recovery is the engine's own retention mechanism.
What's Next?
- APE Protocol Deep Dive - What the extraction actually does
- APE Delta and Recovery - Subscriptions and at-least-once delivery
- Security Overview - Authentication and secrets across all ERPL protocols