Skip to content

Commit

Permalink
[JENKINS-34437] Enable amazon-ecr-plugin behind proxy (#9)
Browse files Browse the repository at this point in the history
* upgrade parent pom
set minor version to 1.651.3
upgrade Credentials Plugin
upgrade AWS Java SDK Plugin
upgrade AWS Credentials Plugin
upgrade Docket Commons Plugin

* add support to proxy configuration
change deprecated annotations

* change deprecated annotations

* improve log

* improve log

* improve performance on getDescription there was a call to getCredentials that consumes too much time and it is not need
improve log in FINEST and ALL levels

* Update pom.xml
  • Loading branch information
kuisathaverat committed May 3, 2017
1 parent bdb1576 commit a5e88f2
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 39 deletions.
14 changes: 7 additions & 7 deletions pom.xml
Expand Up @@ -30,7 +30,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>2.9</version>
<version>2.21</version>
</parent>

<groupId>com.cloudbees.jenkins.plugins</groupId>
Expand All @@ -43,8 +43,8 @@
<url>https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR</url>

<properties>
<jenkins.version>1.609</jenkins.version>
<java.level>6</java.level>
<jenkins.version>1.642.1</jenkins.version>
<java.level>7</java.level>
<powermock.version>1.6.1</powermock.version>
</properties>

Expand Down Expand Up @@ -104,22 +104,22 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials</artifactId>
<version>1.24</version>
<version>2.1.11</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.10.45</version>
<version>1.11.68.1</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>aws-credentials</artifactId>
<version>1.10</version>
<version>1.19</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>docker-commons</artifactId>
<version>1.2</version>
<version>1.6</version>
</dependency>
</dependencies>

Expand Down
Expand Up @@ -25,7 +25,6 @@

package com.cloudbees.jenkins.plugins.amazonecr;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.ecr.AmazonECRClient;
Expand All @@ -38,93 +37,113 @@
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.ItemGroup;
import hudson.security.ACL;
import hudson.util.Secret;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* This new kind of credential provides an embedded {@link com.amazonaws.auth.AWSCredentials}
* when a credential for Amazon ECS Registry end point is needed.
*/
public class AmazonECSRegistryCredential extends BaseStandardCredentials implements StandardUsernamePasswordCredentials {
private static final Logger LOG = Logger.getLogger(AmazonECSRegistryCredential.class.getName());

private final String credentialsId;

private final Regions region;

private final ItemGroup itemGroup;

public AmazonECSRegistryCredential(CredentialsScope scope, @NonNull String credentialsId,
public AmazonECSRegistryCredential(CredentialsScope scope, @Nonnull String credentialsId,
String description, ItemGroup itemGroup) {
this(scope, credentialsId, Regions.US_EAST_1, description, itemGroup);
this(scope, credentialsId, Regions.US_EAST_1, description, (ItemGroup<?>)itemGroup);
}

public AmazonECSRegistryCredential(@CheckForNull CredentialsScope scope, @NonNull String credentialsId,
public AmazonECSRegistryCredential(@CheckForNull CredentialsScope scope, @Nonnull String credentialsId,
Regions region, String description, ItemGroup itemGroup) {
super(scope, "ecr:" + region.getName() + ":" + credentialsId, "Amazon ECR Registry : "
+ (StringUtils.isNotBlank(description) ? description + " - " : "" ) + region);
super(scope, "ecr:" + region.getName() + ":" + credentialsId, "Amazon ECR Registry:"
+ (StringUtils.isNotBlank(description) ? description : credentialsId) + "-" + region);
this.credentialsId = credentialsId;
this.region = region;
this.itemGroup = itemGroup;
}


@Nonnull
public String getCredentialsId() {
return credentialsId;
}

public @CheckForNull AmazonWebServicesCredentials getCredentials() {
LOG.log(Level.FINE,"Looking for Amazon web credentials ID: {0} Region: {1}", new Object[]{this.credentialsId,this.region});
List<AmazonWebServicesCredentials> credentials = CredentialsProvider.lookupCredentials(
AmazonWebServicesCredentials.class, itemGroup, ACL.SYSTEM, Collections.EMPTY_LIST);

if(LOG.isLoggable(Level.FINEST)){
String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(new Throwable());
LOG.log(Level.FINEST,"Trace : {0}", fullStackTrace);
}

if (credentials.isEmpty()) {
LOG.fine("ID Not found");
return null;
}

for (AmazonWebServicesCredentials awsCredentials : credentials) {
if (awsCredentials.getId().equals(this.credentialsId)) {
LOG.log(Level.FINE,"ID found {0}" , this.credentialsId);
return awsCredentials;
}
}
LOG.fine("ID Not found");
return null;
}

@Nonnull
public String getDescription() {
final AmazonWebServicesCredentials credentials = getCredentials();
return credentials == null ? "No Valid Credential" : CredentialsNameProvider.name(credentials)
+ " " + (StringUtils.isNotBlank(credentials.getDescription()) ? region : super.getDescription());
String description = super.getDescription();
LOG.finest(description);
return description;
}

@NonNull
@Nonnull
@Override
public Secret getPassword() {
final AmazonWebServicesCredentials credentials = getCredentials();
if (credentials == null) throw new IllegalStateException("Invalid credentials");

final AmazonECRClient client = new AmazonECRClient(credentials.getCredentials(), new ClientConfiguration());
LOG.log(Level.FINE,"Get Password for {0} region : {1}", new Object[]{credentials.getDisplayName(), region});
if(LOG.isLoggable(Level.ALL)){
String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(new Throwable());
LOG.log(Level.ALL,"Trace : {0}", fullStackTrace);
}
com.amazonaws.AmazonECRClientFactory factory = new com.amazonaws.AmazonECRClientFactory();
final AmazonECRClient client = factory.getAmazonECRClientWithProxy(credentials.getCredentials());
client.setRegion(Region.getRegion(region));

final GetAuthorizationTokenResult authorizationToken = client.getAuthorizationToken(new GetAuthorizationTokenRequest());
final List<AuthorizationData> authorizationData = authorizationToken.getAuthorizationData();
if (authorizationData == null || authorizationData.isEmpty()) {
throw new IllegalStateException("Failed to retreive authorization token for Amazon ECR");
}
LOG.fine("Success");
return Secret.fromString(authorizationData.get(0).getAuthorizationToken());
}

@NonNull
@Nonnull
@Override
public String getUsername() {
return "AWS";
}

@Nonnull
public String getEmail() {
return "nobody@example.com";
}
Expand Down
Expand Up @@ -25,23 +25,18 @@

package com.cloudbees.jenkins.plugins.amazonecr;

import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.cloudbees.jenkins.plugins.awscredentials.AmazonWebServicesCredentials;
import com.cloudbees.plugins.credentials.Credentials;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import hudson.Extension;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.security.ACL;
import org.acegisecurity.Authentication;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
Expand All @@ -55,28 +50,28 @@
@Extension
public class AmazonECSRegistryCredentialsProvider extends CredentialsProvider {

private static final Logger LOGGER = Logger.getLogger(AmazonECSRegistryCredentialsProvider.class.getName());
private static final Logger LOG = Logger.getLogger(AmazonECSRegistryCredentialsProvider.class.getName());

@NonNull
@Nonnull
@Override
public <C extends Credentials> List<C> getCredentials(@NonNull Class<C> type, @Nullable ItemGroup itemGroup, @Nullable Authentication authentication) {
public <C extends Credentials> List<C> getCredentials(@Nonnull Class<C> type, @Nullable ItemGroup itemGroup, @Nullable Authentication authentication) {

if (!type.isAssignableFrom(AmazonECSRegistryCredential.class)) {
return ImmutableList.of();
}

List<C> derived = Lists.newLinkedList();

final List<AmazonWebServicesCredentials> list = lookupCredentials(AmazonWebServicesCredentials.class, itemGroup, ACL.SYSTEM , Collections.EMPTY_LIST);
final List<AmazonWebServicesCredentials> list = lookupCredentials(AmazonWebServicesCredentials.class, itemGroup, authentication , Collections.EMPTY_LIST);

for (AmazonWebServicesCredentials credentials : list) {
LOGGER.log(Level.FINE, "Resolving Amazon Web Services credentials of scope {0} with id {1} , itemgroup {2}",
LOG.log(Level.FINE, "Resolving Amazon Web Services credentials of scope {0} with id {1} , itemgroup {2}",
new Object[]{credentials.getScope(), credentials.getId(),itemGroup});
derived.add((C) new AmazonECSRegistryCredential( credentials.getScope(),
credentials.getId(),credentials.getDescription(),itemGroup));

for (Regions region : Regions.values()) {
LOGGER.log(Level.FINE, "Resolving Amazon Web Services credentials of scope {0} with id {1} and region {2}",
LOG.log(Level.FINE, "Resolving Amazon Web Services credentials of scope {0} with id {1} and region {2}",
new Object[]{credentials.getScope(), credentials.getId(),region});
derived.add((C) new AmazonECSRegistryCredential( credentials.getScope(),
credentials.getId(),
Expand Down
Expand Up @@ -25,26 +25,33 @@

package com.cloudbees.jenkins.plugins.amazonecr;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.util.Secret;
import jenkins.authentication.tokens.api.AuthenticationTokenException;
import jenkins.authentication.tokens.api.AuthenticationTokenSource;
import org.jenkinsci.plugins.docker.commons.credentials.DockerRegistryToken;

import javax.annotation.Nonnull;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
@Extension
public class AmazonECSRegistryTokenSource extends AuthenticationTokenSource<DockerRegistryToken, AmazonECSRegistryCredential> {

private static final Logger LOG = Logger.getLogger(AmazonECSRegistryTokenSource.class.getName());


public AmazonECSRegistryTokenSource() {
super(DockerRegistryToken.class, AmazonECSRegistryCredential.class);
}

@NonNull
@Nonnull
@Override
public DockerRegistryToken convert(@NonNull AmazonECSRegistryCredential credential) throws AuthenticationTokenException {
public DockerRegistryToken convert(@Nonnull AmazonECSRegistryCredential credential) throws AuthenticationTokenException {
LOG.log(Level.FINE,"Converting credential to Docker registry token : {0}",credential.getCredentialsId());
return new DockerRegistryToken(credential.getEmail(), Secret.toString(credential.getPassword()));
}
}

0 comments on commit a5e88f2

Please sign in to comment.