This repository has been archived by the owner on Jan 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Instance Role Profile credential provider (#6)
Created an Instance Role Profile credential provider that will use the instance profile arn to determine what to attempt to authenticate with cerberus with
- Loading branch information
Showing
5 changed files
with
141 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
src/main/java/com/nike/cerberus/client/auth/aws/InstanceProfileVaultCredentialsProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package com.nike.cerberus.client.auth.aws; | ||
|
||
import com.amazonaws.regions.Region; | ||
import com.amazonaws.regions.Regions; | ||
import com.amazonaws.util.EC2MetadataUtils; | ||
import com.nike.vault.client.UrlResolver; | ||
import com.nike.vault.client.VaultClientException; | ||
|
||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* This Credentials provider will look up the assigned InstanceProfileArn for this machine and attempt | ||
* To automatically retrieve a Vault token from CMS's iam-auth endpoint that takes region, acct id, role name. | ||
*/ | ||
public class InstanceProfileVaultCredentialsProvider extends BaseAwsCredentialsProvider { | ||
|
||
/** | ||
* Constructor to setup credentials provider using the specified | ||
* implementation of {@link UrlResolver} | ||
* | ||
* @param urlResolver Resolver for resolving the Cerberus URL | ||
*/ | ||
public InstanceProfileVaultCredentialsProvider(UrlResolver urlResolver) { | ||
super(urlResolver); | ||
} | ||
|
||
@Override | ||
protected void authenticate() { | ||
EC2MetadataUtils.IAMInfo iamInfo = getIamInfo(); | ||
IamAuthInfo iamAuthInfo = getIamAuthInfo(iamInfo.instanceProfileArn); | ||
|
||
try { | ||
getAndSetToken(iamAuthInfo.accountId, iamAuthInfo.roleName, iamAuthInfo.region); | ||
} catch (Exception e) { | ||
throw new VaultClientException(String.format("Failed to authenticate with Cerberus's iam auth endpoint " + | ||
"using the following auth info, acct id: %s, roleName: %s, region: %s", | ||
iamAuthInfo.accountId, iamAuthInfo.roleName, iamAuthInfo.region), e); | ||
} | ||
} | ||
|
||
protected IamAuthInfo getIamAuthInfo(String instanceProfileArn) { | ||
if (instanceProfileArn == null) { | ||
throw new VaultClientException("instanceProfileArn provided was null rather than valid arn"); | ||
} | ||
|
||
IamAuthInfo info = new IamAuthInfo(); | ||
String pattern = "arn:aws:iam::(.*?):instance-profile/(.*)"; | ||
Matcher matcher = Pattern.compile(pattern).matcher(instanceProfileArn); | ||
boolean found = matcher.find(); | ||
if (! found) { | ||
throw new VaultClientException(String.format( | ||
"Failed to find account id and role / instance profile name from ARN: %s using pattern %s", | ||
instanceProfileArn, pattern)); | ||
} | ||
|
||
info.accountId = matcher.group(1); | ||
info.roleName = matcher.group(2); | ||
|
||
return info; | ||
} | ||
|
||
protected static class IamAuthInfo { | ||
String accountId; | ||
String roleName; | ||
Region region = Regions.getCurrentRegion(); | ||
} | ||
|
||
protected EC2MetadataUtils.IAMInfo getIamInfo() { | ||
return EC2MetadataUtils.getIAMInstanceProfileInfo(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
...t/java/com/nike/cerberus/client/auth/aws/InstanceProfileVaultCredentialsProviderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package com.nike.cerberus.client.auth.aws; | ||
|
||
import com.amazonaws.regions.Region; | ||
import com.amazonaws.util.EC2MetadataUtils; | ||
import com.nike.vault.client.StaticVaultUrlResolver; | ||
import com.nike.vault.client.VaultClientException; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.mockito.Matchers.any; | ||
import static org.mockito.Matchers.anyString; | ||
import static org.mockito.Mockito.doReturn; | ||
import static org.mockito.Mockito.doThrow; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.spy; | ||
import static org.mockito.Mockito.when; | ||
|
||
public class InstanceProfileVaultCredentialsProviderTest { | ||
|
||
InstanceProfileVaultCredentialsProvider provider; | ||
|
||
@Before | ||
public void before() { | ||
provider = new InstanceProfileVaultCredentialsProvider(new StaticVaultUrlResolver("foo")); | ||
} | ||
|
||
@Test | ||
public void test_that_valid_arn_gets_parsed() { | ||
InstanceProfileVaultCredentialsProvider.IamAuthInfo info = provider.getIamAuthInfo("arn:aws:iam::1234:inst" + | ||
"ance-profile/base/prod-base-sdfgsdfg-be5c-47ff-b82f-sdfgsdfgsfdg-CmsInstanceProfile-sdfgsdfgsdfg"); | ||
|
||
assertEquals("1234", info.accountId); | ||
assertEquals("base/prod-base-sdfgsdfg-be5c-47ff-b82f-sdfgsdfgsfdg-CmsInstanceProfile-sdfgsdfgsdfg", | ||
info.roleName); | ||
} | ||
|
||
@Test(expected = VaultClientException.class) | ||
public void test_that_invalid_arn_fails() { | ||
provider.getIamAuthInfo(""); | ||
} | ||
|
||
@Test(expected = VaultClientException.class) | ||
public void test_that_null_arn_fails() { | ||
provider.getIamAuthInfo(null); | ||
} | ||
|
||
@Test(expected = VaultClientException.class) | ||
public void test_that_authenticate_catches_exceptions_and_throws_vault_exception() { | ||
InstanceProfileVaultCredentialsProvider providerSpy = spy(provider); | ||
|
||
doThrow(new RuntimeException("Foo")).when(providerSpy).getAndSetToken(anyString(), anyString(), any(Region.class)); | ||
doReturn(new InstanceProfileVaultCredentialsProvider.IamAuthInfo()).when(providerSpy).getIamAuthInfo(anyString()); | ||
EC2MetadataUtils.IAMInfo iamInfo = new EC2MetadataUtils.IAMInfo(); | ||
iamInfo.instanceProfileArn = "foo"; | ||
doReturn(iamInfo).when(providerSpy).getIamInfo(); | ||
|
||
providerSpy.authenticate(); | ||
} | ||
} |