String getAuthToken(String hostname, int port, String rdsUser, String rdsIamRole) { InstanceProfileCredentialsProvider awsCredProvider = new InstanceProfileCredentialsProvider(true); if (LOG.isDebugEnabled()) { LOG.debug("getAuthToken: Access key id: {}", awsCredProvider.getCredentials().getAWSAccessKeyId()); } RdsIamAuthTokenGenerator generator = RdsIamAuthTokenGenerator.builder() .credentials(awsCredProvider) .region(EC2MetadataUtils.getEC2InstanceRegion()) .build(); if (LOG.isDebugEnabled()) { LOG.debug("Instance {} Port {} User {} Region: {} Role: {}", hostname, port, rdsUser, EC2MetadataUtils.getEC2InstanceRegion(), rdsIamRole); } return generator.getAuthToken(GetIamAuthTokenRequest.builder() .hostname(hostname).port(port).userName(rdsUser) .build()); }
/** * Substitutes the EC2 instance ID. If not running on EC2 we won't be able * to retrieve instance metadata (and it takes a long time to learn that, * waiting for a timeout) so this isn't handled as a "simple" substitution. */ private String substituteEC2InstanceId(String input) { String tag = "{ec2:instanceId}"; int index = input.indexOf(tag); if (index < 0) { tag = "{instanceId}"; index = input.indexOf(tag); if (index < 0) return input; } String instanceId = EC2MetadataUtils.getInstanceId(); if ((instanceId == null) || (instanceId.length() == 0)) return input; return substitute(tag, instanceId, input); }
/** * Calculates DynamoDB end-point. * * Algorithm details: * <ol> * <li> Use endpoint in job configuration "dynamodb.endpoint" value if available * <li> Use endpoint from region in job configuration "dynamodb.region" value if available * <li> Use endpoint from region in job configuration "dynamodb.regionid" value if available * <li> Use endpoint from EC2 Metadata of instance if available * <li> If all previous attempts at retrieving endpoint fail, default to us-east-1 endpoint * </ol> * * @param conf Job Configuration * @param region optional preferred region * @return end-point for DynamoDb service */ public static String getDynamoDBEndpoint(Configuration conf, String region) { String endpoint = getValueFromConf(conf, DynamoDBConstants.ENDPOINT); if (Strings.isNullOrEmpty(endpoint)) { if (Strings.isNullOrEmpty(region)) { region = getValueFromConf(conf, DynamoDBConstants.REGION); } if (Strings.isNullOrEmpty(region)) { region = getValueFromConf(conf, DynamoDBConstants.REGION_ID); } if (Strings.isNullOrEmpty(region)) { try { region = EC2MetadataUtils.getEC2InstanceRegion(); } catch (Exception e) { log.warn(String.format("Exception when attempting to get AWS region information. Will " + "ignore and default " + "to %s", DynamoDBConstants.DEFAULT_AWS_REGION), e); } } if (Strings.isNullOrEmpty(region)) { region = DynamoDBConstants.DEFAULT_AWS_REGION; } endpoint = RegionUtils.getRegion(region).getServiceEndpoint(ServiceAbbreviations.Dynamodb); } log.info("Using endpoint for DynamoDB: " + endpoint); return endpoint; }
/** * 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 * decrypt the Vault auth response with KMS. If successful, the token * retrieved is cached locally for future calls to * {@link BaseAwsCredentialsProvider#getCredentials()}. */ @Override protected void authenticate() { try { final String instanceProfileArn = getInstanceProfileArn(); final Set<String> iamRoleSet = EC2MetadataUtils.getIAMSecurityCredentials().keySet(); Region region = Regions.getCurrentRegion(); for (String iamRole : buildIamRoleArns(instanceProfileArn, iamRoleSet)) { try { getAndSetToken(iamRole, region); return; } catch (VaultClientException sce) { LOGGER.warn("Unable to acquire Vault token for IAM role: " + iamRole + ", instance profile was " + instanceProfileArn, sce); } } } catch (AmazonClientException ace) { LOGGER.warn("Unexpected error communicating with AWS services.", ace); } catch (JsonSyntaxException jse) { LOGGER.error("The decrypted auth response was not in the expected format!", jse); } throw new VaultClientException("Unable to acquire token with EC2 instance role."); }
@Override public Object getProperty(String name) { Map<String, String> userData = getUserData(); if (userData.containsKey(name)) { return userData.get(name); } if (!KNOWN_PROPERTY_NAMES.containsKey(getRootPropertyName(name))) { return null; } try { return EC2MetadataUtils.getData(EC2_METADATA_ROOT + "/" + name); } catch (AmazonClientException e) { //Suppress exception if we are not able to contact the service, //because that is quite often the case if we run in unit tests outside the environment. LOGGER.warn("Error getting instance meta-data with name '{}' error message is '{}'", name, e.getMessage()); return null; } }
/** * Substitutes the EC2 regsion. If not running on EC2 we won't be able * to retrieve instance metadata (and it takes a long time to learn that, * waiting for a timeout) so this isn't handled as a "simple" substitution. */ private String substituteEC2Region(String input) { String tag = "{ec2:region}"; int index = input.indexOf(tag); if (index < 0) return input; String region = EC2MetadataUtils.getEC2InstanceRegion(); if ((region == null) || (region.length() == 0)) return input; return substitute(tag, region, input); }
@Test @Ignore public void testInstanceId() throws Exception { Substitutions subs = new Substitutions(TEST_DATE, 0); assertEquals(EC2MetadataUtils.getInstanceId(), subs.perform("{instanceId}")); assertEquals(EC2MetadataUtils.getInstanceId(), subs.perform("{ec2:instanceId}")); }
@Test @Ignore public void testEC2Region() throws Exception { Substitutions subs = new Substitutions(TEST_DATE, 0); assertEquals(EC2MetadataUtils.getEC2InstanceRegion(), subs.perform("{ec2:region}")); }
public void populateRuntimeContext() { if (null != EC2MetadataUtils.getInstanceId()) { runtimeContext.put("instance_id", EC2MetadataUtils.getInstanceId()); } if (null != EC2MetadataUtils.getAvailabilityZone()) { runtimeContext.put("availability_zone", EC2MetadataUtils.getAvailabilityZone()); } }
private Optional<Region> getRegionFromMetadata() { try { Region resolvedRegion = null; if (EC2MetadataUtils.getInstanceInfo() != null) { if (EC2MetadataUtils.getInstanceInfo().getRegion() != null) { resolvedRegion = Region.fromName(EC2MetadataUtils.getInstanceInfo().getRegion()); } else { // fallback to provider chain if region is not exposed resolvedRegion = Region.fromName(new DefaultAwsRegionProviderChain().getRegion()); } } return Optional.ofNullable(resolvedRegion); } catch (SdkClientException e) { return Optional.empty(); } }
private String tryDetectRegion() { try { return EC2MetadataUtils.getEC2InstanceRegion(); } catch (AmazonClientException sce) { LogFactory.getLog(InstanceMetadataRegionProvider.class) .debug("Ignoring failure to retrieve the region: " + sce.getMessage()); return null; } }
@Override public URI getCredentialsEndpoint() throws URISyntaxException, IOException { String host = EC2MetadataUtils.getHostAddressForEC2MetadataService(); String securityCredentialsList = EC2CredentialsUtils.getInstance().readResource(new URI(host + EC2MetadataUtils.SECURITY_CREDENTIALS_RESOURCE)); String[] securityCredentials = securityCredentialsList.trim().split("\n"); if (securityCredentials.length == 0) { throw new SdkClientException("Unable to load credentials path"); } return new URI(host + EC2MetadataUtils.SECURITY_CREDENTIALS_RESOURCE + securityCredentials[0]); }
/** * Generates the SignalFx metrics reporter * @param serviceVersionDim The version number for this service/app * @param customReporterConfigurator Allows custom SignalFx dimensions or configuration to be sent to SignalFx * @param metricDetailsToReport The set of metric details that should be reported to SignalFx * @return The SignalFxReporterFactory */ public SignalFxReporterFactory generateSignalFxReporterFactory( String serviceVersionDim, String appNameDim, Function<Builder, Builder> customReporterConfigurator, Set<MetricDetails> metricDetailsToReport ) { Set<SignalFxReporter.MetricDetails> finalMetricDetailsToReport = (metricDetailsToReport == null) ? DEFAULT_METRIC_DETAILS_TO_SEND_TO_SIGNALFX : metricDetailsToReport; String host = EC2MetadataUtils.getLocalHostName(); String ec2Hostname = EC2_HOSTNAME_PREFIX + EC2MetadataUtils.getPrivateIpAddress(); Function<SignalFxReporter.Builder, SignalFxReporter.Builder> defaultReporterConfigurator = (builder) -> builder .addUniqueDimension("host", host) .addUniqueDimension("ec2_hostname", ec2Hostname) .addUniqueDimension("app", appNameDim) .addUniqueDimension("env", signalFxAppEnvDim) .addUniqueDimension("framework", "riposte") .addUniqueDimension("app_version", serviceVersionDim) .setDetailsToAdd(finalMetricDetailsToReport); if (customReporterConfigurator == null) customReporterConfigurator = Function.identity(); return new SignalFxReporterFactory( signalFxApiKey, defaultReporterConfigurator.andThen(customReporterConfigurator), // Report metrics at a 10 second interval Pair.of(10L, TimeUnit.SECONDS) ); }
@Before public void setUp() { PowerMockito.spy(RegionUtils.class); PowerMockito.mockStatic(EC2MetadataUtils.class); region = mock(Region.class); conf.clear(); }
@Test public void getsEndpointFromEc2InstanceRegion() { when(EC2MetadataUtils.getEC2InstanceRegion()).thenReturn("ec2-instance-region"); when(RegionUtils.getRegion("ec2-instance-region")).thenReturn(region); when(region.getServiceEndpoint(ServiceAbbreviations.Dynamodb)).thenReturn(TEST_ENDPOINT); assertEquals(TEST_ENDPOINT, DynamoDBUtil.getDynamoDBEndpoint(conf, null)); PowerMockito.verifyStatic(); EC2MetadataUtils.getEC2InstanceRegion(); verify(region, never()).getServiceEndpoint(TEST_REGION); }
@Test public void getsEndpointFromDefaultAwsRegion() { PowerMockito.mockStatic(RegionUtils.class); when(EC2MetadataUtils.getEC2InstanceRegion()).thenThrow(new AmazonClientException("Unable to " + "get region from EC2 instance data")); when(RegionUtils.getRegion(DynamoDBConstants.DEFAULT_AWS_REGION)).thenReturn(region); when(region.getServiceEndpoint(ServiceAbbreviations.Dynamodb)).thenReturn(TEST_ENDPOINT); assertEquals(TEST_ENDPOINT, DynamoDBUtil.getDynamoDBEndpoint(conf, null)); PowerMockito.verifyStatic(); RegionUtils.getRegion(DynamoDBConstants.DEFAULT_AWS_REGION); }
protected String getInstanceProfileArn() { EC2MetadataUtils.IAMInfo iamInfo = EC2MetadataUtils.getIAMInstanceProfileInfo(); if (iamInfo == null) { final String errorMessage = "No IAM Instance Profile assigned to running instance."; LOGGER.error(errorMessage); throw new VaultClientException(errorMessage); } return iamInfo.instanceProfileArn; }
@Before public void setup() throws Exception { kmsClient = mock(AWSKMSClient.class); urlResolver = mock(UrlResolver.class); provider = new InstanceRoleVaultCredentialsProvider(urlResolver); whenNew(AWSKMSClient.class).withAnyArguments().thenReturn(kmsClient); mockStatic(EC2MetadataUtils.class); mockGetCurrentRegion(); }
@Test(expected = VaultClientException.class) public void getCredentials_throws_client_exception_when_no_roles_are_set() { when(EC2MetadataUtils.getIAMSecurityCredentials()) .thenReturn(Collections.<String, EC2MetadataUtils.IAMSecurityCredential>emptyMap()); mockGetIamInstanceProfileInfo(GOOD_INSTANCE_PROFILE_ARN); provider.getCredentials(); }
public static String getInstanceId() { if (instanceId == null) { instanceId = EC2MetadataUtils.getInstanceId(); if (instanceId != null) { return instanceId; } else { instanceId = DEV_SYSTEM_ID; } } return instanceId; }
/** * Returns the EC2 private address if available * @return */ private synchronized Optional<String> getPrivateAddress() { if(privateAddress == null) { // this is expensive so we check only once privateAddress = Optional.ofNullable(EC2MetadataUtils.getPrivateIpAddress()); } return privateAddress; }
protected String machineId() { String machine = machineDimension; if (machine == null && isEC2MetadataAvailable()) { machine = EC2MetadataUtils.getInstanceId(); } if (Strings.isNullOrEmpty(machine)) { machine = "localhost"; } return machine; }
protected Region region() { String az = null; if (isEC2MetadataAvailable()) { az = EC2MetadataUtils.getAvailabilityZone(); } String regionName = awsRegion; if (!Strings.isNullOrEmpty(az)) { regionName = az.substring(0, az.length() - 1); // strip the AZ letter } return RegionUtils.getRegion(regionName); }
private ServerInstanceContext(){ amazonElasticLoadBalancing = new AmazonElasticLoadBalancingClient(); amazonEC2 = new AmazonEC2Client(); ec2MetadataClient = new Ec2MetadataClient() { @Override public String getAvailabilityZone() { return EC2MetadataUtils.getAvailabilityZone(); } @Override public String getInstanceId() { return EC2MetadataUtils.getInstanceId(); } @Override public String getUserData() { return EC2MetadataUtils.getUserData(); } @Override public String getPrivateIpAddress() { return EC2MetadataUtils.getPrivateIpAddress(); } @Override public String getPublicIpAddress() { for (EC2MetadataUtils.NetworkInterface net : EC2MetadataUtils.getNetworkInterfaces()) { List<String> ips = net.getPublicIPv4s(); if (ips != null && ips.size() > 0) { return ips.get(0); } } return null; } }; init(); }
private Map<String, String> getUserData() { if (this.cachedUserData == null) { Map<String, String> userDataMap = new LinkedHashMap<>(); String userData = null; try { userData = EC2MetadataUtils.getUserData(); } catch (AmazonClientException e) { //Suppress exception if we are not able to contact the service, //because that is quite often the case if we run in unit tests outside the environment. LOGGER.warn("Error getting instance user-data error message is '{}'", e.getMessage()); } if (StringUtils.hasText(userData)) { String[] userDataAttributes = userData.split(this.userDataAttributeSeparator); for (String userDataAttribute : userDataAttributes) { String[] userDataAttributesParts = StringUtils.split(userDataAttribute, this.userDataValueSeparator); if (userDataAttributesParts != null && userDataAttributesParts.length > 0) { String key = userDataAttributesParts[0]; String value = null; if (userDataAttributesParts.length > 1) { value = userDataAttributesParts[1]; } userDataMap.put(key, value); } } } this.cachedUserData = Collections.unmodifiableMap(userDataMap); } return this.cachedUserData; }
protected Region getCurrentRegion() { try { InstanceInfo instanceInfo = EC2MetadataUtils.getInstanceInfo(); return instanceInfo != null && instanceInfo.getRegion() != null ? RegionUtils.getRegion(instanceInfo.getRegion()) : null; } catch (AmazonClientException e) { return null; } }
private static void resetMetaDataCache() { try { Field metadataCacheField = EC2MetadataUtils.class.getDeclaredField("cache"); metadataCacheField.setAccessible(true); metadataCacheField.set(null, new HashMap<String, String>()); } catch (Exception e) { throw new IllegalStateException("Unable to clear metadata cache in '" + EC2MetadataUtils.class.getName() + "'", e); } }
public static boolean isRunningOnCloudEnvironment() { if (isCloudEnvironment == null) { try { isCloudEnvironment = EC2MetadataUtils.getData(EC2_METADATA_ROOT + "/instance-id", 1) != null; } catch (AmazonClientException e) { isCloudEnvironment = false; } } return isCloudEnvironment; }
private static void clearMetadataCache() { try { Field metadataCacheField = EC2MetadataUtils.class.getDeclaredField("cache"); metadataCacheField.setAccessible(true); metadataCacheField.set(null, new HashMap<String, String>()); } catch (Exception e) { throw new IllegalStateException("Unable to clear metadata cache in '" + EC2MetadataUtils.class.getName() + "'", e); } }
@Override public String get(String key) { if ("amazon-webservice-region-available".equals(key)) { return Boolean.toString(EC2MetadataUtils.getAvailabilityZone() != null); } return null; }
public static Optional<String> findInstanceId() { try { return Optional.fromNullable(EC2MetadataUtils.getInstanceId()); } catch (Exception e) { return Optional.absent(); } }
public static Optional<String> findAvailabilityZone() { try { return Optional.fromNullable(EC2MetadataUtils.getAvailabilityZone()); } catch (Exception e) { return Optional.absent(); } }
private static Optional<String> findSubnet() { try { List<EC2MetadataUtils.NetworkInterface> networkInterfaces = EC2MetadataUtils.getNetworkInterfaces(); if (EC2MetadataUtils.getNetworkInterfaces().isEmpty()) { return Optional.absent(); } else { return Optional.fromNullable(networkInterfaces.get(0).getSubnetId()); } } catch (Exception e) { return Optional.absent(); } }
private static Optional<String> findVpc() { try { List<EC2MetadataUtils.NetworkInterface> networkInterfaces = EC2MetadataUtils.getNetworkInterfaces(); if (EC2MetadataUtils.getNetworkInterfaces().isEmpty()) { return Optional.absent(); } else { return Optional.fromNullable(networkInterfaces.get(0).getVpcId()); } } catch (Exception e) { return Optional.absent(); } }
@Test(expected = VaultClientException.class) public void getCredentials_throws_client_exception_when_not_running_on_ec2_instance() { when(EC2MetadataUtils.getIAMSecurityCredentials()).thenThrow(new AmazonClientException("BAD")); provider.getCredentials(); }
@Test(expected = VaultClientException.class) public void getCredentials_thorws_client_exception_when_no_instance_profile_assigned() { when(EC2MetadataUtils.getIAMInstanceProfileInfo()).thenReturn(null); provider.getCredentials(); }
private void mockGetCurrentRegion() { when(EC2MetadataUtils.getEC2InstanceRegion()).thenReturn(Regions.US_WEST_2.getName()); }
private void mockGetIamSecurityCredentials(final String role) { Map<String, EC2MetadataUtils.IAMSecurityCredential> map = new HashMap<>(); map.put(role, null); when(EC2MetadataUtils.getIAMSecurityCredentials()).thenReturn(map); }