🔗Perimeter Security

🔗Enabling Perimeter Security

Follow the instructions below for enabling perimeter security, either for Standalone CDAP or Distributed CDAP, depending on your installation. Client authentication, once security has been enabled, is described in the Developers' Manual section Client Authentication.

🔗Enabling Perimeter Security (Standalone CDAP)

To enable security in Standalone CDAP, add these properties to cdap-site.xml:

Property Value Description
security.enabled true Enables authentication for CDAP. When set to true all requests to CDAP must provide a valid access token.
security.auth.server.announce.address   CDAP Authentication service announce address, in the format of host:port. This is the address that clients should use to communicate with the Authentication Server. Leave empty (the default value) to use the default address generated by the Authentication Server.
security.auth.server.bind.address 0.0.0.0 IP address that the CDAP Authentication Server should bind to (default value shown)
security.auth.server.bind.port 10009 CDAP Authentication service bind port (default value shown)

Client Authentication then needs to be configured, as described below under Configuring Authentication Mechanisms. With Standalone CDAP, the simplest is Basic Authentication.

🔗Enabling Perimeter Security (Distributed CDAP)

To enable security in Distributed CDAP, add these properties to cdap-site.xml:

Property Value Description
security.enabled true Enables authentication for CDAP. When set to true all requests to CDAP must provide a valid access token.
security.auth.server.announce.address   CDAP Authentication service announce address, in the format of host:port. This is the address that clients should use to communicate with the Authentication Server. Leave empty (the default value) to use the default address generated by the Authentication Server.
security.auth.server.bind.address 0.0.0.0 IP address that the CDAP Authentication Server should bind to (default value shown)
security.auth.server.bind.port 10009 CDAP Authentication service bind port (default value shown)

🔗Configuring Kerberos (required)

To configure Kerberos authentication for various CDAP services, add these properties to cdap-site.xml:

Property Value Description
kerberos.auth.enabled security.enabled true to enable Kerberos authentication
cdap.master.kerberos.keytab <filepath> Kerberos keytab file path, either absolute or relative
cdap.master.kerberos.principal <principal> Kerberos principal associated with the keytab

🔗Configuring ZooKeeper (required)

To configure ZooKeeper to enable SASL authentication, add the following to your zoo.cfg:

authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
jaasLoginRenew=3600000
kerberos.removeHostFromPrincipal=true
kerberos.removeRealmFromPrincipal=true

This will let ZooKeeper use the SASLAuthenticationProvider as an auth provider, and the jaasLoginRenew line will cause the ZooKeeper server to renew its Kerberos ticket once an hour.

Then, create a jaas.conf file for your ZooKeeper server:

Server {
     com.sun.security.auth.module.Krb5LoginModule required
     useKeyTab=true
     keyTab="/path/to/zookeeper.keytab"
     storeKey=true
     useTicketCache=false
     principal="<your-zookeeper-principal>";
};

The keytab file must be readable by the ZooKeeper server, and <your-zookeeper-principal> must correspond to the keytab file.

Finally, start ZooKeeper server with the following JVM option:

-Djava.security.auth.login.config=/path/to/jaas.conf

🔗Accessing CDAP Services with SSL

To enable running the CDAP Router with SSL, add this property to cdap-site.xml:

Property Value Description
ssl.external.enabled true true to enable SSL for external services

🔗Default Ports

Without SSL, these properties have—unless set specifically—these default values:

Property Default Value Description
router.bind.port 11015 Port number that the CDAP Router should bind to for HTTP Connections
security.auth.server.bind.port 10009 Port number that the CDAP Authentication Server should bind to for HTTP Connections
dashboard.bind.port 11011 Port number that the CDAP UI should bind to for HTTP Connections

With SSL, these properties have—unless set specifically—these default values:

Property Default Value Description
router.ssl.bind.port 10443 Port number that the CDAP router should bind to for HTTPS Connections
security.auth.server.ssl.bind.port 10010 Port number that the CDAP Authentication Server should bind to for HTTPS Connections
dashboard.ssl.bind.port 9443 Port number that the CDAP UI should bind to for HTTPS Connections

🔗Configuring SSL for the Authentication Server

To configure the granting of AccessTokens via SSL, add these properties to cdap-security.xml:

Property Value Description
security.auth.server.ssl.keystore.path <filepath> Keystore file location, either absolute or relative; the file should be owned and readable only by the CDAP user
security.auth.server.ssl.keystore.password <password> Keystore password
security.auth.server.ssl.keystore.keypassword <password> Keystore key password
security.auth.server.ssl.keystore.type JKS Keystore file type (default JKS)

To configure client certificate based authentication via 2-way SSL, add these properties to cdap-site.xml:

Property Value Description
security.auth.server.ssl.truststore.path <filepath> Truststore file location, either absolute or relative; the file should be owned and readable only by the CDAP user
security.auth.server.ssl.truststore.password <password> Keystore password
security.auth.server.ssl.truststore.type JKS Keystore file type (default JKS)

