package com.sequenceiq.cloudbreak.cloud.aws;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.apache.commons.lang3.StringUtils.isNoneEmpty;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.InstanceProfileCredentialsProvider;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.autoscaling.AmazonAutoScalingClient;
import com.amazonaws.services.cloudformation.AmazonCloudFormationClient;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.identitymanagement.AmazonIdentityManagement;
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient;
import com.sequenceiq.cloudbreak.cloud.aws.view.AwsCredentialView;
import com.sequenceiq.cloudbreak.cloud.context.AuthenticatedContext;
import com.sequenceiq.cloudbreak.cloud.context.CloudContext;
import com.sequenceiq.cloudbreak.cloud.event.credential.CredentialVerificationException;
import com.sequenceiq.cloudbreak.cloud.exception.CloudConnectorException;
import com.sequenceiq.cloudbreak.cloud.model.CloudCredential;
@Component
public class AwsClient {
private static final String DEFAULT_REGION_NAME = "us-west-1";
private static final Logger LOGGER = LoggerFactory.getLogger(AwsClient.class);
private static final String EXISTING_KEYPAIR_PARAM_KEY = "existingKeyPairName";
@Inject
private AwsPlatformParameters awsPlatformParameters;
@Inject
private AwsSessionCredentialClient credentialClient;
@Inject
private AwsEnvironmentVariableChecker awsEnvironmentVariableChecker;
public AuthenticatedContext createAuthenticatedContext(CloudContext cloudContext, CloudCredential cloudCredential) {
AuthenticatedContext authenticatedContext = new AuthenticatedContext(cloudContext, cloudCredential);
try {
authenticatedContext.putParameter(AmazonEC2Client.class, createAccess(authenticatedContext.getCloudCredential()));
} catch (AmazonServiceException e) {
throw new CredentialVerificationException(e.getErrorMessage(), e);
}
return authenticatedContext;
}
public AmazonEC2Client createAccess(CloudCredential credential) {
return createAccess(new AwsCredentialView(credential), DEFAULT_REGION_NAME);
}
public AmazonEC2Client createAccess(AwsCredentialView awsCredential, String regionName) {
AmazonEC2Client client = isRoleAssumeRequired(awsCredential)
? new AmazonEC2Client(credentialClient.retrieveCachedSessionCredentials(awsCredential))
: new AmazonEC2Client(createAwsCredentials(awsCredential));
client.setRegion(RegionUtils.getRegion(regionName));
return client;
}
public AmazonIdentityManagement createAmazonIdentityManagement(AwsCredentialView awsCredential) {
return isRoleAssumeRequired(awsCredential)
? new AmazonIdentityManagementClient(credentialClient.retrieveCachedSessionCredentials(awsCredential))
: new AmazonIdentityManagementClient(createAwsCredentials(awsCredential));
}
public AmazonCloudFormationClient createCloudFormationClient(AwsCredentialView awsCredential, String regionName) {
AmazonCloudFormationClient client = isRoleAssumeRequired(awsCredential)
? new AmazonCloudFormationClient(credentialClient.retrieveCachedSessionCredentials(awsCredential))
: new AmazonCloudFormationClient(createAwsCredentials(awsCredential));
client.setRegion(RegionUtils.getRegion(regionName));
return client;
}
public AmazonAutoScalingClient createAutoScalingClient(AwsCredentialView awsCredential, String regionName) {
AmazonAutoScalingClient client = isRoleAssumeRequired(awsCredential)
? new AmazonAutoScalingClient(credentialClient.retrieveCachedSessionCredentials(awsCredential))
: new AmazonAutoScalingClient(createAwsCredentials(awsCredential));
client.setRegion(RegionUtils.getRegion(regionName));
return client;
}
public String getCbName(String groupName, Long number) {
return String.format("%s%s", groupName, number);
}
public String getKeyPairName(AuthenticatedContext ac) {
return String.format("%s%s%s%s", ac.getCloudCredential().getName(), ac.getCloudCredential().getId(),
ac.getCloudContext().getName(), ac.getCloudContext().getId());
}
public boolean existingKeyPairNameSpecified(AuthenticatedContext auth) {
return StringUtils.isNoneEmpty(getExistingKeyPairName(auth));
}
public String getExistingKeyPairName(AuthenticatedContext auth) {
CloudCredential cloudCredential = auth.getCloudCredential();
return cloudCredential.getParameter(EXISTING_KEYPAIR_PARAM_KEY, String.class);
}
public void checkAwsEnvironmentVariables(CloudCredential credential) {
AwsCredentialView awsCredential = new AwsCredentialView(credential);
if (isRoleAssumeRequired(awsCredential)) {
if (awsEnvironmentVariableChecker.isAwsAccessKeyAvailable() && !awsEnvironmentVariableChecker.isAwsSecretAccessKeyAvailable()) {
throw new CloudConnectorException("If 'AWS_ACCESS_KEY_ID' available then 'AWS_SECRET_ACCESS_KEY' must be set!");
} else if (awsEnvironmentVariableChecker.isAwsSecretAccessKeyAvailable() && !awsEnvironmentVariableChecker.isAwsAccessKeyAvailable()) {
throw new CloudConnectorException("If 'AWS_SECRET_ACCESS_KEY' available then 'AWS_ACCESS_KEY_ID' must be set!");
} else if (!awsEnvironmentVariableChecker.isAwsAccessKeyAvailable() && !awsEnvironmentVariableChecker.isAwsSecretAccessKeyAvailable()) {
try {
new InstanceProfileCredentialsProvider().getCredentials();
} catch (AmazonClientException e) {
StringBuilder sb = new StringBuilder();
sb.append("The 'AWS_ACCESS_KEY_ID' and 'AWS_SECRET_ACCESS_KEY' environment variables must be set ");
sb.append("or an instance profile role should be available.");
LOGGER.info(sb.toString());
throw new CloudConnectorException(sb.toString());
}
}
}
}
public boolean roleBasedCredential(AwsCredentialView awsCredential) {
return isNoneEmpty(awsCredential.getRoleArn());
}
private boolean isRoleAssumeRequired(AwsCredentialView awsCredential) {
return isNoneEmpty(awsCredential.getRoleArn()) && isEmpty(awsCredential.getAccessKey()) && isEmpty(awsCredential.getSecretKey());
}
private BasicAWSCredentials createAwsCredentials(AwsCredentialView credentialView) {
String accessKey = credentialView.getAccessKey();
String secretKey = credentialView.getSecretKey();
if (isEmpty(accessKey) || isEmpty(secretKey)) {
throw new CloudConnectorException("Missing access or secret key from the credential.");
}
return new BasicAWSCredentials(accessKey, secretKey);
}
}