Skip to content

Commit

Permalink
Release of version 2.0.0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
rueiyhuang committed Sep 13, 2023
1 parent d825f93 commit dd26c3c
Show file tree
Hide file tree
Showing 109 changed files with 6,661 additions and 3,625 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Changelog
=========
v2.0.0.9 (2023-09-11)
==================

1. Added Identity Center authentication support with new plugins.
2. Fixed IAM Authentication to support longer temporary passwords from 129 to 32767 characters.
3. Added automatic region detection for Custom Cluster Naming (CNAME) feature.


v2.0.0.8 (2023-08-15)
---------------------
- Fixed regular expressions used for parsing HTML Tag value responses received form for Ping IdP.[Ruei-Yang Huang]
Expand Down
4 changes: 2 additions & 2 deletions src/odbc/rsodbc/Release/objects.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

USER_OBJS :=

THIRD_PARTY_LIBS := $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-redshift.a $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-redshift-serverless.a $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-sts.a $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-core.a $(AWS_SDK_LIB_DIR)/libaws-crt-cpp.a $(AWS_SDK_LIB_DIR)/libaws-c-s3.a $(AWS_SDK_LIB_DIR)/libaws-c-auth.a $(AWS_SDK_LIB_DIR)/libaws-c-event-stream.a $(AWS_SDK_LIB_DIR)/libaws-c-http.a $(AWS_SDK_LIB_DIR)/libaws-c-mqtt.a $(AWS_SDK_LIB_DIR)/libaws-c-io.a $(AWS_SDK_LIB_DIR)/libaws-c-cal.a $(AWS_SDK_LIB_DIR)/libaws-checksums.a $(AWS_SDK_LIB_DIR)/libaws-c-compression.a $(AWS_SDK_LIB_DIR)/libaws-c-common.a $(AWS_SDK_LIB_DIR)/libs2n.a $(AWS_SDK_LIB_DIR)/libaws-c-sdkutils.a $(CURL_LIB_DIR)/libcurl.a $(OPENSSL_LIB_DIR)/libssl.a $(OPENSSL_LIB_DIR)/libcrypto.a
THIRD_PARTY_LIBS := $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-redshift.a $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-sso-oidc.a $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-redshift-serverless.a $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-sts.a $(AWS_SDK_LIB_DIR)/libaws-cpp-sdk-core.a $(AWS_SDK_LIB_DIR)/libaws-crt-cpp.a $(AWS_SDK_LIB_DIR)/libaws-c-s3.a $(AWS_SDK_LIB_DIR)/libaws-c-auth.a $(AWS_SDK_LIB_DIR)/libaws-c-event-stream.a $(AWS_SDK_LIB_DIR)/libaws-c-http.a $(AWS_SDK_LIB_DIR)/libaws-c-mqtt.a $(AWS_SDK_LIB_DIR)/libaws-c-io.a $(AWS_SDK_LIB_DIR)/libaws-c-cal.a $(AWS_SDK_LIB_DIR)/libaws-checksums.a $(AWS_SDK_LIB_DIR)/libaws-c-compression.a $(AWS_SDK_LIB_DIR)/libaws-c-common.a $(AWS_SDK_LIB_DIR)/libs2n.a $(AWS_SDK_LIB_DIR)/libaws-c-sdkutils.a $(CURL_LIB_DIR)/libcurl.a $(OPENSSL_LIB_DIR)/libssl.a $(OPENSSL_LIB_DIR)/libcrypto.a
ifdef DEPENDENCY_DIR
THIRD_PARTY_LIBS += $(DEPENDENCY_DIR)/lib/libnghttp2.a $(DEPENDENCY_DIR)/lib/libcares.a $(DEPENDENCY_DIR)/lib/libkeyutils.a $(DEPENDENCY_DIR)/lib/libz.a
endif

LIBS := $(THIRD_PARTY_LIBS) -lpq -lpgport -lpthread -lkrb5 -lgssapi_krb5 -lz -ldl -lrt
LIBS := $(THIRD_PARTY_LIBS) -lpq -lpgport -lpthread -lkrb5 -lgssapi_krb5 -lz -ldl -lrt -lresolv

9 changes: 9 additions & 0 deletions src/odbc/rsodbc/Release/subdir.mk
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ CPP_SRCS += \
../iam/plugins/IAMJwtPluginCredentialsProvider.cpp \
../iam/plugins/IAMJwtBasicCredentialsProvider.cpp \
../iam/plugins/JwtIamAuthPlugin.cpp \
../iam/plugins/IdpTokenAuthPlugin.cpp \
../iam/plugins/BrowserIdcAuthPlugin.cpp \
../iam/plugins/NativePluginCredentialsProvider.cpp \
../iam/plugins/IAMExternalCredentialsProvider.cpp \
../iam/plugins/IAMPluginFactory.cpp

