Apache Kylin¶
Apache Kylin is an OLAP engine that organizes cubes and models into projects. Kylin's own access control works at the project level with four permission levels: query, operation, management and admin. The Ranger Kylin plugin lets you manage those project permissions centrally in Ranger, for users and groups, with Ranger auditing.
The plugin runs inside the Kylin server as an external ACL provider
(org.apache.ranger.authorization.kylin.authorizer.RangerKylinAuthorizer, registered in
kylin.properties). Whenever Kylin checks a project permission it calls the plugin, which answers from
policies downloaded from Ranger Admin, cached locally and enforced even if Ranger Admin is unavailable.
Requirements¶
- A Ranger Admin instance that every Kylin server can reach over HTTP or HTTPS.
- An audit store if auditing is enabled.
- Apache Kylin with the
ExternalAclProviderextension point, which exists in Kylin 2.x to 4.x. Ranger master builds the plugin against Kylin 4.0.4 (kylin.versionin the rootpom.xml). - The plugin jars from the
ranger-<version>-kylin-pluginarchive built by Ranger. Copy the contents of itslib/directory (the shim jars and theranger-kylin-plugin-impl/directory) intotomcat/webapps/kylin/WEB-INF/libof every Kylin server.
Configuration¶
Activate the plugin by registering the Ranger class as the external ACL provider in kylin.properties:
# MANDATORY: makes the Ranger plugin the external ACL provider of Kylin.
kylin.server.external-acl-provider=org.apache.ranger.authorization.kylin.authorizer.RangerKylinAuthorizer
Place the Ranger configuration files described below in the Kylin conf/ directory, which is on the
server's classpath, and restart Kylin. The plugin is working when the policy cache file
kylin_<service>.json appears in the cache directory and the plugin is listed under
Audit → Plugin Status in Ranger Admin.
ranger-kylin-security.xml¶
This file names the Ranger service whose policies are enforced, tells the plugin where Ranger Admin is, and
controls how policies are downloaded and cached. The plugin loads it from the classpath, so place it in
the Kylin conf/ directory. ranger.plugin.kylin.service.name and
ranger.plugin.kylin.policy.rest.url are mandatory; every other property has a working default.
<configuration>
<!-- Connection to Ranger Admin -->
<property>
<name>ranger.plugin.kylin.service.name</name>
<value>dev_kylin</value>
<description>MANDATORY: Name of the service in Ranger Admin whose policies this plugin
enforces.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.url</name>
<value>http://ranger-admin:6080</value>
<description>MANDATORY: URL of Ranger Admin. Separate several URLs with commas for Ranger Admin
high availability.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.ssl.config.file</name>
<value>/opt/kylin/conf/ranger-policymgr-ssl.xml</value>
<description>Path to ranger-policymgr-ssl.xml. Needed only when the Ranger Admin URL uses https.
Default: not set.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.client.username</name>
<value></value>
<description>User for HTTP Basic authentication to Ranger Admin when Kerberos is not used.
Default: not set.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.client.password</name>
<value></value>
<description>Password for that user. Default: not set.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.client.connection.timeoutMs</name>
<value>120000</value>
<description>Connection timeout for calls to Ranger Admin. Unit: milliseconds.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.client.read.timeoutMs</name>
<value>30000</value>
<description>Read timeout for calls to Ranger Admin. Unit: milliseconds.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.client.max.retry.attempts</name>
<value>3</value>
<description>Number of retries for a failed call to Ranger Admin.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.rest.client.retry.interval.ms</name>
<value>1000</value>
<description>Wait between retries. Unit: milliseconds.</description>
</property>
<!-- Policy refresh and cache -->
<property>
<name>ranger.plugin.kylin.policy.cache.dir</name>
<value>/etc/ranger/dev_kylin/policycache</value>
<description>Directory for the local policy cache (kylin_<service>.json), writable by the
process user. Lets the plugin start with the last known policies when Ranger Admin is
unreachable. Default: not set.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.pollIntervalMs</name>
<value>30000</value>
<description>How often the plugin asks Ranger Admin for policy changes. Unit:
milliseconds.</description>
</property>
<property>
<name>ranger.plugin.kylin.policy.source.impl</name>
<value>org.apache.ranger.admin.client.RangerAdminRESTClient</value>
<description>Class that retrieves policies from Ranger Admin.</description>
</property>
<!-- Authorization behavior -->
<property>
<name>ranger.plugin.kylin.super.users</name>
<value></value>
<description>Comma-separated users that are allowed without policy evaluation. Default: not
set.</description>
</property>
<property>
<name>ranger.plugin.kylin.super.groups</name>
<value></value>
<description>Comma-separated groups whose members are allowed without policy evaluation.
Default: not set.</description>
</property>
<property>
<name>ranger.plugin.kylin.audit.exclude.users</name>
<value></value>
<description>Comma-separated users whose accesses are not audited. Default: not
set.</description>
</property>
<property>
<name>ranger.plugin.kylin.audit.exclude.groups</name>
<value></value>
<description>Comma-separated groups whose members' accesses are not audited. Default: not
set.</description>
</property>
<property>
<name>ranger.plugin.kylin.audit.exclude.roles</name>
<value></value>
<description>Comma-separated roles whose members' accesses are not audited. Default: not
set.</description>
</property>
<!-- Users, groups and roles -->
<property>
<name>ranger.plugin.kylin.use.rangerGroups</name>
<value>false</value>
<description>Add the groups Ranger knows for the user (from UserSync) to each
request.</description>
</property>
<property>
<name>ranger.plugin.kylin.use.only.rangerGroups</name>
<value>false</value>
<description>Ignore the groups supplied by the component and use only the groups Ranger knows
for the user.</description>
</property>
</configuration>
ranger-kylin-audit.xml¶
This file selects where the plugin sends audit events; place it next to ranger-kylin-security.xml. Each
destination is switched on with xasecure.audit.destination.<name>=true and configured with properties
under the same prefix. No property is mandatory: without an enabled destination, no audit events are
stored. The example sends audits to Solr.
<configuration>
<!-- General -->
<property>
<name>xasecure.audit.is.enabled</name>
<value>true</value>
<description>Master switch for auditing in this plugin.</description>
</property>
<property>
<name>xasecure.audit.provider.summary.enabled</name>
<value>false</value>
<description>Collapse events that differ only in time into one event with a count.</description>
</property>
<!-- Audit Server destination -->
<property>
<name>xasecure.audit.destination.auditserver</name>
<value>false</value>
<description>Send audits to the Ranger Audit Server.</description>
</property>
<property>
<name>xasecure.audit.destination.auditserver.url</name>
<value></value>
<description>Audit Server URL. Default: not set.</description>
</property>
<!-- Solr destination -->
<property>
<name>xasecure.audit.destination.solr</name>
<value>true</value>
<description>Send audits to Apache Solr. Default: false.</description>
</property>
<property>
<name>xasecure.audit.destination.solr.urls</name>
<value>http://solr:8983/solr/ranger_audits</value>
<description>Solr collection URLs, separated by commas. Ignored when
xasecure.audit.destination.solr.zookeepers is set. Default: not set.</description>
</property>
<property>
<name>xasecure.audit.destination.solr.zookeepers</name>
<value></value>
<description>ZooKeeper connect string of a SolrCloud cluster. Default: not set.</description>
</property>
<property>
<name>xasecure.audit.destination.solr.batch.filespool.dir</name>
<value>/var/log/kylin/audit/solr/spool</value>
<description>Local directory where events are spooled while Solr is unreachable. Every enabled
destination has the same property under its own prefix. Default: not set.</description>
</property>
<property>
<name>xasecure.audit.destination.solr.collection</name>
<value>ranger_audits</value>
<description>Collection name when ZooKeeper is used.</description>
</property>
<!-- Elasticsearch destination -->
<property>
<name>xasecure.audit.destination.elasticsearch</name>
<value>false</value>
<description>Send audits to Elasticsearch.</description>
</property>
<property>
<name>xasecure.audit.destination.elasticsearch.urls</name>
<value></value>
<description>Elasticsearch host names, separated by commas. Default: not set.</description>
</property>
<property>
<name>xasecure.audit.destination.elasticsearch.port</name>
<value>9200</value>
<description>REST port of the Elasticsearch cluster.</description>
</property>
<property>
<name>xasecure.audit.destination.elasticsearch.protocol</name>
<value>http</value>
<description>One of: http, https.</description>
</property>
<property>
<name>xasecure.audit.destination.elasticsearch.index</name>
<value>ranger_audits</value>
<description>Index that receives the events.</description>
</property>
<!-- HDFS destination -->
<property>
<name>xasecure.audit.destination.hdfs</name>
<value>false</value>
<description>Write audits as files to HDFS or a Hadoop-compatible object store.</description>
</property>
<property>
<name>xasecure.audit.destination.hdfs.dir</name>
<value></value>
<description>Base directory, for example hdfs://namenode:8020/ranger/audit. Default: not
set.</description>
</property>
<!-- Log4j destination -->
<property>
<name>xasecure.audit.destination.log4j</name>
<value>false</value>
<description>Write audits as JSON to a logger of the host process.</description>
</property>
<property>
<name>xasecure.audit.destination.log4j.logger</name>
<value>ranger.audit.log4j</value>
<description>Logger name used by the log4j destination.</description>
</property>
</configuration>
Give every enabled destination a spool directory (xasecure.audit.destination.<name>.batch.filespool.dir)
so that events survive an outage of the audit store. The queue, spool, Kerberos and TLS options of each
destination, and the Audit Server client settings, are in the
Audit framework reference.
ranger-policymgr-ssl.xml¶
This file is needed only when Ranger Admin is reached over https. The plugin loads it from the path set in
ranger.plugin.kylin.policy.rest.ssl.config.file; a file named
ranger-kylin-policymgr-ssl.xml on the classpath is picked up automatically. No property is mandatory:
without a truststore the plugin relies on the default truststore of the JVM, and the keystore is needed only
for two-way TLS. Passwords are not stored in the file: they are read from a Hadoop credential store (JCEKS)
under fixed aliases.
<configuration>
<!-- Keystore (client certificate, two-way TLS) -->
<property>
<name>xasecure.policymgr.clientssl.keystore</name>
<value></value>
<description>Keystore with the plugin's client certificate. Needed only when Ranger Admin
requires client certificates. Default: not set.</description>
</property>
<property>
<name>xasecure.policymgr.clientssl.keystore.credential.file</name>
<value></value>
<description>Hadoop credential store (JCEKS) that holds the keystore password under the alias
sslKeyStore. Default: not set.</description>
</property>
<property>
<name>xasecure.policymgr.clientssl.keystore.type</name>
<value>jks</value>
<description>Keystore type.</description>
</property>
<!-- Truststore -->
<property>
<name>xasecure.policymgr.clientssl.truststore</name>
<value>/opt/kylin/conf/ranger-plugin-truststore.jks</value>
<description>Truststore that contains the Ranger Admin certificate or its CA. When no truststore
is configured, the default truststore of the JVM is used. Default: not set.</description>
</property>
<property>
<name>xasecure.policymgr.clientssl.truststore.credential.file</name>
<value>jceks://file/etc/ranger/dev_kylin/cred.jceks</value>
<description>Hadoop credential store (JCEKS) that holds the truststore password under the alias
sslTrustStore. Default: not set.</description>
</property>
<property>
<name>xasecure.policymgr.clientssl.truststore.type</name>
<value>jks</value>
<description>Truststore type.</description>
</property>
</configuration>
When Ranger Admin validates client certificates, set commonNameForCertificate in the service configuration
to the CN of the plugin's certificate. See Security hardening.
Service definition in Ranger Admin¶
Create a service of type kylin in Ranger Admin. Its name must equal ranger.plugin.kylin.service.name
on the Kylin servers.
| Field | Required | Description |
|---|---|---|
username |
Yes | Kylin user for the connection test and resource lookup. |
password |
Yes | Password for that user, sent with HTTP Basic authentication. |
kylin.url |
Yes | Kylin URL, for example http://kylin-host:7070. Separate several URLs with , or ;. |
commonNameForCertificate |
No | Expected CN of the plugin's client certificate. |
Test Connection and lookup call GET /kylin/api/projects to autocomplete project names
(KylinClient).
Resources and permissions¶
The service definition is
ranger-servicedef-kylin.json.
It sets enableDenyAndExceptionsInPolicies=false, so only allow policies can be written.
There is one resource, project (label Kylin Project). It accepts wildcards, is matched
case-insensitively and offers lookup; it does not support the exclude flag.
| Access type | Kylin permission |
|---|---|
QUERY |
Run queries in the project |
OPERATION |
Build and refresh cubes |
MANAGEMENT |
Edit models and cubes |
ADMIN |
Administer the project |
No access type implies another. No policy conditions, masking, row filters or context enrichers are defined.
How Kylin requests map to policies¶
Kylin calls checkPermission(user, groups, entityType, entityUuid, permission). The plugin:
- resolves the project name from the entity UUID when the entity type is a project instance
(
ProjectManager.getPrjByUuid); if the project cannot be found the resource is set to*; - converts the Spring Security ACL permission with Kylin's
ExternalAclProvider.transformPermissionintoQUERY,OPERATION,MANAGEMENTorADMIN; - evaluates a Ranger request with the user, the groups Kylin supplies and that access type.
getAcl() (listing ACL entries) is not supported and returns null; manage grants in Ranger.
Default policies¶
When the service is created, Ranger Admin generates the all - project policy. The Kylin service class adds
nothing to it. Grant each user or group the access type that matches the Kylin permission level they need
on their projects.
Behavior notes¶
- Scope. Only project-level permissions go through the external ACL provider. Kylin's own authentication (and its system-level admin role) still apply.
- Allow-only. Deny policies, exceptions and resource excludes are not available for this service type.
- Client IP. The plugin records the Kylin server's own address (
InetAddress.getLocalHost()) as the client IP, so IP-based conditions are not useful. - Unknown project UUIDs are evaluated against
project=*; a policy on all projects therefore also covers such requests.
Auditing¶
Each permission check writes one audit event with user, groups, project, access type, policy id and
result. The Kylin service definition ships no default audit filters, so add
ranger.plugin.audit.filters to the service configuration if you need to reduce volume. See
audit filters.