private static void setIAMCredentials()

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);
  }