Authorization API and PDP¶
The authorization API is the most direct way for an application to ask Ranger "may this user do this to that resource?". You describe the user, the resource, and the permissions you need in a JSON document (or the equivalent Java/Python object), and Ranger answers with a decision plus any row filter or data mask the application must apply. The same request and response model is used whether the policies are evaluated inside your process or by a remote Ranger PDP (policy decision point) server.
Three Maven modules implement it:
authz-api(org.apache.ranger:ranger-authz-api)- The abstract
RangerAuthorizerclass, the request/response model classes, andRangerAuthorizerFactory. It contains no policy evaluation code. authz-embedded(org.apache.ranger:authz-embedded)RangerEmbeddedAuthorizerevaluates requests in-process with aRangerBasePluginper service. It downloads policies from Ranger Admin and writes audits.authz-remote(org.apache.ranger:authz-remote)RangerRemoteAuthorizerforwards each request over HTTP(S) to a Ranger PDP server (/authz/v1/...).
Because both implementations extend the same abstract class, an application can switch between embedded and
remote evaluation by changing one property (ranger.authorizer.impl.class) without touching its code.
Two integration styles in the code base
The authz-api and authz-embedded modules were introduced in Ranger 2.8.0; the authz-remote client and the PDP server followed in 2.9.0. The Polaris authorizer and the PDP server use it. Most in-tree
plugins (HDFS, Hive, HBase, Kafka, Ozone, ...) still use the older RangerBasePlugin /
RangerAccessRequest API from agents-common; that API is described in
Plugin architecture and Custom plugins.
Use the authz API for new integrations.
Concepts¶
The terminology below comes from authz-api/README.txt and the model classes in
authz-api/src/main/java/org/apache/ranger/authz/model/.
- User
- The actor performing the action: a name, and optionally
groups,roles, and free-formattributes(department, location, ...). Policies can match on any of these. - Resource
- The object being accessed. It is named as
resource-type:resource-value, for examplepath:/warehouse/hive/mktg/visitors,table:db1.tbl1ortable:default/sales. The part before the first:is the resource type, the last resource in a hierarchy of the service definition (for Hive:database/table/column). The value is split on/into the hierarchy levels; escape a literal/in a value with\/. (SeeRangerResourceNameParserinauthz-api.) A resource can also carryattributes(such asOWNER) andsubResources(for example the columns of a table) so that one request authorizes a table and several columns at once. - Action
- A label for what the caller is doing (
QUERY,LIST,CREATE). It is recorded in the audit log only; the decision is based onpermissions. - Permissions
- The access types, as defined in the service definition, that the action needs (
select,read,write, ...). A request can carry several; each is evaluated and reported separately. - Context
serviceType(the service-definition name, for examplehive),serviceName(the Ranger service whose policies apply, for exampledev_hive),accessTime,clientIpAddress,forwardedIpAddressesand anadditionalInfomap. Well-knownadditionalInfokeys areclientType,clusterName,clusterTypeandrequestData(constants onRangerAccessContext).- Decision
ALLOW,DENY,NOT_DETERMINED(no policy matched) orPARTIAL(RangerAuthzResult.AccessDecision). For a request with several permissions, anyDENYmakes the overall decisionDENY; otherwise anyNOT_DETERMINEDwins overALLOW.- Row filter / data mask
- When a policy applies, the response can carry a
rowFilter.filterExprfor the resource and adataMask(maskType,maskedValue) per sub-resource. Ranger does not enforce these; the application must add them to the query before it runs.
Request and response JSON¶
Single resource¶
{
"requestId": "hive-access-request",
"user": { "name": "gary.adams", "groups": [ "fte", "mktg" ], "roles": [ "analyst" ] },
"access": {
"resource": { "name": "table:default/sales", "attributes": { "OWNER": "nancy.boxer" } },
"action": "QUERY",
"permissions": [ "select" ]
},
"context": {
"serviceType": "hive",
"serviceName": "dev_hive",
"accessTime": 1755543894,
"clientIpAddress": "172.16.45.59",
"additionalInfo": { "clientType": "beeline", "clusterName": "cl1" }
}
}
{
"requestId": "hive-access-request",
"decision": "ALLOW",
"permissions": {
"select": {
"access": { "decision": "ALLOW", "policy": { "id": 1, "version": 1 } },
"rowFilter": { "filterExpr": "dept = 'mktg'", "policy": { "id": 11, "version": 3 } }
}
}
}
Resource with sub-resources¶
Add subResources to authorize a table and its columns in one round trip. The top-level access result is
derived from the sub-resource results, and each sub-resource can carry its own dataMask:
"access": {
"resource": {
"name": "table:db1/tbl1",
"subResources": [ "column:col1", "column:col2" ]
},
"action": "QUERY",
"permissions": [ "select" ]
}
"permissions": {
"select": {
"access": { "decision": "ALLOW" },
"rowFilter": { "filterExpr": "dept = 'mktg'", "policy": { "id": 11, "version": 3 } },
"subResources": {
"column:col1": { "access": { "decision": "ALLOW", "policy": { "id": 5, "version": 1 } },
"dataMask": { "maskType": "MASK_SHOW_LAST_4",
"maskedValue": "mask_show_last_n({col}, 4, 'x', 'x', 'x', -1, '1')",
"policy": { "id": 26, "version": 2 } } },
"column:col2": { "access": { "decision": "ALLOW", "policy": { "id": 2, "version": 1 } },
"dataMask": { "maskType": "MASK_HASH", "maskedValue": "mask_hash({col})",
"policy": { "id": 27, "version": 4 } } }
}
}
}
If a permission is denied, its dataMask and rowFilter are cleared in the response.
Multiple resources¶
RangerMultiAuthzRequest carries one user, one context and a list of accesses; the result contains a
list of per-access results plus an overall decision: ALLOW if every access is allowed, DENY if every
access is denied, NOT_DETERMINED if none could be determined, and PARTIAL for any mix.
{
"requestId": "4aa68265-34f1-4115-b026-d88dff292669",
"user": { "name": "gary.adams", "groups": [ "fte", "mktg" ] },
"accesses": [
{ "resource": { "name": "table:db1/tbl1" }, "action": "QUERY", "permissions": [ "select" ] },
{ "resource": { "name": "table:db1/tbl2" }, "action": "QUERY", "permissions": [ "select" ] },
{ "resource": { "name": "table:db1/vw1" }, "action": "CREATE", "permissions": [ "create" ] }
],
"context": { "serviceType": "hive", "serviceName": "dev_hive" }
}
Other operations¶
RangerAuthorizer has four operations. Each one maps to a PDP endpoint:
| Method | Path | Description |
|---|---|---|
POST |
/authz/v1/authorize |
authorize: one resource (with optional sub-resources), one or more permissions. |
POST |
/authz/v1/authorizeMulti |
authorize for several resources in one call. |
POST |
/authz/v1/permissions |
getResourcePermissions: effective permissions on a resource for every user, group and role. |
POST |
/authz/v1/filterResources |
filterResources: given a list of resources, return only those the user may access. |
The request and result classes of each operation are:
| Operation | Request class | Result class |
|---|---|---|
authorize |
RangerAuthzRequest |
RangerAuthzResult |
authorize (multi) |
RangerMultiAuthzRequest |
RangerMultiAuthzResult |
getResourcePermissions |
RangerResourcePermissionsRequest |
RangerResourcePermissions |
filterResources |
RangerFilterResourcesRequest |
RangerFilterResourcesResult |
getResourcePermissions is built from RangerBasePlugin.getResourceACLs. The default implementation of
filterResources calls authorize once per resource.
The PDP paths are declared in pdp/src/main/java/org/apache/ranger/pdp/rest/RangerPdpREST.java
(@Path("/v1") under the /authz context). Setting up and securing the server itself is covered in
Ranger PDP.
Validation errors¶
RangerAuthorizer validates every request before evaluation and throws RangerAuthzException with an error
code from RangerAuthzApiErrorCode, for example missing user info, missing resource name,
permissions is empty. Nothing to authorize, service name or service type is mandatory, or
invalid resource "..." - does not match template "...". accessTime defaults to the current time and a
missing additionalInfo map is created for you.
Java usage¶
Dependencies¶
<dependency>
<groupId>org.apache.ranger</groupId>
<artifactId>ranger-authz-api</artifactId>
<version>${ranger.version}</version>
</dependency>
<!-- pick one implementation -->
<dependency>
<groupId>org.apache.ranger</groupId>
<artifactId>authz-embedded</artifactId> <!-- in-process evaluation -->
<version>${ranger.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ranger</groupId>
<artifactId>authz-remote</artifactId> <!-- calls a PDP server -->
<version>${ranger.version}</version>
</dependency>
Create an authorizer once, authorize many times¶
import org.apache.ranger.authz.api.RangerAuthorizer;
import org.apache.ranger.authz.api.RangerAuthorizerFactory;
import org.apache.ranger.authz.model.*;
import org.apache.ranger.authz.model.RangerAuthzResult.AccessDecision;
import org.apache.ranger.authz.model.RangerAuthzResult.DataMaskResult;
import org.apache.ranger.authz.model.RangerAuthzResult.RowFilterResult;
Properties props = new Properties();
props.load(new FileInputStream("ranger-authz.properties"));
// ranger.authorizer.impl.class selects RangerEmbeddedAuthorizer (default) or RangerRemoteAuthorizer
RangerAuthorizer authorizer = RangerAuthorizerFactory.createAuthorizer(props);
authorizer.init();
RangerUserInfo user = new RangerUserInfo("alice");
RangerAccessInfo access = new RangerAccessInfo("table:sales/customers/accounts", "QUERY", "select");
RangerAccessContext ctx = new RangerAccessContext("hive", "dev_hive");
RangerAuthzRequest request = new RangerAuthzRequest(user, access, ctx);
RangerAuthzResult result = authorizer.authorize(request); // thread-safe
if (!AccessDecision.ALLOW.equals(result.getDecision())) {
throw new AccessDeniedException();
}
RowFilterResult rowFilter = result.getPermissions().get("select").getRowFilter();
if (rowFilter != null && rowFilter.getFilterExpr() != null) {
// add the filter expression to the query
}
DataMaskResult dataMask = result.getPermissions().get("select").getDataMask();
if (dataMask != null && dataMask.getMaskType() != null) {
// apply the mask expression to the projected column
}
authorizer.close(); // at shutdown
RangerAuthorizerFactory.createAuthorizer instantiates the class named by ranger.authorizer.impl.class
(default org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer) through its (Properties) constructor.
You can also construct RangerEmbeddedAuthorizer or RangerRemoteAuthorizer directly.
A runnable version of this flow is RemoteAuthzClient in
ranger-examples/sample-client:
it reads a request JSON file and a properties file and prints the result. The class is packaged in
ranger-<version>-sample-client.tar.gz, but the lib/ directory of that archive does not contain the
authz-remote jar or its Apache HttpClient dependency, so add them to the classpath:
java -cp "lib/*:<authz-remote jar and its dependencies>" \
org.apache.ranger.examples.pdpclient.RemoteAuthzClient request.json ranger-authz-remote-authn-header.properties
The sample request.json, and header/JWT/Kerberos property files, ship in
ranger-examples/sample-client/src/main/resources/ and in the root of the archive.
Embedded authorizer configuration¶
RangerEmbeddedAuthorizer creates one RangerBasePlugin per service name on demand, so a
single authorizer can serve several Ranger services. Configuration is a flat Properties object; the
prefixes below are mapped onto the standard plugin properties (ranger.plugin.<serviceType>.*) and audit
properties (xasecure.audit.*) by RangerAuthzConfig. A complete template is
authz-embedded/src/conf/ranger-authz-embedded.properties.
Services¶
These properties tell the authorizer which Ranger services it serves and how to resolve a request that names only a service or only a service type.
| Key | Default | Type | Description |
|---|---|---|---|
ranger.authz.init.services |
(none) | List | Service names whose plugins are created eagerly in init(); others are created on first request. |
ranger.authz.service.<name>.servicetype |
(none) | String | Service type of a service, used when a request gives only serviceName. |
ranger.authz.servicetype.<type>.default.service |
(none) | String | Service name to use when a request gives only serviceType. |
ranger.authz.app.type |
ranger-authz |
String | Application type used as the audit agentId/app name. |
Plugin property prefixes¶
Every plugin property (policy.rest.url, policy.pollIntervalMs, policy.cache.dir,
policy.rest.ssl.config.file, policy.rest.client.connection.timeoutMs, policy.rest.client.read.timeoutMs,
...) can be set at three levels by choosing a prefix. A more specific prefix overrides a more general one.
| Prefix | Applies to |
|---|---|
ranger.authz.default.<suffix> |
Every service, for example ranger.authz.default.policy.rest.url. |
ranger.authz.servicetype.<type>.<suffix> |
All services of one type. |
ranger.authz.service.<name>.<suffix> |
One service. |
ranger.authz.audit.<suffix> |
The audit framework; mapped to xasecure.audit.<suffix>, for example destination.solr, destination.solr.urls, destination.hdfs.dir, destination.log4j. |
Native plugin property names (ranger.plugin.<type>.* and xasecure.*) are honored as well and override the
prefixed forms. Precedence for a service: default < servicetype < service < ranger.plugin.<type>.*.
ranger.authz.init.services=dev_hive
ranger.authz.service.dev_hive.servicetype=hive
ranger.authz.servicetype.hive.default.service=dev_hive
ranger.authz.default.policy.rest.url=http://localhost:6080
ranger.authz.default.policy.pollIntervalMs=30000
ranger.authz.default.policy.cache.dir=/etc/ranger/policycache
# authentication of the plugin to Ranger Admin: basic, JWT or Kerberos
ranger.authz.service.dev_hive.policy.rest.client.username=
ranger.authz.service.dev_hive.policy.rest.client.password=
# ranger.authz.service.dev_hive.policy.rest.client.jwt.source=env|file|cred
# ranger.authz.service.dev_hive.policy.rest.client.jwt.supplier=<class implementing java.util.function.Supplier<String>>
# ranger.authz.service.dev_hive.ugi.initialize=true
# ranger.authz.service.dev_hive.ugi.login.type=keytab
# ranger.authz.service.dev_hive.ugi.keytab.principal=
# ranger.authz.service.dev_hive.ugi.keytab.file=
ranger.authz.audit.destination.log4j=enabled
ranger.authz.audit.destination.log4j.logger=ranger_audit
The template also shows alternative policy sources for tests and offline use:
ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.EmbeddedResourcePolicySource with
policy.source.embedded_resource.path, or ...LocalFolderPolicySource with policy.source.local_folder.path.
Remote authorizer configuration¶
RangerRemoteAuthorizer sends each request to a PDP server. Set ranger.authorizer.impl.class to
org.apache.ranger.authz.remote.RangerRemoteAuthorizer and configure the properties below (constants in
RangerRemoteAuthzConfig; template in
authz-remote/src/conf/ranger-authz-remote.properties).
Connection¶
| Key | Default | Type | Description |
|---|---|---|---|
ranger.authz.remote.pdp.url |
(none) | URL | Required. PDP base URL, e.g. http://localhost:6500. /authz/v1 is appended unless already present. |
ranger.authz.remote.pdp.connect.timeout.ms |
5000 |
Duration (ms) | Connection timeout. |
ranger.authz.remote.pdp.read.timeout.ms |
30000 |
Duration (ms) | Read timeout. |
ranger.authz.remote.header.<name> |
(none) | String | Extra HTTP header sent with every call. |
Authentication¶
The client authenticates to the PDP with a trusted header, a JWT bearer token or Kerberos (SPNEGO).
| Key | Default | Type | Description |
|---|---|---|---|
ranger.authz.remote.authn.type |
none |
Enum | One of none, header, jwt, kerberos. |
ranger.authz.remote.authn.header.<name> |
(none) | String | For header: header to send, e.g. ranger.authz.remote.authn.header.X-Forwarded-User=test-user. |
ranger.authz.remote.authn.jwt.source |
(none) | Enum | For jwt: where the token comes from, env or file. |
ranger.authz.remote.authn.jwt.env |
(none) | String | Environment variable holding the bearer token. |
ranger.authz.remote.authn.jwt.file |
(none) | Path | File holding the bearer token. |
Kerberos¶
| Key | Default | Type | Description |
|---|---|---|---|
ranger.authz.remote.authn.kerberos.principal |
(none) | String | Client principal. Required for kerberos. |
ranger.authz.remote.authn.kerberos.keytab |
(none) | Path | Keytab of the client principal. Required for kerberos. |
ranger.authz.remote.authn.kerberos.debug |
false |
Boolean | Enable JDK Kerberos debug output. |
ranger.authz.remote.authn.kerberos.spnego.strip.port |
true |
Boolean | Build the SPNEGO service name without the port. |
ranger.authz.remote.authn.kerberos.spnego.use.canonical.hostname |
true |
Boolean | Canonicalize the host in the SPNEGO service name. |
ranger.authz.remote.authn.kerberos.jaas.context.name |
RangerRemoteClientKerberos |
String | JAAS context name. |
ranger.authz.remote.authn.kerberos.jaas.login.module |
com.sun.security.auth.module.Krb5LoginModule |
Class | JAAS login module. |
ranger.authz.remote.authn.kerberos.jaas.store.key |
true |
Boolean | JAAS storeKey option. |
ranger.authz.remote.authn.kerberos.jaas.is.initiator |
true |
Boolean | JAAS isInitiator option. |
ranger.authz.remote.authn.kerberos.jaas.do.not.prompt |
true |
Boolean | JAAS doNotPrompt option. |
ranger.authz.remote.authn.kerberos.jaas.use.ticket.cache |
false |
Boolean | JAAS useTicketCache option. |
ranger.authz.remote.authn.kerberos.jaas.refresh.krb5.config |
true |
Boolean | JAAS refreshKrb5Config option. |
TLS¶
| Key | Default | Type | Description |
|---|---|---|---|
ranger.authz.remote.ssl.truststore.file |
(none) | Path | Truststore holding the PDP certificate. |
ranger.authz.remote.ssl.truststore.password |
(none) | Password | Truststore password. |
ranger.authz.remote.ssl.truststore.type |
PKCS12 |
String | Truststore type. |
ranger.authz.remote.ssl.keystore.file |
(none) | Path | Client keystore for mutual TLS. |
ranger.authz.remote.ssl.keystore.password |
(none) | Password | Keystore password. |
ranger.authz.remote.ssl.keystore.type |
PKCS12 |
String | Keystore type. |
ranger.authz.remote.ssl.disable.hostname.verification |
false |
Boolean | Skip hostname verification (testing only). |
ranger.authorizer.impl.class=org.apache.ranger.authz.remote.RangerRemoteAuthorizer
ranger.authz.remote.pdp.url=http://localhost:6500
ranger.authz.remote.authn.type=jwt
ranger.authz.remote.authn.jwt.source=env
ranger.authz.remote.authn.jwt.env=RANGER_PDP_JWT
Delegation and fail-closed behavior
The PDP only lets trusted callers authorize on behalf of another user (user.name different from the
authenticated caller) or supply user groups, roles and attributes or resource attributes; other callers
receive 403 FORBIDDEN. And a
transport failure is not a decision: treat a timeout or connection error as a denial unless your
application has an explicitly designed fallback.
Choosing embedded or remote¶
flowchart LR
subgraph App["Application (Java)"]
E[RangerEmbeddedAuthorizer]
end
subgraph App2["Application (any language)"]
R[RangerRemoteAuthorizer / REST client]
end
A[(Ranger Admin)] -->|policies, tags, roles| E
A -->|policies, tags, roles| P[Ranger PDP server]
R -->|POST /authz/v1/authorize| P
E --> S[(audit store)]
P --> S
| Aspect | Embedded (authz-embedded) |
Remote (authz-remote, PDP REST) |
|---|---|---|
| Where policies are evaluated | In the application JVM | In the PDP server |
| Latency | Local, no network call per request | One HTTP round trip per request |
| Dependencies | Ranger plugin libraries on the classpath | The authz-remote client, or any language via REST |
| Policy freshness | Plugin polls Admin (policy.pollIntervalMs), keeps a local cache |
Managed by the PDP |
| Audit | Written by the application's audit provider | Written by the PDP |
| Availability | Works from cache if Admin is down | Depends on PDP availability |
Further reading¶
- Ranger PDP service — installing and securing the PDP server.
- Python client —
RangerPDPClientfor the same endpoints. - Client libraries overview.
- Blog: Integrating applications with Apache Ranger.
- Source:
authz-api/README.txt,authz-remote/README.md.