🔗Configuring SSL for the Router

To configure SSL for the Router, add these properties to cdap-security.xml:

Property Value Description
router.ssl.keystore.path <filepath> Keystore file location, either absolute or relative; the file should be owned and readable only by the CDAP user
router.ssl.keystore.password <password> Keystore password
router.ssl.keystore.keypassword <password> Keystore key password
router.ssl.keystore.type JKS Keystore file type (default JKS)

🔗Configuring SSL for the CDAP UI

To enable SSL for the CDAP UI, add these properties to cdap-security.xml:

Property Value Description
dashboard.ssl.cert <filepath> SSL cert file location, either absolute or relative; the file should be owned and readable only by the CDAP user
dashboard.ssl.key <filepath> SSL key file location, either absolute or relative; the file should be owned and readable only by the CDAP user

Note: To enable SSL for the CDAP UI and allow self-signed certificates, add this property to cdap-security.xml:

Property Value Description
dashboard.ssl.disable.cert.check true true to disable SSL certificate check from the CDAP UI

🔗Enabling Access Logging

To enable access logging, add the following to logback.xml (typically under /etc/cdap/conf/)

<appender name="AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <file>access.log</file>
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <fileNamePattern>access.log.%d{yyyy-MM-dd}</fileNamePattern>
    <maxHistory>30</maxHistory>
  </rollingPolicy>
  <encoder>
    <pattern>%msg%n</pattern>
  </encoder>
</appender>
<logger name="http-access" level="TRACE" additivity="false">
  <appender-ref ref="AUDIT" />
</logger>

<appender name="EXTERNAL_AUTH_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <file>external_auth_access.log</file>
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <fileNamePattern>external_auth_access.log.%d{yyyy-MM-dd}</fileNamePattern>
    <maxHistory>30</maxHistory>
  </rollingPolicy>
  <encoder>
    <pattern>%msg%n</pattern>
  </encoder>
</appender>
<logger name="external-auth-access" level="TRACE" additivity="false">
  <appender-ref ref="EXTERNAL_AUTH_AUDIT" />
</logger>

You may also configure the file being logged to by changing the path under <file>...</file>.

🔗Configuring Authentication Mechanisms

CDAP provides several ways to authenticate a client’s identity:

🔗Basic Authentication

The simplest way to identity a client is to authenticate against a realm file. To configure basic authentication add these properties to cdap-site.xml:

Property Value Description
security.authentication.handlerClassName co.cask.cdap.security.server. BasicAuthenticationHandler Name of the class handling authentication
security.authentication.basic.realmfile <filepath> An absolute or relative path to the realm file

The realm file is of the following format:

username: password[,rolename ...]

In Standalone CDAP, the realm file can be specified as conf/realmfile and placed with the cdap-site.xml file. Note that it is not advisable to use this method of authentication. In production, we recommend using any of the other methods described below.

🔗LDAP Authentication

You can configure CDAP to authenticate against an LDAP instance by adding these properties to cdap-site.xml:

Property Value Description
security.authentication.handlerClassName co.cask.cdap.security.server. LDAPAuthenticationHandler Name of the class handling authentication
security.authentication.loginmodule.className co.cask.cdap.security.server. LDAPLoginModule Name of a class used as a custom login module for authentication
security.authentication.handler.debug false Set to true to enable debugging
security.authentication.handler.hostname <hostname> LDAP server host
security.authentication.handler.port <port> LDAP server port
security.authentication.handler.userBaseDn <userBaseDn> Distinguished Name of the root for user account entries in the LDAP directory
security.authentication.handler.userRdnAttribute <userRdnAttribute> LDAP Object attribute for username when search by role DN
security.authentication.handler.userObjectClass <userObjectClass> LDAP Object class used to store user entries

In addition, you may configure these optional properties in cdap-site.xml:

Property Value Description
security.authentication.handler.bindDn <bindDn> The Distinguished Name used to bind to the LDAP server and search the directory
security.authentication.handler.bindPassword <bindPassword> The password used to bind to the LDAP server
security.authentication.handler.userIdAttribute <userIdAttribute> LDAP Object attribute containing the username
security.authentication.handler.userPasswordAttribute <userPasswordAttribute> LDAP Object attribute containing the user password
security.authentication.handler.roleBaseDn <roleBaseDn> Distinguished Name of the root of the LDAP tree to search for group memberships
security.authentication.handler.roleNameAttribute <roleNameAttribute> LDAP Object attribute specifying the group name
security.authentication.handler.roleMemberAttribute <roleMemberAttribute> LDAP Object attribute specifying the group members
security.authentication.handler.roleObjectClass <roleObjectClass> LDAP Object class used to store group entries

To enable SSL between the authentication server and the LDAP instance, configure these properties in cdap-site.xml:

