blob: fb74df6f22645f18cb61d71c611df34bd967c988 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef PULSAR_AUTHENTICATION_H_
#define PULSAR_AUTHENTICATION_H_
#include <pulsar/Result.h>
#include <pulsar/defines.h>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace pulsar {
class ClientConfiguration;
class Authentication;
class PULSAR_PUBLIC AuthenticationDataProvider {
public:
virtual ~AuthenticationDataProvider();
/**
* @return true if the authentication data contains data for TLS
*/
virtual bool hasDataForTls();
/**
* @return a client certificate chain or “none” if the data is not available
*/
virtual std::string getTlsCertificates();
/**
* @return a private key for the client certificate or “none” if the data is not available
*/
virtual std::string getTlsPrivateKey();
/**
* @return true if this authentication data contains data for HTTP
*/
virtual bool hasDataForHttp();
/**
* @return an authentication scheme or “none” if the request is not authenticated
*/
virtual std::string getHttpAuthType();
/**
* @return the string of HTTP header or “none” if the request is not authenticated
*/
virtual std::string getHttpHeaders();
/**
* @return true if authentication data contains data from Pulsar protocol
*/
virtual bool hasDataFromCommand();
/**
* @return authentication data which is stored in a command
*/
virtual std::string getCommandData();
protected:
AuthenticationDataProvider();
};
typedef std::shared_ptr<AuthenticationDataProvider> AuthenticationDataPtr;
typedef std::shared_ptr<Authentication> AuthenticationPtr;
typedef std::map<std::string, std::string> ParamMap;
class PULSAR_PUBLIC Authentication {
public:
virtual ~Authentication();
/**
* @return the authentication method name supported by this provider
*/
virtual const std::string getAuthMethodName() const = 0;
/**
* Get AuthenticationData from the current instance
*
* @param[out] authDataContent the shared pointer of AuthenticationData. The content of AuthenticationData
* is changed to the internal data of the current instance.
* @return ResultOk or ResultAuthenticationError if authentication failed
*/
virtual Result getAuthData(AuthenticationDataPtr& authDataContent) {
authDataContent = authData_;
return ResultOk;
}
/**
* Parse the authentication parameter string to a map whose key and value are both strings
*
* The parameter string can have multiple lines. The format of each line is a comma-separated “key:value”
* string.
*
* For example, “k1:v1,k2:v2” is parsed to two key-value pairs `(k1, v1)` and `(k2, v2)`.
*
* @param authParamsString the authentication parameter string to be parsed
* @return the parsed map whose key and value are both strings
*/
static ParamMap parseDefaultFormatAuthParams(const std::string& authParamsString);
protected:
Authentication();
AuthenticationDataPtr authData_;
friend class ClientConfiguration;
};
/**
* AuthFactory is used to create instances of Authentication class when
* configuring a Client instance. It loads the authentication from an
* external plugin.
*
* To use authentication methods that are internally supported, you should
* use `AuthTls::create("my-cert.pem", "my-private.key")` or similar.
*/
class PULSAR_PUBLIC AuthFactory {
public:
static AuthenticationPtr Disabled();
/**
* Create an AuthenticationPtr with an empty ParamMap
*
* @see create(const std::string&, const ParamMap&)
*/
static AuthenticationPtr create(const std::string& pluginNameOrDynamicLibPath);
/**
* Create an AuthenticationPtr with a ParamMap that is converted from authParamsString
*
* @see Authentication::parseDefaultFormatAuthParams
* @see create(const std::string&, const ParamMap&)
*/
static AuthenticationPtr create(const std::string& pluginNameOrDynamicLibPath,
const std::string& authParamsString);
/**
* Create an AuthenticationPtr
*
* When the first parameter represents the plugin name, the type of authentication can be one of the
* following:
* - AuthTls (if the plugin name is “tls”)
* - AuthToken (if the plugin name is “token” or “org.apache.pulsar.client.impl.auth.AuthenticationToken”)
* - AuthAthenz (if the plugin name is “athenz” or
* “org.apache.pulsar.client.impl.auth.AuthenticationAthenz”)
* - AuthOauth2 (if the plugin name is “oauth2token” or
* “org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2”)
*
* @param pluginNameOrDynamicLibPath the plugin name or the path or a dynamic library that contains the
* implementation of Authentication
* @param params the ParamMap that is passed to Authentication::create method
*/
static AuthenticationPtr create(const std::string& pluginNameOrDynamicLibPath, ParamMap& params);
protected:
static bool isShutdownHookRegistered_;
static std::vector<void*> loadedLibrariesHandles_;
static void release_handles();
};
/**
* TLS implementation of Pulsar client authentication
*/
class PULSAR_PUBLIC AuthTls : public Authentication {
public:
AuthTls(AuthenticationDataPtr&);
~AuthTls();
/**
* Create an AuthTls with a ParamMap
*
* It is equal to create(params[“tlsCertFile”], params[“tlsKeyFile”])
* @see create(const std::string&, const std::string&)
*/
static AuthenticationPtr create(ParamMap& params);
/**
* Create an AuthTls with an authentication parameter string
*
* @see Authentication::parseDefaultFormatAuthParams
*/
static AuthenticationPtr create(const std::string& authParamsString);
/**
* Create an AuthTls with the required parameters
*
* @param certificatePath the file path for a client certificate
* @param privateKeyPath the file path for a client private key
*/
static AuthenticationPtr create(const std::string& certificatePath, const std::string& privateKeyPath);
/**
* @return “tls”
*/
const std::string getAuthMethodName() const;
/**
* Get AuthenticationData from the current instance
*
* @param[out] authDataTls the shared pointer of AuthenticationData. The content of AuthenticationData is
* changed to the internal data of the current instance.
* @return ResultOk
*/
Result getAuthData(AuthenticationDataPtr& authDataTls);
private:
AuthenticationDataPtr authDataTls_;
};
typedef std::function<std::string()> TokenSupplier;
/**
* Token based implementation of Pulsar client authentication
*/
class PULSAR_PUBLIC AuthToken : public Authentication {
public:
AuthToken(AuthenticationDataPtr&);
~AuthToken();
/**
* Create an AuthToken with a ParamMap
*
* @param parameters it must contain a key-value, where key means how to get the token and value means the
* token source
*
* If the key is “token”, the value is the token
*
* If the key is “file”, the value is the file that contains the token
*
* If the key is “env”, the value is the environment variable whose value is the token
*
* Otherwise, a `std::runtime_error` error is thrown.
* @see create(const std::string& authParamsString)
*/
static AuthenticationPtr create(ParamMap& params);
/**
* Create an AuthToken with an authentication parameter string
*
* @see Authentication::parseDefaultFormatAuthParams
*/
static AuthenticationPtr create(const std::string& authParamsString);
/**
* Create an authentication provider for token based authentication
*
* @param token
* a string containing the auth token
*/
static AuthenticationPtr createWithToken(const std::string& token);
/**
* Create an authentication provider for token based authentication
*
* @param tokenSupplier
* a supplier of the client auth token
*/
static AuthenticationPtr create(const TokenSupplier& tokenSupplier);
/**
* @return “token”
*/
const std::string getAuthMethodName() const;
/**
* Get AuthenticationData from the current instance
*
* @param[out] authDataToken the shared pointer of AuthenticationData. The content of AuthenticationData
* is changed to the internal data of the current instance.
* @return ResultOk
*/
Result getAuthData(AuthenticationDataPtr& authDataToken);
private:
AuthenticationDataPtr authDataToken_;
};
/**
* Basic based implementation of Pulsar client authentication
*/
class PULSAR_PUBLIC AuthBasic : public Authentication {
public:
explicit AuthBasic(AuthenticationDataPtr&);
~AuthBasic() override;
/**
* Create an AuthBasic with a ParamMap
*
* It is equal to create(params[“username”], params[“password”])
* @see create(const std::string&, const std::string&)
*/
static AuthenticationPtr create(ParamMap& params);
/**
* Create an AuthBasic with an authentication parameter string
*
* @param authParamsString the JSON format string: {"username": "admin", "password": "123456"}
*/
static AuthenticationPtr create(const std::string& authParamsString);
/**
* Create an AuthBasic with the required parameters
*/
static AuthenticationPtr create(const std::string& username, const std::string& password);
/**
* Create an AuthBasic with the required parameters
*/
static AuthenticationPtr create(const std::string& username, const std::string& password,
const std::string& method);
/**
* @return “basic”
*/
const std::string getAuthMethodName() const override;
/**
* Get AuthenticationData from the current instance
*
* @param[out] authDataBasic the shared pointer of AuthenticationData. The content of AuthenticationData
* is changed to the internal data of the current instance.
* @return ResultOk
*/
Result getAuthData(AuthenticationDataPtr& authDataBasic) override;
private:
AuthenticationDataPtr authDataBasic_;
};
/**
* Athenz implementation of Pulsar client authentication
*/
class PULSAR_PUBLIC AuthAthenz : public Authentication {
public:
AuthAthenz(AuthenticationDataPtr&);
~AuthAthenz();
/**
* Create an AuthAthenz with a ParamMap
*
* The required parameter keys are “tenantDomain”, “tenantService”, “providerDomain”, “privateKey”, and
* “ztsUrl”
*
* @param params the key-value to construct ZTS client
* @see http://pulsar.apache.org/docs/en/security-athenz/
*/
static AuthenticationPtr create(ParamMap& params);
/**
* Create an AuthAthenz with an authentication parameter string
*
* @see Authentication::parseDefaultFormatAuthParams
*/
static AuthenticationPtr create(const std::string& authParamsString);
/**
* @return “athenz”
*/
const std::string getAuthMethodName() const;
/**
* Get AuthenticationData from the current instance
*
* @param[out] authDataAthenz the shared pointer of AuthenticationData. The content of AuthenticationData
* is changed to the internal data of the current instance.
* @return ResultOk
*/
Result getAuthData(AuthenticationDataPtr& authDataAthenz);
private:
AuthenticationDataPtr authDataAthenz_;
};
// OAuth 2.0 token and associated information.
// currently mainly works for access token
class Oauth2TokenResult {
public:
enum
{
undefined_expiration = -1
};
Oauth2TokenResult();
~Oauth2TokenResult();
/**
* Set the access token string
*
* @param accessToken the access token string
*/
Oauth2TokenResult& setAccessToken(const std::string& accessToken);
/**
* Set the ID token
*
* @param idToken the ID token
*/
Oauth2TokenResult& setIdToken(const std::string& idToken);
/**
* Set the refresh token which can be used to obtain new access tokens using the same authorization grant
* or null for none
*
* @param refreshToken the refresh token
*/
Oauth2TokenResult& setRefreshToken(const std::string& refreshToken);
/**
* Set the token lifetime
*
* @param expiresIn the token lifetime
*/
Oauth2TokenResult& setExpiresIn(const int64_t expiresIn);
/**
* @return the access token string
*/
const std::string& getAccessToken() const;
/**
* @return the ID token
*/
const std::string& getIdToken() const;
/**
* @return the refresh token which can be used to obtain new access tokens using the same authorization
* grant or null for none
*/
const std::string& getRefreshToken() const;
/**
* @return the token lifetime in milliseconds
*/
int64_t getExpiresIn() const;
private:
// map to json "access_token"
std::string accessToken_;
// map to json "id_token"
std::string idToken_;
// map to json "refresh_token"
std::string refreshToken_;
// map to json "expires_in"
int64_t expiresIn_;
};
typedef std::shared_ptr<Oauth2TokenResult> Oauth2TokenResultPtr;
class Oauth2Flow {
public:
virtual ~Oauth2Flow();
/**
* Initializes the authorization flow.
*/
virtual void initialize() = 0;
/**
* Acquires an access token from the OAuth 2.0 authorization server.
* @return a token result including an access token.
*/
virtual Oauth2TokenResultPtr authenticate() = 0;
/**
* Closes the authorization flow.
*/
virtual void close() = 0;
protected:
Oauth2Flow();
};
typedef std::shared_ptr<Oauth2Flow> FlowPtr;
class CachedToken {
public:
virtual ~CachedToken();
/**
* @return true if the token has expired
*/
virtual bool isExpired() = 0;
/**
* Get AuthenticationData from the current instance
*
* @return ResultOk or ResultAuthenticationError if authentication failed
*/
virtual AuthenticationDataPtr getAuthData() = 0;
protected:
CachedToken();
};
typedef std::shared_ptr<CachedToken> CachedTokenPtr;
/**
* Oauth2 based implementation of Pulsar client authentication.
* Passed in parameter would be like:
* ```
* "type": "client_credentials",
* "issuer_url": "https://accounts.google.com",
* "client_id": "d9ZyX97q1ef8Cr81WHVC4hFQ64vSlDK3",
* "client_secret": "on1uJ...k6F6R",
* "audience": "https://broker.example.com"
* ```
* If passed in as std::string, it should be in Json format.
*/
class PULSAR_PUBLIC AuthOauth2 : public Authentication {
public:
AuthOauth2(ParamMap& params);
~AuthOauth2();
/**
* Create an AuthOauth2 with a ParamMap
*
* The required parameter keys are “issuer_url”, “private_key”, and “audience”
*
* @param parameters the key-value to create OAuth 2.0 client credentials
* @see http://pulsar.apache.org/docs/en/security-oauth2/#client-credentials
*/
static AuthenticationPtr create(ParamMap& params);
/**
* Create an AuthOauth2 with an authentication parameter string
*
* @see Authentication::parseDefaultFormatAuthParams
*/
static AuthenticationPtr create(const std::string& authParamsString);
/**
* @return “token”
*/
const std::string getAuthMethodName() const;
/**
* Get AuthenticationData from the current instance
*
* @param[out] authDataOauth2 the shared pointer of AuthenticationData. The content of AuthenticationData
* is changed to the internal data of the current instance.
* @return ResultOk or ResultAuthenticationError if authentication failed
*/
Result getAuthData(AuthenticationDataPtr& authDataOauth2);
private:
FlowPtr flowPtr_;
CachedTokenPtr cachedTokenPtr_;
};
} // namespace pulsar
#endif /* PULSAR_AUTHENTICATION_H_ */