Security
The driver currently supports authentication (using plain text or a custom authenticator) and SSL (via OpenSSL).
Authentication
Plain text
Credentials are provided using the [cass_cluster_set_credentials()
] function.
CassCluster* cluster = cass_cluster_new();
const char* username = "cassandra";
const char* password = "cassandra";
cass_cluster_set_credentials(cluster, username, password);
/* Connect session object */
cass_cluster_free(cluster);
Important: The credentials are sent in plain text to the server. For this reason, it is highly recommended that this be used in conjunction with client-to-node encryption (SSL), or in a trusted network environment.
Custom
A custom authentication implementation can be set using
cass_cluster_set_authenticator_callbacks()
. This is useful for integrating
with more complex authentication systems such as Kerberos.
typedef struct Credentials_ {
const char* password;
const char* username;
} Credential;
void on_auth_initial(CassAuthenticator* auth, void* data) {
/*
* This callback is used to initiate a request to begin an authentication
* exchange. Required resources can be acquired and initialized here.
*
* Resources required for this specific exchange can be stored in the
* auth->data field and will be available in the subsequent challenge
* and success phases of the exchange. The cleanup callback should be used to
* free these resources.
*/
/*
* The data parameter contains the credentials passed in when the
* authentication callbacks were set and is available to all
* authentication exchanges.
*/
const Credentials* credentials = (const Credentials *)data;
size_t username_size = strlen(credentials->username);
size_t password_size = strlen(credentials->password);
size_t size = username_size + password_size + 2;
/* Allocate a response token */
char* response = cass_authenticator_response(auth, size);
/* Credentials are prefixed with '\0' */
response[0] = '\0';
memcpy(response + 1, credentials->username, username_size);
response[username_size + 1] = '\0';
memcpy(response + username_size + 2, credentials->password, password_size);
}
void on_auth_challenge(CassAuthenticator* auth, void* data,
const char* token, size_t token_size) {
/*
* This is used for handling an authentication challenge initiated
* by the server. The information contained in the token parameter is
* authentication protocol specific. It may be NULL or empty.
*/
}
void on_auth_success(CassAuthenticator* auth, void* data,
const char* token, size_t token_size) {
/*
* This is to be used for handling the success phase of an exchange. The
* token parameters contains information that may be used to finialize
* the request. The information contained in the token parameter is
* authentication protocol specific. It may be NULL or empty.
*/
}
void on_auth_cleanup(CassAuthenticator* auth, void* data) {
/*
* This is used to cleanup resources acquired during the authentication
* exchange.
*/
}
int main() {
/* ... */
/* Setup authentication callbacks and credentials */
CassAuthenticatorCallbacks auth_callbacks = {
on_auth_initial,
on_auth_challenge,
on_auth_success,
on_auth_cleanup
};
/*
* The `credentials` argument passed into `cass_cluster_set_auth_callbacks()`
* is passed as the `data` parameter into the authentication callbacks.
* Callbacks will be called by multiple threads concurrently so it is important
* makes sure this data is either immutable or its access is serialized. The
* `data` parameter can be cleaned up be passing a `CassAuthenticatorDataCleanupCallback`
* to `cass_cluster_set_authenticator_callbacks()`.
*/
Credentials credentials = {
"cassandra",
"cassandra"
};
/* Set custom authentication callbacks and credentials */
cass_cluster_set_authenticator_callbacks(cluster,
&auth_callbacks,
NULL, /* No cleanup callback required */
&credentials);
/* ... */
}