Property Default Value Value Description
security.authentication.handler.useLdaps false true Set to true to enable use of LDAPS
security.authentication.handler.ldapsVerifyCertificate true true Set to true to enable verification of the SSL certificate used by the LDAP server

🔗JASPI Authentication

To authenticate a user using JASPI (Java Authentication Service Provider Interface) add these properties to cdap-site.xml:

Property Value Description
security.authentication.handlerClassName co.cask.cdap.security.server. JASPIAuthenticationHandler Name of the class handling authentication
security.authentication.loginmodule.className <custom-login-module> Name of the class of the login module handling authentication

In addition, any properties with the prefix security.authentication.handler., such as security.authentication.handler.hostname, will be provided to the handler. These properties, stripped of the prefix, will be used to instantiate the javax.security.auth.login.Configuration used by the LoginModule.

🔗Custom Authentication

To use a Custom Authentication mechanism, set the security.authentication.handlerClassName in cdap-site.xml with the custom handler's classname. Any properties set in either cdap-site.xml or cdap-security.xml and that are prefixed with security.authentication.handler. are available through a Map<String, String> object and can be used to configure the handler.

To make your custom handler class available to the authentication service, copy your packaged jar file (and any additional dependency jars) to the security/lib/ directory within your CDAP installation (typically under /opt/cdap).

The Developers’ Manual Custom Authentication section shows how to create a Custom Authentication Mechanism.

🔗Configuring Exemptions from Authentication

Sometimes you need to exempt certain URLs from authentication. For example, you may want to secure your entire application, except that you want to allow sending data to a stream by unauthenticated clients. For this, you can configure the CDAP Router to bypass the authentication for URLs that match a given regular expression, by adding this property in cdap-site.xml:

Property Value Description
router.bypass.auth.regex <reg-exp> Regular expression to match URLs that are exempt from authentication.

For example, the following configuration in cdap-site.xml will allow unauthenticated posting to all streams in the default namespace:

<property>
  <name>router.bypass.auth.regex</name>
  <value>/v3/namespaces/default/streams/[^/]+</value>
</property>

This must be configured on every node that runs the CDAP Router.

🔗Testing Perimeter Security

To ensure that you've configured security correctly, run these simple tests to verify that the security components are working as expected. See the CDAP Reference Manual: HTTP RESTful API for information on the conventions used for these examples. Note that if SSL is enabled for CDAP Servers, then the base URL used in these examples will use https instead of http.

  • After configuring CDAP as described above, start (or restart) CDAP and attempt to make a request:

    GET /v3/apps
    

    such as:

    $ curl -v -w"\n" -X GET "http://localhost:11015/v3/namespaces/default/apps"
    
    > curl -v -X GET "http://localhost:11015/v3/namespaces/default/apps"
    

    This should return a 401 Unauthorized response with a list of authentication URIs in the response body. For example:

    {"auth_uri":["http://localhost:10009/token"]}
    
  • Submit a username and password to one of the authentication URIs (<auth-uri>) to obtain an AccessToken by submitting a Basic Authorization header with the username and password:

    GET <auth-uri> "Authorization: Basic <encoded_username_password_string>"
    

    Using curl, assuming a CDAP authentication server at the URI localhost:10009 and that you have defined a username:password pair such as cdap:bigdata in the realm file, you can use curl's -u option to create the header:

    $ curl -v -w"\n" -X GET "http://localhost:10009/token" -u cdap:bigdata
    
    > curl -v -X GET "http://localhost:10009/token" -u cdap:bigdata
    

    This should return a 200 OK response with the AccessToken string in the response body (formatted to fit):

    {"access_token":"AghjZGFwAI7e8p65Uo7OpfG5UrD87psGQE0u0sFDoqxtacdRR5GxEb6bkTypP7mXdqvqqnLmfxOS",
      "token_type":"Bearer","expires_in":86400}
    
  • Reattempt the first command, but this time include the access_token as a header in the request:

    GET /v3/apps "Authorization: Bearer <access_token>"
    

    such as (formatted to fit):

    $ curl -v -w"\n" -X GET "http://localhost:11015/v3/namespaces/default/apps" \
    -H "Authorization: Bearer AghjZGFwAI7e8p65Uo7OpfG5UrD87psGQE0u0sFDoqxtacdRR5GxEb6bkTypP7mXdqvqqnLmfxOS"
    
    > curl -v -X GET "http://localhost:11015/v3/namespaces/default/apps" ^
    -H "Authorization: Bearer AghjZGFwAI7e8p65Uo7OpfG5UrD87psGQE0u0sFDoqxtacdRR5GxEb6bkTypP7mXdqvqqnLmfxOS"
    

    This should return a 200 OK response.

  • Visiting the CDAP UI should redirect you to a login page that prompts for credentials. Entering the credentials that you have configured should let you work with the CDAP UI as normal.