blob: 89b2becb0188f53ccc0e796fb7c6a3ed1613754b [file] [view]
---
id: security-extending
title: Extending Authentication and Authorization in Pulsar
sidebar_label: "Extending"
original_id: security-extending
---
Pulsar provides a way to use custom authentication and authorization mechanisms
## Authentication
Pulsar support mutual TLS and Athenz authentication plugins, and these can be used as described
in [Security](security-overview.md).
It is possible to use a custom authentication mechanism by providing the implementation in the
form of two plugins one for the Client library and the other for the Pulsar Broker to validate
the credentials.
### Client authentication plugin
For client library, you will need to implement `org.apache.pulsar.client.api.Authentication`. This class can then be passed
when creating a Pulsar client:
```java
PulsarClient client = PulsarClient.builder()
.serviceUrl("pulsar://localhost:6650")
.authentication(new MyAuthentication())
.build();
```
For reference, there are 2 interfaces to implement on the client side:
* `Authentication` -> http://pulsar.apache.org/api/client/org/apache/pulsar/client/api/Authentication.html
* `AuthenticationDataProvider` -> http://pulsar.apache.org/api/client/org/apache/pulsar/client/api/AuthenticationDataProvider.html
This in turn will need to provide the client credentials in the form of `org.apache.pulsar.client.api.AuthenticationDataProvider`. This will leave
the chance to return different kinds of authentication token for different
type of connection or by passing a certificate chain to use for TLS.
Examples for client authentication providers can be found at:
* Mutual TLS Auth -- https://github.com/apache/pulsar/tree/master/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth
* Athenz -- https://github.com/apache/pulsar/tree/master/pulsar-client-auth-athenz/src/main/java/org/apache/pulsar/client/impl/auth
### Broker authentication plugin
On broker side, we need the corresponding plugin to validate the credentials
passed by the client. Broker can support multiple authentication providers
at the same time.
In `conf/broker.conf` it's possible to specify a list of valid providers:
```properties
# Authentication provider name list, which is comma separated list of class names
authenticationProviders=
```
There is one single interface to implement `org.apache.pulsar.broker.authentication.AuthenticationProvider`:
```java
/**
* Provider of authentication mechanism
*/
public interface AuthenticationProvider extends Closeable {
/**
* Perform initialization for the authentication provider
*
* @param config
* broker config object
* @throws IOException
* if the initialization fails
*/
void initialize(ServiceConfiguration config) throws IOException;
/**
* @return the authentication method name supported by this provider
*/
String getAuthMethodName();
/**
* Validate the authentication for the given credentials with the specified authentication data
*
* @param authData
* provider specific authentication data
* @return the "role" string for the authenticated connection, if the authentication was successful
* @throws AuthenticationException
* if the credentials are not valid
*/
String authenticate(AuthenticationDataSource authData) throws AuthenticationException;
}
```
Example for Broker authentication plugins:
* Mutual TLS -- https://github.com/apache/pulsar/blob/master/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTls.java
* Athenz -- https://github.com/apache/pulsar/blob/master/pulsar-broker-auth-athenz/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderAthenz.java
## Authorization
Authorization is the operation that checks whether a particular "role" or "principal" is
allowed to perform a certain operation.
By default, Pulsar provides an embedded authorization, though it's possible to
configure a different one through a plugin.
To provide a custom provider, one needs to implement the
`org.apache.pulsar.broker.authorization.AuthorizationProvider` interface, have this class in the
Pulsar broker classpath and configure it in `conf/broker.conf`:
```properties
# Authorization provider fully qualified class-name
authorizationProvider=org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider
```
```java
/**
* Provider of authorization mechanism
*/
public interface AuthorizationProvider extends Closeable {
/**
* Perform initialization for the authorization provider
*
* @param config
* broker config object
* @param configCache
* pulsar zk configuration cache service
* @throws IOException
* if the initialization fails
*/
void initialize(ServiceConfiguration conf, ConfigurationCacheService configCache) throws IOException;
/**
* Check if the specified role has permission to send messages to the specified fully qualified topic name.
*
* @param topicName
* the fully qualified topic name associated with the topic.
* @param role
* the app id used to send messages to the topic.
*/
CompletableFuture<Boolean> canProduceAsync(TopicName topicName, String role,
AuthenticationDataSource authenticationData);
/**
* Check if the specified role has permission to receive messages from the specified fully qualified topic name.
*
* @param topicName
* the fully qualified topic name associated with the topic.
* @param role
* the app id used to receive messages from the topic.
* @param subscription
* the subscription name defined by the client
*/
CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
AuthenticationDataSource authenticationData, String subscription);
/**
* Check whether the specified role can perform a lookup for the specified topic.
*
* For that the caller needs to have producer or consumer permission.
*
* @param topicName
* @param role
* @return
* @throws Exception
*/
CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role,
AuthenticationDataSource authenticationData);
/**
*
* Grant authorization-action permission on a namespace to the given client
*
* @param namespace
* @param actions
* @param role
* @param authDataJson
* additional authdata in json format
* @return CompletableFuture
* @completesWith <br />
* IllegalArgumentException when namespace not found<br />
* IllegalStateException when failed to grant permission
*/
CompletableFuture<Void> grantPermissionAsync(NamespaceName namespace, Set<AuthAction> actions, String role,
String authDataJson);
/**
* Grant authorization-action permission on a topic to the given client
*
* @param topicName
* @param role
* @param authDataJson
* additional authdata in json format
* @return CompletableFuture
* @completesWith <br />
* IllegalArgumentException when namespace not found<br />
* IllegalStateException when failed to grant permission
*/
CompletableFuture<Void> grantPermissionAsync(TopicName topicName, Set<AuthAction> actions, String role,
String authDataJson);
}
```