Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Add logic that allows some credential providers to be skippable (#39)
Browse files Browse the repository at this point in the history
* Add logic that allows some credential providers to be skippable

* Cache results of env utils
  • Loading branch information
fieldju authored Sep 25, 2018
1 parent 6f2d18c commit a4aedbc
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 7 deletions.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ apply plugin: 'com.jfrog.bintray'
apply plugin: 'maven-publish'
apply plugin: "com.github.johnrengelman.shadow"

sourceCompatibility = 1.7
targetCompatibility = 1.7
sourceCompatibility = 1.8
targetCompatibility = 1.8

task copyProjectVersion() {
def releaseVersion = version
Expand All @@ -40,4 +40,4 @@ apply from: file('gradle/check.gradle')
apply from: file('gradle/integration.gradle')
apply from: file('gradle/bintray.gradle')

group = groupId
group = groupId
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
version=5.3.1
version=6.0.0
groupId=com.nike
artifactId=cerberus-client
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@

package com.nike.cerberus.client.auth;


public interface CerberusCredentialsProvider {

CerberusCredentials getCredentials();

/**
* Overrideable method to tell a provider chain if a provider should be ran.
* @return true if the provider should run.
*/
default boolean shouldRun() {
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public CerberusCredentials getCredentials() {

List<String> logMessages = new ArrayList<>();
for (final CerberusCredentialsProvider credentialsProvider : credentialsProviderList) {

if (! credentialsProvider.shouldRun()) {
continue;
}

try {
final CerberusCredentials credentials = credentialsProvider.getCredentials();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.nike.cerberus.client.CerberusClientException;
import com.nike.cerberus.client.UrlResolver;
import com.nike.cerberus.client.auth.CerberusCredentialsProvider;
import com.nike.cerberus.client.util.EnvironmentUtils;
import okhttp3.OkHttpClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
Expand Down Expand Up @@ -99,6 +100,10 @@ public EcsTaskRoleCerberusCredentialsProvider(UrlResolver urlResolver, String xC
super(urlResolver, xCerberusClientOverride);
}

public boolean shouldRun() {
return EnvironmentUtils.isRunningInEcs();
}

/**
* Looks up the IAM roles assigned to the task via the ECS task metadata
* service. An attempt is made to authenticate and decrypt the Cerberus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.nike.cerberus.client.CerberusClientException;
import com.nike.cerberus.client.UrlResolver;
import com.nike.cerberus.client.auth.CerberusCredentialsProvider;
import com.nike.cerberus.client.util.EnvironmentUtils;
import okhttp3.OkHttpClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
Expand Down Expand Up @@ -88,6 +89,10 @@ public InstanceRoleCerberusCredentialsProvider(UrlResolver urlResolver, String x
super(urlResolver, xCerberusClientOverride);
}

public boolean shouldRun() {
return EnvironmentUtils.isRunningInEc2();
}

/**
* Looks up the IAM roles assigned to the instance via the EC2 metadata
* service. For each role assigned, an attempt is made to authenticate and
Expand Down
80 changes: 80 additions & 0 deletions src/main/java/com/nike/cerberus/client/util/EnvironmentUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.nike.cerberus.client.util;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

/**
* Simple Util for determining environment metadata
*/
public class EnvironmentUtils {

private static final Map<String, Boolean> canGetSuccessfullyResults = new HashMap<>();

private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentUtils.class);

/**
* This endpoint is available on EC2 instances
*/
private static final String INSTANCE_IDENTITY_DOCUMENT = "http://169.254.169.254/latest/dynamic/instance-identity/document";

/**
* This endpoint is available on ECS Containers
*/
private static final String ECS_METADATA_ENDPOINT = "http://localhost:51678/v1/metadata";

private EnvironmentUtils() {
}

/**
* True if the current system is running in a pure EC2 environment, and not ECS.
*/
public static boolean isRunningInEc2() {
return hasInstanceIdentity() && ! isRunningInEcs();
}

/**
* True if the http://169.254.169.254/latest/dynamic/instance-identity/document endpoint
* is available and returns a 2xx status code. True means we are currently running on
* an Ec2 instance. This check should work both on Linux and Windows.
*/
private static boolean hasInstanceIdentity() {
return canGetSuccessfully(INSTANCE_IDENTITY_DOCUMENT);
}

/**
*
* @return true if this is a container in ECS
*/
public static boolean isRunningInEcs() {
return canGetSuccessfully(ECS_METADATA_ENDPOINT);
}

static boolean canGetSuccessfully(String url) {
return canGetSuccessfullyResults.computeIfAbsent(url, theUrl -> {
OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(500, MILLISECONDS)
.readTimeout(500, MILLISECONDS)
.writeTimeout(500, MILLISECONDS)
.build();

Request request = new Request.Builder().get().url(theUrl).build();

try (Response response = httpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
return true;
}
} catch (Exception e) {
LOGGER.debug("Error when trying to GET {}", theUrl, e);
}
return false;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -47,6 +48,8 @@ public class CerberusCredentialsProviderChainTest {
public void setup() {
credentialsProviderOne = mock(CerberusCredentialsProvider.class);
credentialsProviderTwo = mock(CerberusCredentialsProvider.class);
when(credentialsProviderOne.shouldRun()).thenReturn(true);
when(credentialsProviderTwo.shouldRun()).thenReturn(true);
credentialsProviderChain = new CerberusCredentialsProviderChain(credentialsProviderOne, credentialsProviderTwo);
}

Expand Down Expand Up @@ -124,7 +127,7 @@ public void isReuseLastProvider_returns_if_reuse_last_provider_is_enabled() {
}

@Test
public void list_contstructor_set_provider_list() {
public void list_constructor_set_provider_list() {
List<CerberusCredentialsProvider> list = new LinkedList<>();
list.add(credentialsProviderOne);
list.add(credentialsProviderTwo);
Expand Down Expand Up @@ -168,4 +171,16 @@ public String getToken() {
return TOKEN;
}
}
}

@Test
public void test_that_if_a_provider_returns_false_for_should_run_it_is_not_ran() {
when(credentialsProviderOne.shouldRun()).thenReturn(false);
when(credentialsProviderTwo.getCredentials()).thenReturn(new TestCerberusCredentials());

CerberusCredentials credentials = credentialsProviderChain.getCredentials();

assertThat(credentials).isNotNull();

verify(credentialsProviderOne, never()).getCredentials();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.nike.cerberus.client.util;

import org.junit.Test;

import java.util.UUID;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class EnvironmentUtilsTest {

@Test
public void test_that_canGetSuccessfully_can_get_google_index() {
assertTrue(EnvironmentUtils.canGetSuccessfully("http://www.google.com"));
assertTrue(EnvironmentUtils.canGetSuccessfully("http://www.google.com"));
}

@Test
public void test_that_canGetSuccessfully_can_not_get_random_http_address() {
assertFalse(EnvironmentUtils.canGetSuccessfully("http://" + UUID.randomUUID().toString() + ".com/" + UUID.randomUUID().toString()));
}

}

0 comments on commit a4aedbc

Please sign in to comment.