in src/main/java/com/amazon/redshift/core/IamHelper.java [367:590]
private static void setIAMCredentials(RedshiftJDBCSettings settings, RedshiftLogger log, String authProfile) throws RedshiftException {
AWSCredentialsProvider provider;
CredentialProviderType providerType = CredentialProviderType.NONE;
boolean idpCredentialsRefresh = false;
String idpToken = null;
if (!StringUtils.isNullOrEmpty(settings.m_credentialsProvider)) {
if (!StringUtils.isNullOrEmpty(settings.m_profile)) {
RedshiftException err = new RedshiftException(
GT.tr("Conflict in connection property setting {0} and {1}",
RedshiftProperty.CREDENTIALS_PROVIDER.getName(), RedshiftProperty.AWS_PROFILE.getName()),
RedshiftState.UNEXPECTED_ERROR);
if (RedshiftLogger.isEnable())
log.log(LogLevel.ERROR, err.toString());
throw err;
}
if (StringUtils.isNullOrEmpty(authProfile)
&& !StringUtils.isNullOrEmpty(settings.m_iamAccessKeyID)) {
RedshiftException err = new RedshiftException(
GT.tr("Conflict in connection property setting {0} and {1}",
RedshiftProperty.CREDENTIALS_PROVIDER.getName(), RedshiftProperty.IAM_ACCESS_KEY_ID.getName()),
RedshiftState.UNEXPECTED_ERROR);
if (RedshiftLogger.isEnable())
log.log(LogLevel.ERROR, err.toString());
throw err;
}
try {
Class<? extends AWSCredentialsProvider> clazz = (Class.forName(settings.m_credentialsProvider)
.asSubclass(AWSCredentialsProvider.class));
provider = clazz.newInstance();
if (provider instanceof IPlugin) {
IPlugin plugin = ((IPlugin) provider);
providerType = CredentialProviderType.PLUGIN;
plugin.setLogger(log);
plugin.setGroupFederation(settings.m_groupFederation);
for (Map.Entry<String, String> entry : settings.m_pluginArgs.entrySet()) {
String pluginArgKey = entry.getKey();
plugin.addParameter(pluginArgKey, entry.getValue());
if (KEY_PREFERRED_ROLE.equalsIgnoreCase(pluginArgKey))
settings.m_preferredRole = entry.getValue();
else if (KEY_ROLE_ARN.equalsIgnoreCase(pluginArgKey))
settings.m_roleArn = entry.getValue();
else if (KEY_ROLE_SESSION_NAME.equalsIgnoreCase(pluginArgKey))
settings.m_roleSessionName = entry.getValue();
else if (RedshiftProperty.DB_GROUPS_FILTER.getName().equalsIgnoreCase(pluginArgKey))
settings.m_dbGroupsFilter = entry.getValue();
}
}
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
RedshiftException err = new RedshiftException(
GT.tr("Invalid credentials provider class {0}", settings.m_credentialsProvider),
RedshiftState.UNEXPECTED_ERROR, e);
if (RedshiftLogger.isEnable())
log.log(LogLevel.ERROR, err.toString());
throw err;
} catch (NumberFormatException e) {
RedshiftException err = new RedshiftException(
GT.tr("{0} : {1}", e.getMessage(), settings.m_credentialsProvider), RedshiftState.UNEXPECTED_ERROR, e);
if (RedshiftLogger.isEnable())
log.log(LogLevel.ERROR, err.toString());
throw err;
}
} else if (!StringUtils.isNullOrEmpty(settings.m_profile)) {
if (StringUtils.isNullOrEmpty(authProfile)
&& !StringUtils.isNullOrEmpty(settings.m_iamAccessKeyID)) {
RedshiftException err = new RedshiftException(GT.tr("Conflict in connection property setting {0} and {1}",
RedshiftProperty.AWS_PROFILE.getName(), RedshiftProperty.IAM_ACCESS_KEY_ID.getName()),
RedshiftState.UNEXPECTED_ERROR);
if (RedshiftLogger.isEnable())
log.log(LogLevel.ERROR, err.toString());
throw err;
}
ProfilesConfigFile pcf = new PluginProfilesConfigFile(settings, log);
provider = new ProfileCredentialsProvider(pcf, settings.m_profile);
providerType = CredentialProviderType.PROFILE;
} else if (!StringUtils.isNullOrEmpty(settings.m_iamAccessKeyID)) {
AWSCredentials credentials;
if (!StringUtils.isNullOrEmpty(settings.m_iamSessionToken)) {
credentials = new BasicSessionCredentials(settings.m_iamAccessKeyID, settings.m_iamSecretKey,
settings.m_iamSessionToken);
providerType = CredentialProviderType.IAM_KEYS_WITH_SESSION;
} else {
credentials = new BasicAWSCredentials(settings.m_iamAccessKeyID, settings.m_iamSecretKey);
providerType = CredentialProviderType.IAM_KEYS;
}
provider = new AWSStaticCredentialsProvider(credentials);
} else {
provider = new DefaultAWSCredentialsProviderChain();
}
if (RedshiftLogger.isEnable())
log.log(LogLevel.DEBUG, "IDP Credential Provider {0}:{1}", provider, settings.m_credentialsProvider);
int getClusterCredentialApiType = findTypeOfGetClusterCredentialsAPI(settings, providerType, provider);
if (getClusterCredentialApiType == GET_CLUSTER_CREDENTIALS_V1_API
|| getClusterCredentialApiType == GET_CLUSTER_CREDENTIALS_IAM_V2_API
|| getClusterCredentialApiType == GET_SERVERLESS_CREDENTIALS_V1_API) {
if (RedshiftLogger.isEnable())
log.log(LogLevel.DEBUG, "Calling provider.getCredentials()");
// Provider will cache the credentials, it's OK to call getCredentials()
// here.
AWSCredentials credentials = provider.getCredentials();
if (credentials instanceof CredentialsHolder) {
idpCredentialsRefresh = ((CredentialsHolder) credentials).isRefresh();
// autoCreate, user and password from URL take priority.
CredentialsHolder.IamMetadata im = ((CredentialsHolder) credentials).getMetadata();
if (null != im) {
Boolean autoCreate = im.getAutoCreate();
String dbUser = im.getDbUser();
String samlDbUser = im.getSamlDbUser();
String profileDbUser = im.getProfileDbUser();
String dbGroups = im.getDbGroups();
boolean forceLowercase = im.getForceLowercase();
boolean allowDbUserOverride = im.getAllowDbUserOverride();
if (null == settings.m_autocreate) {
settings.m_autocreate = autoCreate;
}
if (null == settings.m_forceLowercase) {
settings.m_forceLowercase = forceLowercase;
}
/*
* Order of precedence when configuring settings.m_dbUser:
*
* If allowDbUserOverride = true: 1. Value from SAML assertion. 2.
* Value from connection string setting. 3. Value from credentials
* profile setting.
*
* If allowDbUserOverride = false (default): 1. Value from connection
* string setting. 2. Value from credentials profile setting. 3. Value
* from SAML assertion.
*/
if (allowDbUserOverride) {
if (null != samlDbUser) {
settings.m_dbUser = samlDbUser;
} else if (null != dbUser) {
settings.m_dbUser = dbUser;
} else if (null != profileDbUser) {
settings.m_dbUser = profileDbUser;
}
} else {
if (null != dbUser) {
settings.m_dbUser = dbUser;
} else if (null != profileDbUser) {
settings.m_dbUser = profileDbUser;
} else if (null != samlDbUser) {
settings.m_dbUser = samlDbUser;
}
}
if (settings.m_dbGroups.isEmpty() && null != dbGroups) {
settings.m_dbGroups = Arrays
.asList((settings.m_forceLowercase ? dbGroups.toLowerCase(Locale.getDefault()) : dbGroups).split(","));
}
}
}
if ("*".equals(settings.m_username) && null == settings.m_dbUser) {
RedshiftException err = new RedshiftException(
GT.tr("Missing connection property {0}", RedshiftProperty.DB_USER.getName()),
RedshiftState.UNEXPECTED_ERROR);
if (RedshiftLogger.isEnable())
log.log(LogLevel.ERROR, err.toString());
throw err;
}
} // V1 Or IAM_V2 API for provisional cluster or serverless
else {
// TODO not yet decided
if (RedshiftLogger.isEnable())
log.log(LogLevel.DEBUG, "groupFederation=" + settings.m_groupFederation);
// Check for GetClusterCredentialsV2 cache
// Combine key of IDP and V2 API
String key = null;
GetClusterCredentialsWithIAMResult credentials = null;
if (!settings.m_iamDisableCache) {
key = getCredentialsV2CacheKey(settings, providerType, provider, getClusterCredentialApiType, false);
credentials = credentialsV2Cache.get(key);
}
if (credentials == null
|| credentials.getExpiration().before(new Date(System.currentTimeMillis() - 60 * 1000 * 5))) {
// If not found or expired
// Get IDP token
if (providerType == CredentialProviderType.PLUGIN) {
IPlugin plugin = (IPlugin) provider;
if (RedshiftLogger.isEnable())
log.log(LogLevel.DEBUG, "Calling plugin.getIdpToken()");
idpToken = plugin.getIdpToken();
}
settings.m_idpToken = idpToken;
}
} // Group federation API for plugin
setClusterCredentials(provider, settings, log, providerType, idpCredentialsRefresh, getClusterCredentialApiType);
}