diff --git a/pom.xml b/pom.xml
index 1ff721eb..b1f2c302 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,6 +112,17 @@
+
+ com.amazonaws
+ aws-java-sdk-sts
+ ${aws-java-sdk.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
com.amazonaws
amazon-kinesis-client
diff --git a/src/main/java/org/graylog/aws/auth/AWSAuthProvider.java b/src/main/java/org/graylog/aws/auth/AWSAuthProvider.java
index af51b73f..0e608fb5 100644
--- a/src/main/java/org/graylog/aws/auth/AWSAuthProvider.java
+++ b/src/main/java/org/graylog/aws/auth/AWSAuthProvider.java
@@ -6,6 +6,10 @@
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
+import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
+import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
+import com.amazonaws.services.securitytoken.model.GetCallerIdentityRequest;
import org.graylog.aws.config.AWSPluginConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,20 +24,53 @@ public class AWSAuthProvider implements AWSCredentialsProvider {
private AWSCredentialsProvider credentials;
public AWSAuthProvider(AWSPluginConfiguration config) {
- this(config, null, null);
+ this(config, null, null, null,null);
}
- public AWSAuthProvider(AWSPluginConfiguration config, @Nullable String accessKey, @Nullable String secretKey) {
+ public AWSAuthProvider(AWSPluginConfiguration config,
+ @Nullable String accessKey,
+ @Nullable String secretKey,
+ @Nullable String region,
+ @Nullable String assumeRoleArn) {
+ this.credentials = this.resolveAuthentication(config, accessKey, secretKey, region, assumeRoleArn);
+ }
+
+ private AWSCredentialsProvider resolveAuthentication(AWSPluginConfiguration config,
+ @Nullable String accessKey,
+ @Nullable String secretKey,
+ @Nullable String region,
+ @Nullable String assumeRoleArn) {
+ AWSCredentialsProvider awsCredentials;
if (!isNullOrEmpty(accessKey) && !isNullOrEmpty(secretKey)) {
- this.credentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey));
+ awsCredentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey));
LOG.debug("Using input specific config");
} else if (!isNullOrEmpty(config.accessKey()) && !isNullOrEmpty(config.secretKey())) {
- this.credentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials(config.accessKey(), config.secretKey()));
+ awsCredentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials(config.accessKey(), config.secretKey()));
LOG.debug("Using AWS Plugin config");
} else {
- this.credentials = new DefaultAWSCredentialsProviderChain();
+ awsCredentials = new DefaultAWSCredentialsProviderChain();
LOG.debug("Using Default Provider Chain");
}
+ if (!isNullOrEmpty(assumeRoleArn) && !isNullOrEmpty(region)) {
+ LOG.debug("Creating cross account assume role credentials");
+ return this.getSTSCredentialsProvider(awsCredentials, region, assumeRoleArn);
+ } else {
+ return awsCredentials;
+ }
+ }
+
+ private AWSCredentialsProvider getSTSCredentialsProvider(AWSCredentialsProvider awsCredentials, String region, String assumeRoleArn) {
+ AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
+ .withRegion(region)
+ .withCredentials(awsCredentials)
+ .build();
+ String roleSessionName = String.format("API_KEY_%s@ACCOUNT_%s",
+ awsCredentials.getCredentials().getAWSAccessKeyId(),
+ stsClient.getCallerIdentity(new GetCallerIdentityRequest()).getAccount());
+ LOG.debug("Cross account role session name: " + roleSessionName);
+ return new STSAssumeRoleSessionCredentialsProvider.Builder(assumeRoleArn, roleSessionName)
+ .withStsClient(stsClient)
+ .build();
}
@Override
diff --git a/src/main/java/org/graylog/aws/inputs/cloudtrail/CloudTrailTransport.java b/src/main/java/org/graylog/aws/inputs/cloudtrail/CloudTrailTransport.java
index e52a0cbf..0d520231 100644
--- a/src/main/java/org/graylog/aws/inputs/cloudtrail/CloudTrailTransport.java
+++ b/src/main/java/org/graylog/aws/inputs/cloudtrail/CloudTrailTransport.java
@@ -48,6 +48,7 @@ public class CloudTrailTransport extends ThrottleableTransport {
private static final String CK_SQS_NAME = "aws_sqs_queue_name";
private static final String CK_ACCESS_KEY = "aws_access_key";
private static final String CK_SECRET_KEY = "aws_secret_key";
+ private static final String CK_ASSUME_ROLE_ARN = "aws_assume_role_arn";
private static final Regions DEFAULT_REGION = Regions.US_EAST_1;
@@ -118,7 +119,9 @@ public void doLaunch(MessageInput input) throws MisfireException {
final AWSAuthProvider authProvider = new AWSAuthProvider(
config,
input.getConfiguration().getString(CK_ACCESS_KEY),
- input.getConfiguration().getString(CK_SECRET_KEY)
+ input.getConfiguration().getString(CK_SECRET_KEY),
+ input.getConfiguration().getString(CK_AWS_SQS_REGION),
+ input.getConfiguration().getString(CK_ASSUME_ROLE_ARN)
);
subscriber = new CloudTrailSubscriber(
@@ -208,6 +211,14 @@ public ConfigurationRequest getRequestedConfiguration() {
TextField.Attribute.IS_PASSWORD
));
+ r.addField(new TextField(
+ CK_ASSUME_ROLE_ARN,
+ "AWS assume role ARN",
+ "",
+ "The role ARN with required permissions (cross account access)",
+ ConfigurationField.Optional.OPTIONAL
+ ));
+
return r;
}
}
diff --git a/src/main/java/org/graylog/aws/inputs/transports/KinesisTransport.java b/src/main/java/org/graylog/aws/inputs/transports/KinesisTransport.java
index 4667bdfc..5a06ae34 100644
--- a/src/main/java/org/graylog/aws/inputs/transports/KinesisTransport.java
+++ b/src/main/java/org/graylog/aws/inputs/transports/KinesisTransport.java
@@ -42,6 +42,7 @@ public class KinesisTransport implements Transport {
private static final String CK_AWS_REGION = "aws_region";
private static final String CK_ACCESS_KEY = "aws_access_key";
private static final String CK_SECRET_KEY = "aws_secret_key";
+ private static final String CK_ASSUME_ROLE_ARN = "aws_assume_role_arn";
private static final String CK_KINESIS_STREAM_NAME = "kinesis_stream_name";
private final Configuration configuration;
@@ -75,7 +76,12 @@ public void launch(MessageInput input) throws MisfireException {
final AWSPluginConfiguration awsConfig = clusterConfigService.getOrDefault(AWSPluginConfiguration.class,
AWSPluginConfiguration.createDefault());
- AWSAuthProvider authProvider = new AWSAuthProvider(awsConfig, configuration.getString(CK_ACCESS_KEY), configuration.getString(CK_SECRET_KEY));
+ AWSAuthProvider authProvider = new AWSAuthProvider(
+ awsConfig, configuration.getString(CK_ACCESS_KEY),
+ configuration.getString(CK_SECRET_KEY),
+ configuration.getString(CK_AWS_REGION),
+ configuration.getString(CK_ASSUME_ROLE_ARN)
+ );
this.reader = new KinesisConsumer(
configuration.getString(CK_KINESIS_STREAM_NAME),
@@ -159,6 +165,14 @@ public ConfigurationRequest getRequestedConfiguration() {
TextField.Attribute.IS_PASSWORD
));
+ r.addField(new TextField(
+ CK_ASSUME_ROLE_ARN,
+ "AWS assume role ARN",
+ "",
+ "Role ARN with required permissions (cross account access)",
+ ConfigurationField.Optional.OPTIONAL
+ ));
+
r.addField(new TextField(
CK_KINESIS_STREAM_NAME,
"Kinesis Stream name",