hq/app/aws/AWS.scala (74 lines of code) (raw):
package aws
import config.Config
import model.AwsAccount
import play.api.Configuration
import software.amazon.awssdk.auth.credentials.{AwsCredentialsProviderChain, ProfileCredentialsProvider}
import software.amazon.awssdk.awscore.client.builder.{AwsAsyncClientBuilder, AwsClientBuilder}
import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.cloudformation.CloudFormationAsyncClient
import software.amazon.awssdk.services.ec2.Ec2AsyncClient
import software.amazon.awssdk.services.efs.EfsAsyncClient
import software.amazon.awssdk.services.iam.IamAsyncClient
import software.amazon.awssdk.services.s3.S3Client
import software.amazon.awssdk.services.sts.StsClient
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest
import software.amazon.awssdk.services.support.SupportAsyncClient
import utils.attempt.{Attempt, Failure}
import java.util.concurrent.Executors.newCachedThreadPool
object AWS {
def lookupAccount(accountId: String, accounts: List[AwsAccount]): Attempt[AwsAccount] = {
Attempt.fromOption(
accounts.find(_.id == accountId),
Failure.awsAccountNotFound(accountId).attempt
)
}
private def credentialsProvider(account: AwsAccount): AwsCredentialsProviderChain = {
AwsCredentialsProviderChain.of(
StsAssumeRoleCredentialsProvider.builder()
.stsClient(
StsClient.builder
.region(Config.region)
.build()
)
.refreshRequest(
AssumeRoleRequest.builder
.roleArn(account.roleArn)
.roleSessionName("security-hq")
.build()
)
.build(),
ProfileCredentialsProvider.create(account.id)
)
}
private[aws] def clients[A, B <: AwsClientBuilder[B, A]](
builder: AwsClientBuilder[B, A],
configuration: Configuration,
regionList: Region*
): AwsClients[A] = {
for {
account <- Config.getAwsAccounts(configuration)
region <- regionList
client = builder
.credentialsProvider(credentialsProvider(account))
.region(region)
.build()
} yield AwsClient(client, account, region)
}
private def withCustomThreadPool[A, B <: AwsAsyncClientBuilder[B, A]] = (asyncClientBuilder: AwsAsyncClientBuilder[B, A]) =>
asyncClientBuilder.asyncConfiguration(c => c.advancedOption(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR, newCachedThreadPool())
)
def ec2Clients(configuration: Configuration, regions: List[Region]): AwsClients[Ec2AsyncClient] =
clients(withCustomThreadPool(Ec2AsyncClient.builder), configuration, regions:_*)
def cfnClients(configuration: Configuration, regions: List[Region]): AwsClients[CloudFormationAsyncClient] =
clients(withCustomThreadPool(CloudFormationAsyncClient.builder), configuration, regions:_*)
// Only needs Regions.US_EAST_1
def taClients(configuration: Configuration, region: Region = Region.of("us-east-1")): AwsClients[SupportAsyncClient] =
clients(withCustomThreadPool(SupportAsyncClient.builder), configuration, region)
def s3Clients(configuration: Configuration, regions: List[Region]): AwsClients[S3Client] =
clients(S3Client.builder, configuration, regions:_*)
def iamClients(configuration: Configuration, regions: List[Region]): AwsClients[IamAsyncClient] =
clients(withCustomThreadPool(IamAsyncClient.builder), configuration, regions:_*)
def efsClients(configuration: Configuration, regions: List[Region]): AwsClients[EfsAsyncClient] =
clients(withCustomThreadPool(EfsAsyncClient.builder), configuration, regions:_*)
}