Skip to main content

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 DDIC or SAP*.
  • 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.

ObjectFieldValueWhy
S_RFCRFC_TYPE / RFC_NAME / ACTVTFUGR / SRFC / 16RFC_PING, RFC_SYSTEM_INFO — the connection itself
S_RFCRFC_TYPE / RFC_NAME / ACTVTFUGR / RFC_METADATA / 16The SDK's bulk metadata fetch. Every call needs a descriptor first, so a gap here fails everything
S_RFCRFC_TYPE / RFC_NAME / ACTVTFUGR / RFC1 / 16The per-function metadata fallback, used when the bulk fetch is unavailable
S_RFCRFC_TYPE / RFC_NAME / ACTVTFUGR / SDIFRUNTIME / 16DDIC lookups behind the metadata fetch
S_RFCRFC_TYPE / RFC_NAME / ACTVTFUGR / SUSR / 16AUTHORITY_CHECK, which is how the verification query reaches a verdict

What the extraction needs

ObjectFieldValueWhy
S_RFCRFC_TYPE / RFC_NAME / ACTVTFUGR / LT_DHAPE_REMOTE / 16Create, drive and stop a pipeline graph
S_RFCRFC_TYPE / RFC_NAME / ACTVTFUGR / LT_DHAMB_REMOTE / 16Browse, describe and preview CDS entities
S_DHAPEAC2ACTVT16Run a graph at all
S_DHAPEOPRDHAPEOPNM / ACTVTcom.sap.abap.cds.reader.v2 / 16The operator that extracts
S_DHAPEOPRDHAPEOPNM / ACTVTcom.sap.abap.internal.outport / 16The outport the engine synthesises for every graph
S_DHAPEOPRDHAPEOPNM / ACTVTcom.sap.abap.subscr.reader.v1 / 16List subscriptions
S_DHAPEOPRDHAPEOPNM / ACTVTcom.sap.abap.subscr.eraser.v1 / 16Erase a subscription
S_DHAMBACTDHAMB_ACVTBR, DF, PVBrowse, read a definition, preview — the three browser activities used
S_DHAMBCDSDHBASCDSNM / DHBASCDSRS / ACTVTthe explicit entity list / C1 / 03, 33Display 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:

ObjectSourceIn ZERPL_APE?
S_DHAMBCDSCDS viewsyes
S_DHAMBSLTSLT mass transfersno
S_DHAMBSAPODP_SAPI extractorsno
S_DHAMBBWODP_BWno
S_DHAMBTABdatabase tablesno
S_DHAMBVWdatabase viewsno

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_DHAPEOPR is checked by CL_DHAPE_OPERATOR_REGISTRY once 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 — provided S_DHAPEOP is 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:

verdictMeaning
okCorrect — either a required grant is present, or the forbidden one is absent
missingA required grant is not there
granted, and must not beS_DHAPEOP is held and defeats the operator restriction
unknownNo 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, subobject ACP_JOB.
  • Operator verdicts are cached per session. CL_DHAPE_AUTHORITY holds its operator cache in CLASS-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?