in src/main/java/com/amazon/redshift/plugin/PingCredentialsProvider.java [62:224]
protected String getSamlAssertion() throws IOException
{
checkRequiredParameters();
// If no value was specified for m_partnerSpid use the AWS default.
if (StringUtils.isNullOrEmpty(m_partnerSpId))
{
m_partnerSpId = "urn%3Aamazon%3Awebservices";
}
else
{
// Ensure that the string is properly encoded.
m_partnerSpId = URLEncoder.encode(m_partnerSpId, "UTF-8");
}
String uri = "https://" +
m_idpHost + ':' + m_idpPort +
"/idp/startSSO.ping?PartnerSpId=" + m_partnerSpId;
CloseableHttpClient client = null;
List<NameValuePair> parameters = new ArrayList<NameValuePair>(5);
try
{
CloseableHttpResponse resp;
if (RedshiftLogger.isEnable())
m_log.logDebug("uri: {0}", uri);
client = getHttpClient();
HttpGet get = new HttpGet(uri);
resp = client.execute(get);
if (resp.getStatusLine().getStatusCode() != 200)
{
if(RedshiftLogger.isEnable())
m_log.log(LogLevel.DEBUG, "getSamlAssertion https response:" + EntityUtils.toString(resp.getEntity()));
throw new IOException(
"Failed send request: " + resp.getStatusLine().getReasonPhrase());
}
HttpEntity entity = resp.getEntity();
String body = EntityUtils.toString(entity);
BasicNameValuePair username = null;
BasicNameValuePair pass = null;
String password_tag = null;
if (RedshiftLogger.isEnable())
m_log.logDebug("body: {0}", body);
for (String inputTag : getInputTagsfromHTML(body))
{
String name = getValueByKey(inputTag, "name");
String id = getValueByKey(inputTag, "id");
String value = getValueByKey(inputTag, "value");
if (RedshiftLogger.isEnable())
m_log.logDebug("name: {0} , id: {1}", name, id);
if (username == null
&& (("username".equals(id))
|| ("pf.username".equals(id))
|| ("username".equals(name))
|| ("pf.username".equals(name))
)
&& isText(inputTag))
{
username = new BasicNameValuePair(name, m_userName);
}
else if (("pf.pass".equals(name)
|| name.contains("pass")
)
&& isPassword(inputTag))
{
if (pass != null)
{
if(RedshiftLogger.isEnable()) {
m_log.log(LogLevel.DEBUG, format("pass field: %s " +
"has conflict with field: %s",
password_tag, inputTag));
m_log.log(LogLevel.DEBUG, body);
}
throw new IOException("Duplicate password fields on " +
"login page.");
}
password_tag = inputTag;
pass = new BasicNameValuePair(name, m_password);
}
else if (!StringUtils.isNullOrEmpty(name))
{
parameters.add(new BasicNameValuePair(name, value));
}
}
if( username == null )
{
for (String inputTag : getInputTagsfromHTML(body))
{
String name = getValueByKey(inputTag, "name");
if(RedshiftLogger.isEnable()) {
m_log.log(LogLevel.DEBUG, format("inputTag: %s " +
"has name with field: %s",
inputTag, name));
}
if (("email".equals(name) || name.contains("user")
|| name.contains("email")) && isText(inputTag))
{
username = new BasicNameValuePair(name, m_userName);
}
}
}
if (username == null || pass == null)
{
boolean noUserName = (username == null);
boolean noPass = (pass == null);
if(RedshiftLogger.isEnable())
m_log.log(LogLevel.DEBUG, body);
throw new IOException("Failed to parse login form. noUserName = " + noUserName + " noPass=" + noPass);
}
parameters.add(username);
parameters.add(pass);
String action = getFormAction(body);
if (!StringUtils.isNullOrEmpty(action) && action.startsWith("/"))
{
uri = "https://" + m_idpHost + ':' + m_idpPort + action;
}
if (RedshiftLogger.isEnable())
m_log.logDebug("action uri: {0}", uri);
HttpPost post = new HttpPost(uri);
post.setEntity(new UrlEncodedFormEntity(parameters));
resp = client.execute(post);
if (resp.getStatusLine().getStatusCode() != 200)
{
throw new IOException(
"Failed send request: " + resp.getStatusLine().getReasonPhrase());
}
String content = EntityUtils.toString(resp.getEntity());
Matcher matcher = SAML_PATTERN.matcher(content);
if (!matcher.find())
{
throw new IOException("Failed to retrieve SAMLAssertion.");
}
return matcher.group(1);
}
catch (GeneralSecurityException e)
{
throw new SdkClientException("Failed create SSLContext.", e);
}
finally
{
IOUtils.closeQuietly(client, null);
}
}