Expand Down Expand Up @@ -113,6 +116,9 @@ OBJS += \
./IAMJwtPluginCredentialsProvider.o \
./IAMJwtBasicCredentialsProvider.o \
./JwtIamAuthPlugin.o \
./IdpTokenAuthPlugin.o \
./BrowserIdcAuthPlugin.o \
./NativePluginCredentialsProvider.o \
./IAMExternalCredentialsProvider.o \
./IAMPluginFactory.o

Expand Down Expand Up @@ -169,8 +175,11 @@ C_DEPS += \
./IAMBrowserAzureCredentialsProvider.d \
./IAMBrowserAzureOAuth2CredentialsProvider.d \
./IAMJwtPluginCredentialsProvider.d \
./NativePluginCredentialsProvider.d \
./IAMJwtBasicCredentialsProvider.d \
./JwtIamAuthPlugin.d \
./IdpTokenAuthPlugin.d \
./BrowserIdcAuthPlugin.d \
./IAMExternalCredentialsProvider.d \
./IAMPluginFactory.d

Expand Down
113 changes: 89 additions & 24 deletions src/odbc/rsodbc/iam/RsIamClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
#include "IAMUtils.h"
#include "RsSettings.h"

#include <ares.h>
#include <ares_dns.h>
#if defined LINUX
#include <arpa/nameser.h>
#include <netdb.h> // Include netdb.h for the complete struct hostent definition
#endif

#include <aws/redshift/model/GetClusterCredentialsRequest.h>
#include <aws/redshift/model/GetClusterCredentialsWithIAMRequest.h>
#include <aws/redshift/model/DescribeClustersRequest.h>
Expand Down Expand Up @@ -42,6 +49,8 @@ namespace
/************************************************************************/
static const rs_string PGO_IAM_ERROR_SSL_DISABLED(
"IAM Authentication requires SSL connection.");
static const rs_string PGO_FEDERATED_NON_IAM_ERROR_SSL_DISABLED(
"Authentication must use an SSL connection.");
}

// Static ==========================================================================================
Expand Down Expand Up @@ -73,14 +82,37 @@ m_log(in_logger)
rsUnlockMutex(s_criticalSection);
}

bool static isIdcOrNativeIdpPlugin(const rs_string &pluginName) {
return IAMUtils::isEqual(IAMUtils::convertStringToWstring(pluginName),
IAMUtils::convertCharStringToWstring(IAM_PLUGIN_BROWSER_AZURE_OAUTH2), false) ||
IAMUtils::isEqual(IAMUtils::convertStringToWstring(pluginName),
IAMUtils::convertCharStringToWstring(PLUGIN_IDP_TOKEN_AUTH), false) ||
IAMUtils::isEqual(IAMUtils::convertStringToWstring(pluginName),
IAMUtils::convertCharStringToWstring(PLUGIN_BROWSER_IDC_AUTH), false);
}

bool static isIdcPlugin(const rs_string &pluginName) {
return IAMUtils::isEqual(IAMUtils::convertStringToWstring(pluginName),
IAMUtils::convertCharStringToWstring(PLUGIN_IDP_TOKEN_AUTH), false) ||
IAMUtils::isEqual(IAMUtils::convertStringToWstring(pluginName),
IAMUtils::convertCharStringToWstring(PLUGIN_BROWSER_IDC_AUTH), false);
}

