/*
* Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.amazonaws.codedeploy;
import static org.apache.commons.lang.StringUtils.isEmpty;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.UUID;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.codedeploy.AmazonCodeDeployClient;
import com.amazonaws.services.codedeploy.model.GetApplicationRequest;
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient;
import com.amazonaws.services.identitymanagement.model.GetUserResult;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
import com.amazonaws.services.securitytoken.model.AssumeRoleResult;
import com.amazonaws.services.securitytoken.model.Credentials;
/**
* @author gibbon
*/
public class AWSClients {
/**
* Index in the colon-separated ARN that contains the account id
* Sample ARN: arn:aws:iam::123456789012:user/David
**/
private static final int ARN_ACCOUNT_ID_INDEX = 4;
public final AmazonCodeDeployClient codedeploy;
public final AmazonS3Client s3;
private final String region;
private final String proxyHost;
private final int proxyPort;
public AWSClients(String region, AWSCredentials credentials, String proxyHost, int proxyPort) {
this.region = region;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
//setup proxy connection:
ClientConfiguration clientCfg = new ClientConfiguration();
if (proxyHost != null && proxyPort > 0 ) {
clientCfg.setProxyHost(proxyHost);
clientCfg.setProxyPort(proxyPort);
}
this.s3 = credentials != null ? new AmazonS3Client(credentials, clientCfg) : new AmazonS3Client(clientCfg);
this.codedeploy = credentials != null ? new AmazonCodeDeployClient(credentials, clientCfg) : new AmazonCodeDeployClient(clientCfg);
codedeploy.setRegion(Region.getRegion(Regions.fromName(this.region)));
s3.setRegion(Region.getRegion(Regions.fromName(this.region)));
}
public static AWSClients fromDefaultCredentialChain(String region, String proxyHost, int proxyPort) {
return new AWSClients(region, null, proxyHost, proxyPort);
}
public static AWSClients fromIAMRole(String region, String iamRole, String externalId, String proxyHost, int proxyPort) {
return new AWSClients(region, getCredentials(iamRole, externalId), proxyHost, proxyPort);
}
public static AWSClients fromBasicCredentials(String region, String awsAccessKey, String awsSecretKey, String proxyHost, int proxyPort) {
return new AWSClients(region, new BasicAWSCredentials(awsAccessKey, awsSecretKey), proxyHost, proxyPort);
}
/**
* Via the default provider chain (i.e., global keys for this Jenkins instance), return the account ID for the
* currently authenticated user.
* @return 12-digit account id
*/
public static String getAccountId(String proxyHost, int proxyPort) {
String arn = "";
try {
ClientConfiguration clientCfg = new ClientConfiguration();
if (proxyHost != null && proxyPort > 0 ) {
clientCfg.setProxyHost(proxyHost);
clientCfg.setProxyPort(proxyPort);
}
AmazonIdentityManagementClient iam = new AmazonIdentityManagementClient(clientCfg);
GetUserResult user = iam.getUser();
arn = user.getUser().getArn();
} catch (AmazonServiceException e) {
if (e.getErrorCode().compareTo("AccessDenied") == 0) {
String msg = e.getMessage();
int arnIdx = msg.indexOf("arn:aws");
if (arnIdx != -1) {
int arnSpace = msg.indexOf(" ", arnIdx);
arn = msg.substring(arnIdx, arnSpace);
}
}
}
String accountId = arn.split(":")[ARN_ACCOUNT_ID_INDEX];
return accountId;
}
public void testConnection(String s3bucket, String codeDeployApplication) throws Exception {
String testKey = "tmp-" + UUID.randomUUID() + ".txt";
s3.putObject(s3bucket, testKey, createTestFile());
codedeploy.getApplication(new GetApplicationRequest().withApplicationName(codeDeployApplication));
}
private File createTestFile() throws IOException {
File file = File.createTempFile("codedeploy-jenkins-plugin", ".txt");
file.deleteOnExit();
Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
writer.write("");
writer.close();
return file;
}
private static AWSCredentials getCredentials(String iamRole, String externalId) {
if (isEmpty(iamRole)) return null;
AWSSecurityTokenServiceClient sts = new AWSSecurityTokenServiceClient();
int credsDuration = (int) (AWSCodeDeployPublisher.DEFAULT_TIMEOUT_SECONDS
* AWSCodeDeployPublisher.DEFAULT_POLLING_FREQUENCY_SECONDS);
if (credsDuration > 3600) {
credsDuration = 3600;
}
AssumeRoleResult assumeRoleResult = sts.assumeRole(new AssumeRoleRequest()
.withRoleArn(iamRole)
.withExternalId(externalId)
.withDurationSeconds(credsDuration)
.withRoleSessionName(AWSCodeDeployPublisher.ROLE_SESSION_NAME)
);
Credentials stsCredentials = assumeRoleResult.getCredentials();
BasicSessionCredentials credentials = new BasicSessionCredentials(
stsCredentials.getAccessKeyId(),
stsCredentials.getSecretAccessKey(),
stsCredentials.getSessionToken()
);
return credentials;
}
public int getProxyPort() {
return proxyPort;
}
public String getProxyHost() {
return proxyHost;
}
}