diff --git a/app/elastic/AwsSigner.scala b/app/elastic/AwsSigner.scala new file mode 100644 index 00000000..2f8cc8f8 --- /dev/null +++ b/app/elastic/AwsSigner.scala @@ -0,0 +1,84 @@ +package elastic + +import java.net.URI + +import com.amazonaws.DefaultRequest +import com.amazonaws.auth.AWS4Signer +import com.amazonaws.auth.AWSCredentials +import com.amazonaws.auth.BasicAWSCredentials +import com.amazonaws.http.HttpMethodName +import scala.collection.JavaConverters._ +import java.io.StringReader +import java.io.ByteArrayInputStream +import java.io.InputStream + +object AwsSigner { + + def sing(method: String, url: String, headers: Seq[(String, String)], body: Option[String], secret: String, key: String) : Seq[(String, String)] = { + + val uri = URI.create(url) + + if(uri.getHost.endsWith(".es.amazonaws.com")) { + + val credentials: AWSCredentials = new BasicAWSCredentials(secret, key) + + + val host = if(uri.getPort() == -1) { + s"""${uri.getScheme}://${uri.getHost()}""" + } else { + s"""${uri.getScheme}://${uri.getHost()}:${uri.getPort()}""" + } + + val pattern = """^https:\/\/.+\.(.+)\.es\.amazonaws\.com$""".r + + val region = host match { + case pattern(region) => region + } + + val endpoint = uri.getPath(); + val queryStringOpt = Option(uri.getQuery()); + + val params = queryStringOpt + .map( queryString => { + queryString + .split("&") + .map( text => { + val keyVal = text.split("=", 2) + keyVal(0) -> Seq(keyVal(1)).asJava + }) + .toMap + }) + .getOrElse(Map.empty) + .asJava + + val content: InputStream = new ByteArrayInputStream(body.getOrElse("").getBytes) + + val request = new DefaultRequest[Unit]("es") + request.setHttpMethod(HttpMethodName.fromValue(method)) + request.setEndpoint(URI.create(host)) + request.setResourcePath(endpoint) + request.setHeaders(headers.toMap[String, String].asJava) + request.setParameters(params) + request.setContent(content) + + val signer = new AWS4Signer() + signer.setRegionName(region); + signer.setServiceName("es"); + signer.sign(request, credentials); + + val hdrs = request.getHeaders(); + + Seq( + "Host" -> hdrs.get("Host"), + "Authorization" -> hdrs.get("Authorization"), + "X-Amz-Date" -> hdrs.get("X-Amz-Date") + ) + + } else { + Seq.empty + } + + } + + +} \ No newline at end of file diff --git a/app/elastic/HTTPElasticClient.scala b/app/elastic/HTTPElasticClient.scala index 80a05c21..fa6e422c 100644 --- a/app/elastic/HTTPElasticClient.scala +++ b/app/elastic/HTTPElasticClient.scala @@ -324,7 +324,8 @@ class HTTPElasticClient @Inject()(client: WSClient) extends ElasticClient { val request = authentication.foldLeft(client.url(url).withMethod(method).withHttpHeaders(headers: _*)) { case (request, auth) => - request.withAuth(auth.username, auth.password, WSAuthScheme.BASIC) + val awsHeaders = AwsSigner.sing(method, url, headers, body, auth.username, auth.password) + request.addHttpHeaders(awsHeaders: _*) } body.fold(request)(request.withBody((_))).execute.map { response => diff --git a/build.sbt b/build.sbt index 59edd1c3..7b46a163 100644 --- a/build.sbt +++ b/build.sbt @@ -12,6 +12,7 @@ libraryDependencies ++= Seq( "com.typesafe.play" %% "play-slick" % "3.0.3", "com.typesafe.play" %% "play-slick-evolutions" % "3.0.3", "org.xerial" % "sqlite-jdbc" % "3.23.1", + "com.amazonaws" % "aws-java-sdk-core" % "1.11.359", "org.specs2" %% "specs2-junit" % "3.9.2" % "test", "org.specs2" %% "specs2-core" % "3.9.2" % "test", "org.specs2" %% "specs2-mock" % "3.9.2" % "test"