rs_string RsIamClient::GetPluginName() {
rs_wstring pluginName = m_settings.m_pluginName;
IAMUtils::trim(pluginName);
pluginName = IAMUtils::toLower(pluginName);
return IAMUtils::convertToUTF8(pluginName);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
void RsIamClient::Connect()
{
RS_LOG(m_log)("RsIamClient::Connect");
bool isNativeAuth = false;

ValidateConnectionAttributes();
const rs_string authType = InferCredentialsProvider();
ValidateConnectionAttributes(authType);

RS_LOG(m_log)("RsIamClient::Connect IAM AuthType: %s",
((authType.empty()) ? (char *)"Default" : (char *)authType.c_str()));
Expand All @@ -90,17 +122,22 @@ void RsIamClient::Connect()

if (authType == IAM_AUTH_TYPE_PLUGIN)
{
if (isIdcPlugin(config.GetPluginName()) && m_settings.m_iamAuth) {
IAMUtils::ThrowConnectionExceptionWithInfo(
"You can not use this authentication plugin with IAM enabled.");
}

credentialsProvider = IAMFactory::CreatePluginCredentialsProvider(m_log, config);
if (credentialsProvider)
{
if (IAMUtils::isEqual(IAMUtils::convertStringToWstring(config.GetPluginName()), IAMUtils::convertCharStringToWstring(IAM_PLUGIN_BROWSER_AZURE_OAUTH2), false))
isNativeAuth = true;

if (!isNativeAuth)
{
static_cast<IAMPluginCredentialsProvider&>(*credentialsProvider)
.GetConnectionSettings(m_credentials);
}
if (isIdcOrNativeIdpPlugin(config.GetPluginName())) {
isNativeAuth = true;
}

if (!isNativeAuth) {
static_cast<IAMPluginCredentialsProvider &>(*credentialsProvider)
.GetConnectionSettings(m_credentials);
}
}
}
else if (authType == IAM_AUTH_TYPE_PROFILE)
Expand Down Expand Up @@ -149,14 +186,22 @@ void RsIamClient::Connect()
GetClusterCredentials(credentialsProvider);
}
}
else
{
/* Validate that all required arguments for plugin are provided */
static_cast<IAMJwtPluginCredentialsProvider&>(*credentialsProvider).ValidateArgumentsMap();
rs_string idp_token = static_cast<IAMJwtPluginCredentialsProvider&>(*credentialsProvider).GetJwtAssertion();
m_credentials.SetIdpToken(idp_token);
m_credentials.SetFixExpirationTime();
}
else
{
if (isIdcPlugin(config.GetPluginName())) {
rs_string auth_token =
static_cast<NativePluginCredentialsProvider &>(*credentialsProvider).GetAuthToken();
m_credentials.SetIdpToken(auth_token);
} else { // native idp AzureAD plugin
/* Validate that all required arguments for plugin are provided */
static_cast<IAMJwtPluginCredentialsProvider &>(*credentialsProvider)
.ValidateArgumentsMap();
rs_string idp_token =
static_cast<IAMJwtPluginCredentialsProvider &>(*credentialsProvider).GetJwtAssertion();
m_credentials.SetIdpToken(idp_token);
}
m_credentials.SetFixExpirationTime();
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -278,8 +323,14 @@ Model::GetClusterCredentialsOutcome RsIamClient::SendClusterCredentialsRequest(
inferredAwsRegion = hostnameTokens[2];
}

if(m_settings.m_isCname && inferredAwsRegion.empty() ){
config.region = IAMUtils().GetAwsRegionFromCname(m_settings.m_host);
}
else
{
config.region = m_settings.m_awsRegion.empty() ? inferredAwsRegion : m_settings.m_awsRegion;
config.endpointOverride = IAMUtils::convertToUTF8(m_settings.m_endpointUrl);
}

if (m_settings.m_stsConnectionTimeout > 0)
{
Expand Down Expand Up @@ -411,7 +462,9 @@ Model::GetClusterCredentialsOutcome RsIamClient::SendClusterCredentialsRequest(
request.SetClusterIdentifier(m_settings.m_clusterIdentifer.empty() ? inferredClusterId.c_str() : m_settings.m_clusterIdentifer.c_str()); // Set the cluster identifier instead
}
}
#endif

#endif

/* if host is empty describe cluster using cluster id */
if (m_settings.m_host.empty() || m_settings.m_port == 0) {
if (m_settings.m_clusterIdentifer.empty() && tempClusterIdentifier.empty()) {
Expand Down Expand Up @@ -463,8 +516,14 @@ Model::GetClusterCredentialsWithIAMOutcome RsIamClient::SendClusterCredentialsWi
inferredAwsRegion = hostnameTokens[2];
}

if(m_settings.m_isCname && inferredAwsRegion.empty()){
config.region = IAMUtils().GetAwsRegionFromCname(m_settings.m_host);
}
else
{
config.region = m_settings.m_awsRegion.empty() ? inferredAwsRegion : m_settings.m_awsRegion;
config.endpointOverride = IAMUtils::convertToUTF8(m_settings.m_endpointUrl);
}

if (m_settings.m_stsConnectionTimeout > 0)
{
Expand Down Expand Up @@ -797,7 +856,7 @@ void RsIamClient::GetServerlessCredentials(


////////////////////////////////////////////////////////////////////////////////////////////////////
void RsIamClient::ValidateConnectionAttributes()
void RsIamClient::ValidateConnectionAttributes(const rs_string &in_authType)
{
RS_LOG(m_log)("RsIamClient::ValidateConnectionAttributes");

Expand All @@ -812,6 +871,9 @@ void RsIamClient::ValidateConnectionAttributes()

if (!isSSLModeEnabled)
{
if(in_authType == IAM_AUTH_TYPE_PLUGIN && isIdcOrNativeIdpPlugin(GetPluginName())) {
IAMUtils::ThrowConnectionExceptionWithInfo(PGO_FEDERATED_NON_IAM_ERROR_SSL_DISABLED);
}
IAMUtils::ThrowConnectionExceptionWithInfo(PGO_IAM_ERROR_SSL_DISABLED);
}
}
Expand Down Expand Up @@ -908,10 +970,7 @@ IAMConfiguration RsIamClient::CreateIAMConfiguration(const rs_string& in_authTyp
if (in_authType == IAM_AUTH_TYPE_PLUGIN)
{
/* Plugin AuthType specific connection attributes */
rs_wstring pluginName = m_settings.m_pluginName;
IAMUtils::trim(pluginName);
pluginName = IAMUtils::toLower(pluginName);
config.SetPluginName(IAMUtils::convertToUTF8(pluginName));
config.SetPluginName(GetPluginName());

config.SetIdpHost(IAMUtils::convertToUTF8(m_settings.m_idpHost));
config.SetIdpPort(m_settings.m_idpPort);
Expand All @@ -933,7 +992,13 @@ IAMConfiguration RsIamClient::CreateIAMConfiguration(const rs_string& in_authTyp
config.SetWebIdentityToken(m_settings.m_web_identity_token);
config.SetDuration(m_settings.m_duration);
config.SetRoleSessionName(m_settings.m_role_session_name);
config.SetIdpAuthToken(m_settings.m_idpAuthToken);
config.SetIdpAuthTokenType(m_settings.m_idpAuthTokenType);
config.SetRegion(m_settings.m_awsRegion);
config.SetStartUrl(m_settings.m_startUrl);
config.SetIdcRegion(m_settings.m_idcRegion);
config.SetIdcResponseTimeout(m_settings.m_idcResponseTimeout);
config.SetIdcClientDisplayName(m_settings.m_idcClientDisplayName);
}
else if (in_authType == IAM_AUTH_TYPE_PROFILE)
{
Expand Down Expand Up @@ -1030,4 +1095,4 @@ rs_string RsIamClient::ReadAuthProfile(rs_string auth_profile_name,
const Aws::Redshift::Model::AuthenticationProfile& authProfile = profilesList[0];

return authProfile.GetAuthenticationProfileContent();
}
}
8 changes: 4 additions & 4 deletions src/odbc/rsodbc/iam/RsIamClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,11 @@ namespace RedshiftODBC
rs_string host,
rs_string region);


// count the number of PGOIamClient be initialized, used to InitAPI and ShutdownAPI
static int s_iamClientCount;

// The critical section used for Aws InitAPI LOCK
static MUTEX_HANDLE s_criticalSection;

/// @brief Destructor.
~RsIamClient();

private:
Expand Down Expand Up @@ -163,7 +160,7 @@ namespace RedshiftODBC
/// @brief Validate the connection attributes in PGOSettings
///
/// @exception ErrorException when any attribute in PGOSettings is not valid.
void ValidateConnectionAttributes();
void ValidateConnectionAttributes(const rs_string& in_authType);

/// @brief Infer the credentials provider to used given the connection attribute
rs_string InferCredentialsProvider();
Expand All @@ -176,6 +173,9 @@ namespace RedshiftODBC
Redshift::IamSupport::IAMConfiguration CreateIAMConfiguration(
const rs_string& in_authType = rs_string());

/// @brief Get the plugin name
rs_string GetPluginName();

/// @brief Disabled assignment operator to avoid warning.
///
/// @param in_pgoIamClient The PGOIamClient to assign to the current PGOIamClient.
Expand Down
12 changes: 6 additions & 6 deletions src/odbc/rsodbc/iam/RsIamEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ void RsIamEntry::IamAuthentication(
/*================================================================================================*/

void RsIamEntry::NativePluginAuthentication(
bool isIAMAuth,
RS_IAM_CONN_PROPS_INFO *pIamProps,
RS_PROXY_CONN_PROPS_INFO *pHttpsProps,
RsSettings& settings,
RsLogger *logger)
bool isIAMAuth,
RS_IAM_CONN_PROPS_INFO *pIamProps,
RS_PROXY_CONN_PROPS_INFO *pHttpsProps,
RsSettings& settings,
RsLogger *logger)
{
RsIamHelper::NativePluginAuthentication(isIAMAuth, pIamProps, pHttpsProps, settings, logger);
RsIamHelper::NativePluginAuthentication(isIAMAuth, pIamProps, pHttpsProps, settings, logger);
}

/*================================================================================================*/
Expand Down
Loading

0 comments on commit dd26c3c

Please sign in to comment.