Skip to content

Commit

Permalink
Add logic to use a named AWS credential profile name in config as wel…
Browse files Browse the repository at this point in the history
…l as assuming a role
  • Loading branch information
c0state committed Aug 8, 2017
1 parent 6d7fe4f commit d2cb0ae
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 18 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ libraryDependencies += "org.yaml" % "snakeyaml" % "1.13"

libraryDependencies += "org.jruby" % "jruby" % "1.7.11"

libraryDependencies += "com.amazonaws" % "aws-java-sdk" % "1.11.32"
libraryDependencies += "com.amazonaws" % "aws-java-sdk" % "1.11.172"

libraryDependencies += "log4j" % "log4j" % "1.2.17"

Expand Down
33 changes: 23 additions & 10 deletions src/main/scala/s3/website/model/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import scala.util.{Failure, Try}
import scala.collection.JavaConversions._
import s3.website.Ruby.rubyRuntime
import s3.website._
import com.amazonaws.auth.{AWSCredentialsProvider, BasicAWSCredentials, BasicSessionCredentials, AWSStaticCredentialsProvider, DefaultAWSCredentialsProviderChain}
import com.amazonaws.auth.{AWSCredentialsProvider, BasicAWSCredentials, BasicSessionCredentials, AWSStaticCredentialsProvider, DefaultAWSCredentialsProviderChain, STSAssumeRoleSessionCredentialsProvider}
import com.amazonaws.auth.profile.ProfileCredentialsProvider

