/*
* Copyright (c) 2014 Denis Mikhalkin.
*
* This software is provided to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.denismo.aws.iam;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
/**
* User: Denis Mikhalkin
* Date: 27/11/2014
* Time: 6:48 PM
*/
public class IAMAccountPasswordValidator implements _IAMPasswordValidator {
private static final Logger LOG = LoggerFactory.getLogger(IAMAccountPasswordValidator.class);
@Override
public boolean verifyIAMPassword(Entry user, String pw) throws LdapInvalidAttributeValueException, LdapAuthenticationException {
try {
LOG.debug("Verifying {} {} with accessKey <hidden> and secretKey <hidden>",
"user", user.get("uid").getString());
HttpClient client = new SystemDefaultHttpClient();
HttpPost post = new HttpPost("https://signin.aws.amazon.com/oauth");
post.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36");
post.setHeader("Referer", "https://signin.aws.amazon.com/oauth");
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("client_id", "arn:aws:iam::015428540659:user/homepage"));
urlParameters.add(new BasicNameValuePair("isIAMUser", "1"));
urlParameters.add(new BasicNameValuePair("account", user.get("accountNumber").getString()));
urlParameters.add(new BasicNameValuePair("username", user.get("uid").getString()));
urlParameters.add(new BasicNameValuePair("password", pw));
urlParameters.add(new BasicNameValuePair("Action", "login"));
urlParameters.add(new BasicNameValuePair("redirect_uri", "https://console.aws.amazon.com/console/home?state=hashArgs%23&isauthcode=true"));
urlParameters.add(new BasicNameValuePair("forceMobileApp", ""));
urlParameters.add(new BasicNameValuePair("forceMobileLayout", ""));
urlParameters.add(new BasicNameValuePair("mfaLoginFailure", ""));
urlParameters.add(new BasicNameValuePair("RemainingExpiryPeriod", ""));
urlParameters.add(new BasicNameValuePair("mfacode", ""));
urlParameters.add(new BasicNameValuePair("next_mfacode", ""));
post.setEntity(new UrlEncodedFormEntity(urlParameters, Charset.forName("UTF-8")));
HttpResponse response = client.execute(post);
return containsHeaders(response, "aws-account-alias", "aws-creds");
} catch (IOException e) {
LOG.error("Exception validating password for " + user.get("uid").getString(), e);
return false;
} catch (RuntimeException t) {
LOG.error("Exception validating password for " + user.get("uid").getString(), t);
throw t;
}
}
private boolean containsHeaders(HttpResponse response, String... headers) {
Header[] headerList = response.getHeaders("Set-Cookie");
Set<String> lookup = new HashSet<String>(Arrays.asList(headers));
for (Header header : headerList) {
String value = header.getValue();
if (!value.contains("=")) continue;
String[] parts = value.split("=");
if (parts.length < 2) continue;
lookup.remove(parts[0]);
}
return lookup.isEmpty();
}
}