/* * Copyright 2016 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. * * * Portions copyright Copyright (c) 2015, CloudBees, Inc. * This program is made available under the terms of the MIT License. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.auth.BasicSessionCredentials; import com.amazonaws.regions.Regions; import com.amazonaws.retry.PredefinedBackoffStrategies; import com.amazonaws.retry.RetryPolicy; import com.amazonaws.codebuild.jenkinsplugin.CodeBuildBaseCredentials; import com.amazonaws.services.codebuild.AWSCodeBuildClient; import com.amazonaws.services.codebuild.model.InvalidInputException; import com.amazonaws.services.logs.AWSLogsClient; import com.amazonaws.services.s3.AmazonS3Client; import com.cloudbees.plugins.credentials.Credentials; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.SystemCredentialsProvider; import enums.CredentialsType; import hudson.EnvVars; import hudson.model.Item; import hudson.model.Run; import hudson.util.Secret; import jenkins.model.Jenkins; import lombok.Getter; import org.jenkinsci.plugins.workflow.steps.StepContext; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import static com.amazonaws.auth.profile.internal.ProfileKeyConstants.*; import static com.amazonaws.codebuild.jenkinsplugin.Validation.*; public class AWSClientFactory { @Getter private final String proxyHost; @Getter private final Integer proxyPort; @Getter private final String awsAccessKey; @Getter private final Secret awsSecretKey; @Getter private final String awsSessionToken; @Getter private final String region; private String credentialsDescriptor; private AWSCredentialsProvider awsCredentialsProvider; private final Properties properties; private static final String POM_PROPERTIES = "/META-INF/maven/com.amazonaws/aws-codebuild/pom.properties"; public AWSClientFactory(String credentialsType, String credentialsId, String proxyHost, String proxyPort, String awsAccessKey, Secret awsSecretKey, String awsSessionToken, String region, Run<?, ?> build, StepContext stepContext) { this.awsAccessKey = sanitize(awsAccessKey); this.awsSecretKey = awsSecretKey; this.awsSessionToken = sanitize(awsSessionToken); this.region = sanitize(region); this.properties = new Properties(); CodeBuilderValidation.checkAWSClientFactoryRegionConfig(this.region); this.credentialsDescriptor = ""; if(credentialsType.equals(CredentialsType.Jenkins.toString())) { credentialsId = sanitize(credentialsId); CodeBuilderValidation.checkAWSClientFactoryJenkinsCredentialsConfig(credentialsId); com.amazonaws.codebuild.jenkinsplugin.CodeBuildBaseCredentials codeBuildCredentials; codeBuildCredentials = (CodeBuildBaseCredentials) CredentialsMatchers.firstOrNull(SystemCredentialsProvider.getInstance().getCredentials(), CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialsId))); if(codeBuildCredentials == null) { Item folder; Jenkins instance = Jenkins.getInstance(); if(instance != null) { folder = instance.getItemByFullName(build.getParent().getParent().getFullName()); codeBuildCredentials = (CodeBuildBaseCredentials) CredentialsMatchers.firstOrNull(CredentialsProvider.lookupCredentials(Credentials.class, folder), CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialsId))); } } if(codeBuildCredentials != null) { this.awsCredentialsProvider = codeBuildCredentials; this.proxyHost = codeBuildCredentials.getProxyHost(); this.proxyPort = parseInt(codeBuildCredentials.getProxyPort()); this.credentialsDescriptor = codeBuildCredentials.getCredentialsDescriptor() + " (provided from Jenkins credentials " + credentialsId + ")"; } else { throw new InvalidInputException(CodeBuilderValidation.invalidCredentialsIdError); } } else if(credentialsType.equals(CredentialsType.Keys.toString())) { if(this.awsSecretKey == null) { throw new InvalidInputException(invalidSecretKeyError); } if(stepContext != null && awsAccessKey.isEmpty() && awsSecretKey.getPlainText().isEmpty()) { try { EnvVars stepEnvVars = stepContext.get(EnvVars.class); awsCredentialsProvider = getStepCreds(stepEnvVars); } catch (IOException|InterruptedException e) {} } if(awsCredentialsProvider == null) { awsCredentialsProvider = getBasicCredentialsOrDefaultChain(sanitize(awsAccessKey), awsSecretKey.getPlainText(), sanitize(awsSessionToken)); } this.proxyHost = sanitize(proxyHost); this.proxyPort = parseInt(proxyPort); } else { throw new InvalidInputException(invalidCredTypeError); } } public AWSCodeBuildClient getCodeBuildClient() throws InvalidInputException, IllegalArgumentException { AWSCodeBuildClient client = new AWSCodeBuildClient(awsCredentialsProvider, getClientConfiguration()); client.setEndpoint("https://codebuild." + region + getAwsClientSuffix(region)); return client; } public AmazonS3Client getS3Client() throws InvalidInputException { AmazonS3Client client = new AmazonS3Client(awsCredentialsProvider, getClientConfiguration()); client.setEndpoint("https://s3." + region + getAwsClientSuffix(region)); return client; } public AWSLogsClient getCloudWatchLogsClient() throws InvalidInputException { AWSLogsClient client = new AWSLogsClient(awsCredentialsProvider, getClientConfiguration()); client.setEndpoint("https://logs." + region + getAwsClientSuffix(region)); return client; } private AWSCredentialsProvider getStepCreds(EnvVars stepEnvVars) { String stepAccessKey = stepEnvVars.get(AWS_ACCESS_KEY_ID); String stepSecretKey = stepEnvVars.get(AWS_SECRET_ACCESS_KEY); String stepSessionToken = stepEnvVars.get(AWS_SESSION_TOKEN); if(stepAccessKey != null && !stepAccessKey.isEmpty() && stepSecretKey != null && !stepSecretKey.isEmpty()) { this.credentialsDescriptor = stepCredentials; if(stepSessionToken != null && !stepSessionToken.isEmpty()) { return new AWSStaticCredentialsProvider(new BasicSessionCredentials(stepAccessKey, stepSecretKey, stepSessionToken)); } else { return new AWSStaticCredentialsProvider(new BasicAWSCredentials(stepAccessKey, stepSecretKey)); } } return null; } private ClientConfiguration getClientConfiguration() { String projectVersion = ""; try(InputStream stream = this.getClass().getResourceAsStream(POM_PROPERTIES)) { properties.load(stream); projectVersion = "/" + properties.getProperty("version"); } catch (IOException e) {} ClientConfiguration clientConfig = new ClientConfiguration() .withUserAgentPrefix("CodeBuild-Jenkins-Plugin" + projectVersion) .withProxyHost(proxyHost) .withRetryPolicy(new RetryPolicy(new CodeBuildClientRetryCondition(), new PredefinedBackoffStrategies.ExponentialBackoffStrategy(10000, 30000), 10, true)); if(proxyPort != null) { clientConfig.setProxyPort(proxyPort); } return clientConfig; } public String getCredentialsDescriptor() { if(this.credentialsDescriptor.isEmpty()) { if(awsAccessKey.isEmpty()) { return CodeBuildBaseCredentials.DEFAULT_CHAIN_CREDS; } else { return CodeBuildBaseCredentials.BASIC_AWS_CREDS; } } else { return credentialsDescriptor; } } private String getAwsClientSuffix(String region) { if(region.equals(Regions.CN_NORTH_1.getName().toString()) || region.equals(Regions.CN_NORTHWEST_1.getName().toString())) { return ".amazonaws.com.cn"; } else { return ".amazonaws.com"; } } }