case class Config(
s3_id: Option[String], // If undefined, use IAM Roles (http://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/java-dg-roles.html)
s3_secret: Option[String], // If undefined, use IAM Roles (http://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/java-dg-roles.html)
session_token: Option[String], // If defined, the AWS Security Token Service session token (http://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html)
profile: Option[String], // If defined, the AWS profile to use for credentials
profile_assume_role_arn: Option[String], // If defined, the ARN of the role to assume
s3_bucket: String,
s3_endpoint: S3Endpoint,
site: Option[String],
Expand All @@ -37,20 +40,30 @@ case class Config(
object Config {

def awsCredentials(config: Config): AWSCredentialsProvider = {
val credentialsFromConfigFile: Option[AWSStaticCredentialsProvider] =
if (config.s3_id.isEmpty) {
None
} else if (config.session_token.isEmpty) {
val credentialsFromConfigFile: Option[AWSCredentialsProvider] =
if (config.s3_id.nonEmpty && config.s3_secret.nonEmpty && config.session_token.nonEmpty) {
for {
s3_id <- config.s3_id
s3_secret <- config.s3_secret
} yield new AWSStaticCredentialsProvider(new BasicAWSCredentials(s3_id, s3_secret))
} else {
session_token <- config.session_token
} yield new AWSStaticCredentialsProvider(new BasicSessionCredentials(s3_id, s3_secret, session_token))
} else if (config.s3_id.nonEmpty && config.s3_secret.nonEmpty) {
for {
s3_id <- config.s3_id
s3_secret <- config.s3_secret
session_token <- config.session_token
} yield new AWSStaticCredentialsProvider(new BasicSessionCredentials(s3_id, s3_secret, session_token))
} yield new AWSStaticCredentialsProvider(new BasicAWSCredentials(s3_id, s3_secret))
} else if (config.profile_assume_role_arn.nonEmpty) {
for {
profile <- config.profile
profile_assume_role_arn <- config.profile_assume_role_arn
} yield new STSAssumeRoleSessionCredentialsProvider.Builder(profile_assume_role_arn, "s3_website_assume_role_session")
.withLongLivedCredentialsProvider(new ProfileCredentialsProvider(profile)).build()
} else if (config.profile.nonEmpty) {
for {
profile <- config.profile
} yield new ProfileCredentialsProvider(profile)
} else {
None
}
credentialsFromConfigFile getOrElse new DefaultAWSCredentialsProviderChain
}
Expand Down Expand Up @@ -235,4 +248,4 @@ object Config {
case class S3_website_yml(file: File) {
override def toString = file.getPath
}
}
}
6 changes: 5 additions & 1 deletion src/main/scala/s3/website/model/Site.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ object Site {
s3_id <- loadOptionalString("s3_id").right
s3_secret <- loadOptionalString("s3_secret").right
session_token <- loadOptionalString("session_token").right
profile <- loadOptionalString("profile").right
profile_assume_role_arn <- loadOptionalString("profile_assume_role_arn").right
s3_bucket <- loadRequiredString("s3_bucket").right
s3_endpoint <- loadEndpoint.right
site <- loadOptionalString("site").right
Expand Down Expand Up @@ -67,6 +69,8 @@ object Site {
s3_id,
s3_secret,
session_token,
profile,
profile_assume_role_arn,
s3_bucket,
s3_endpoint getOrElse S3Endpoint.defaultEndpoint,
site,
Expand Down Expand Up @@ -152,4 +156,4 @@ object Site {
Right(None)
}
}
}
}
74 changes: 68 additions & 6 deletions src/test/scala/s3/website/ConfigSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,41 @@ import s3.website.model.{Config, S3Endpoint}
class ConfigSpec extends Specification {

"Config#awsCredentials" should {
s"return ${classOf[BasicSessionCredentials]} when s3_id, s3_secret and session_token are defined in the config" in {
Config.awsCredentials(Config(
s3_id = Some("test"),
s3_secret = Some("secret"),
session_token = Some("Token"),
profile = None,
profile_assume_role_arn = None,
s3_bucket = "foo",
s3_endpoint = S3Endpoint.defaultEndpoint,
site = None,
max_age = None,
cache_control = None,
gzip = None,
gzip_zopfli = None,
s3_key_prefix = None,
ignore_on_server = None,
exclude_from_upload = None,
s3_reduced_redundancy = None,
cloudfront_distribution_id = None,
cloudfront_invalidate_root = None,
content_type = None,
redirects = None,
concurrency_level = 1,
cloudfront_wildcard_invalidation = None,
treat_zero_length_objects_as_redirects = None
)).getCredentials must beAnInstanceOf[BasicSessionCredentials]
}

s"return ${classOf[BasicAWSCredentials]} when s3_id and s3_secret are defined in the config" in {
Config.awsCredentials(Config(
s3_id = Some("test"),
s3_secret = Some("secret"),
session_token = None,
profile = None,
profile_assume_role_arn = None,
s3_bucket = "foo",
s3_endpoint = S3Endpoint.defaultEndpoint,
site = None,
Expand All @@ -32,11 +62,13 @@ class ConfigSpec extends Specification {
)).getCredentials must beAnInstanceOf[BasicAWSCredentials]
}

s"return ${classOf[BasicSessionCredentials]} when s3_id, s3_secret and session_token are defined in the config" in {
s"return ${classOf[STSAssumeRoleSessionCredentialsProvider]} when profile and profile_assume_role_arn are defined in the config" in {
Config.awsCredentials(Config(
s3_id = Some("test"),
s3_secret = Some("secret"),
session_token = Some("Token"),
s3_id = None,
s3_secret = None,
session_token = None,
profile = "profile_name",
profile_assume_role_arn = "arn:aws:iam::account-id:role/role-name",
s3_bucket = "foo",
s3_endpoint = S3Endpoint.defaultEndpoint,
site = None,
Expand All @@ -55,14 +87,44 @@ class ConfigSpec extends Specification {
concurrency_level = 1,
cloudfront_wildcard_invalidation = None,
treat_zero_length_objects_as_redirects = None
)).getCredentials must beAnInstanceOf[BasicSessionCredentials]
)) must beAnInstanceOf[ProfileCredentialsProvider]
}

s"return ${classOf[STSAssumeRoleSessionCredentialsProvider]} when profile is defined in the config" in {
Config.awsCredentials(Config(
s3_id = None,
s3_secret = None,
session_token = None,
profile = "profile_name",
profile_assume_role_arn = None,
s3_bucket = "foo",
s3_endpoint = S3Endpoint.defaultEndpoint,
site = None,
max_age = None,
cache_control = None,
gzip = None,
gzip_zopfli = None,
s3_key_prefix = None,
ignore_on_server = None,
exclude_from_upload = None,
s3_reduced_redundancy = None,
cloudfront_distribution_id = None,
cloudfront_invalidate_root = None,
content_type = None,
redirects = None,
concurrency_level = 1,
cloudfront_wildcard_invalidation = None,
treat_zero_length_objects_as_redirects = None
)) must beAnInstanceOf[ProfileCredentialsProvider]
}

s"return ${classOf[DefaultAWSCredentialsProviderChain]} when s3_id and s3_secret are not defined in the config" in {
s"return ${classOf[DefaultAWSCredentialsProviderChain]} when s3_id, s3_secret, profile and profile_assume_role_arn are not defined in the config" in {
Config.awsCredentials(Config(
s3_id = None,
s3_secret = None,
session_token = None,
profile = None,
profile_assume_role_arn = None,
s3_bucket = "foo",
s3_endpoint = S3Endpoint.defaultEndpoint,
site = None,
Expand Down

0 comments on commit d2cb0ae

Please sign in to comment.