diff --git a/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AWSCredentialsImpl.java b/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AWSCredentialsImpl.java index 9e530da..91a860a 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AWSCredentialsImpl.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AWSCredentialsImpl.java @@ -28,8 +28,8 @@ import com.amazonaws.AmazonClientException; import com.amazonaws.AmazonServiceException; import com.amazonaws.ClientConfiguration; -import com.amazonaws.SdkClientException; import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.auth.BasicSessionCredentials; @@ -131,35 +131,16 @@ public AWSCredentials getCredentials() { if (StringUtils.isBlank(iamRoleArn)) { return initialCredentials; } else { - // Check for available region from the SDK, otherwise specify default - String clientRegion = null; - DefaultAwsRegionProviderChain sdkRegionLookup = new DefaultAwsRegionProviderChain(); - try { - clientRegion = sdkRegionLookup.getRegion(); - } catch (RuntimeException e) { - LOGGER.log(Level.WARNING, "Could not find default region using SDK lookup.", e); - } - if (clientRegion == null) { - clientRegion = Regions.DEFAULT_REGION.getName(); - } - - ClientConfiguration clientConfiguration = getClientConfiguration(); - - AWSSecurityTokenService client; + AWSCredentialsProvider baseProvider; // Handle the case of delegation to instance profile if (StringUtils.isBlank(accessKey) && StringUtils.isBlank(secretKey.getPlainText())) { - client = AWSSecurityTokenServiceClientBuilder.standard() - .withRegion(clientRegion) - .withClientConfiguration(clientConfiguration) - .build(); + baseProvider = null; } else { - client = AWSSecurityTokenServiceClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(initialCredentials)) - .withRegion(clientRegion) - .withClientConfiguration(clientConfiguration) - .build(); + baseProvider = new AWSStaticCredentialsProvider(initialCredentials); } + AWSSecurityTokenService client = buildStsClient(baseProvider); + AssumeRoleRequest assumeRequest = createAssumeRoleRequest(iamRoleArn) .withDurationSeconds(this.getStsTokenDuration()); @@ -200,6 +181,30 @@ public String getDisplayName() { return accessKey + ":" + iamRoleArn; } + /*package*/ static AWSSecurityTokenService buildStsClient(AWSCredentialsProvider provider) { + // Check for available region from the SDK, otherwise specify default + String clientRegion = null; + DefaultAwsRegionProviderChain sdkRegionLookup = new DefaultAwsRegionProviderChain(); + try { + clientRegion = sdkRegionLookup.getRegion(); + } catch(RuntimeException e) { + LOGGER.log(Level.WARNING, "Could not find default region using SDK lookup.", e); + } + if (clientRegion == null) { + clientRegion = Regions.DEFAULT_REGION.getName(); + } + + AWSSecurityTokenServiceClientBuilder builder = AWSSecurityTokenServiceClientBuilder.standard() + .withRegion(clientRegion) + .withClientConfiguration(getClientConfiguration()); + + if (provider != null) { + builder = builder.withCredentials(provider); + } + + return builder.build(); + } + private static AssumeRoleRequest createAssumeRoleRequest(String iamRoleArn) { return new AssumeRoleRequest() .withRoleArn(iamRoleArn) diff --git a/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AmazonWebServicesCredentialsBinding.java b/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AmazonWebServicesCredentialsBinding.java index 4c91028..bfe2dd8 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AmazonWebServicesCredentialsBinding.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/awscredentials/AmazonWebServicesCredentialsBinding.java @@ -27,6 +27,10 @@ import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSSessionCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSSessionCredentialsProvider; +import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider; +import com.amazonaws.services.securitytoken.AWSSecurityTokenService; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import hudson.Extension; @@ -39,6 +43,7 @@ import org.jenkinsci.plugins.credentialsbinding.MultiBinding; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; import javax.annotation.Nonnull; import java.io.IOException; @@ -62,6 +67,10 @@ public class AmazonWebServicesCredentialsBinding extends MultiBinding type() { return AmazonWebServicesCredentials.class; @@ -92,7 +116,13 @@ protected Class type() { @Override public MultiEnvironment bind(@Nonnull Run build, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException { - AWSCredentials credentials = getCredentials(build).getCredentials(); + AWSCredentialsProvider provider = getCredentials(build); + if (!StringUtils.isEmpty(this.roleArn)) { + provider = this.assumeRoleProvider(provider); + } + + AWSCredentials credentials = provider.getCredentials(); + Map m = new HashMap(); m.put(accessKeyVariable, credentials.getAWSAccessKeyId()); m.put(secretKeyVariable, credentials.getAWSSecretKey()); @@ -104,9 +134,26 @@ public MultiEnvironment bind(@Nonnull Run build, FilePath workspace, Launc return new MultiEnvironment(m); } + private AWSSessionCredentialsProvider assumeRoleProvider(AWSCredentialsProvider baseProvider) { + AWSSecurityTokenService stsClient = AWSCredentialsImpl.buildStsClient(baseProvider); + + String roleSessionName = StringUtils.defaultIfBlank(this.roleSessionName, "Jenkins"); + + STSAssumeRoleSessionCredentialsProvider.Builder assumeRoleProviderBuilder = + new STSAssumeRoleSessionCredentialsProvider.Builder(this.roleArn, roleSessionName) + .withStsClient(stsClient); + + if (this.roleSessionDurationSeconds > 0) { + assumeRoleProviderBuilder = assumeRoleProviderBuilder + .withRoleSessionDurationSeconds(this.roleSessionDurationSeconds); + } + + return assumeRoleProviderBuilder.build(); + } + @Override public Set variables() { - return new HashSet(Arrays.asList(accessKeyVariable, secretKeyVariable)); + return new HashSet(Arrays.asList(accessKeyVariable, secretKeyVariable, SESSION_TOKEN_VARIABLE_NAME)); } @Symbol("aws")