Skip to content

Commit

Permalink
Merge pull request #47 from ing-bank/feature/service-npa-add
Browse files Browse the repository at this point in the history
add option to add npa with non personal token
  • Loading branch information
kr7ysztof committed May 29, 2020
2 parents 8b07e15 + 60a58af commit 2a98b9d
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
37 changes: 34 additions & 3 deletions src/main/scala/com/ing/wbaa/rokku/sts/api/AdminApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ import akka.http.scaladsl.server.{ AuthorizationFailedRejection, Route }
import com.ing.wbaa.rokku.sts.api.directive.STSDirectives.authorizeToken
import com.ing.wbaa.rokku.sts.config.StsSettings
import com.ing.wbaa.rokku.sts.data.aws.{ AwsAccessKey, AwsCredential, AwsSecretKey }
import com.ing.wbaa.rokku.sts.data.{ AuthenticationUserInfo, BearerToken, NPAAccount, NPAAccountList, UserGroup, UserName }
import com.ing.wbaa.rokku.sts.data.{ AuthenticationUserInfo, BearerToken, NPAAccount, NPAAccountList, RequestId, UserGroup, UserName }
import com.ing.wbaa.rokku.sts.service.db.security.Encryption
import com.typesafe.scalalogging.LazyLogging
import com.ing.wbaa.rokku.sts.util.JwtToken

import scala.concurrent.Future
import scala.util.{ Failure, Success }

trait AdminApi extends LazyLogging with Encryption {
trait AdminApi extends LazyLogging with Encryption with JwtToken {

protected[this] def stsSettings: StsSettings

val adminRoutes: Route = pathPrefix("admin") {
listAllNPAs ~ addNPA ~ setAccountStatus
listAllNPAs ~ addNPA ~ addServiceNPA ~ setAccountStatus
}

case class ResponseMessage(code: String, message: String, target: String)
Expand All @@ -38,9 +39,12 @@ trait AdminApi extends LazyLogging with Encryption {

protected[this] def getAllNPAAccounts: Future[NPAAccountList]

implicit val requestId = RequestId("")

def userInAdminGroups(userGroups: Set[UserGroup]): Boolean =
userGroups.exists(g => stsSettings.adminGroups.contains(g.value))

//todo: Personal login from keycloak should be removed or changed to service keycloak token
def addNPA: Route = logRequestResult("debug") {
post {
path("npa") {
Expand Down Expand Up @@ -68,6 +72,33 @@ trait AdminApi extends LazyLogging with Encryption {
}
}

def addServiceNPA: Route = logRequestResult("debug") {
post {
path("service" / "npa") {
formFields((Symbol("npaAccount"), Symbol("awsAccessKey"), Symbol("awsSecretKey"))) { (npaAccount, awsAccessKey, awsSecretKey) =>
headerValueByName("Authorization") { bearerToken =>
if (verifyInternalToken(bearerToken)) {
val awsCredentials = AwsCredential(AwsAccessKey(awsAccessKey), AwsSecretKey(awsSecretKey))
onComplete(insertAwsCredentials(UserName(npaAccount), awsCredentials, isNpa = true)) {
case Success(true) =>
logger.info(s"NPA: $npaAccount successfully created")
complete(ResponseMessage("NPA Created", s"NPA: $npaAccount successfully created", "NPA add"))
case Success(false) =>
logger.warn(s"NPA: $npaAccount create failed, accessKey or NPA name must be unique")
complete(ResponseMessage("NPA Create Failed", "Error adding NPA account, accessKey or NPA name must be unique", "NPA add"))
case Failure(ex) =>
logger.error(s"NPA: $npaAccount create failed, " + ex.getMessage)
complete(ResponseMessage("NPA Create Failed", ex.getMessage, "NPA add"))
}
} else {
reject(AuthorizationFailedRejection)
}
}
}
}
}
}

def listAllNPAs: Route =
path("npa" / "list") {
get {
Expand Down
31 changes: 30 additions & 1 deletion src/test/scala/com/ing/wbaa/rokku/sts/api/AdminApiTest.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.ing.wbaa.rokku.sts.api

import akka.actor.ActorSystem
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ FormData, StatusCodes }
import akka.http.scaladsl.server.{ AuthorizationFailedRejection, MissingFormFieldRejection, Route }
import akka.http.scaladsl.server.{ AuthorizationFailedRejection, MissingFormFieldRejection, MissingHeaderRejection, Route }
import akka.http.scaladsl.testkit.ScalatestRouteTest
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.ing.wbaa.rokku.sts.config.StsSettings
import com.ing.wbaa.rokku.sts.data._
import com.ing.wbaa.rokku.sts.data.aws.AwsCredential
Expand Down Expand Up @@ -43,6 +46,15 @@ class AdminApiTest extends AnyWordSpec
val validOAuth2TokenHeader: RequestTransformer = addHeader("Authorization", "Bearer valid")
val notAdminOAuth2TokenHeader: RequestTransformer = addHeader("Authorization", "Bearer notAdmin")

val bearerToken: String => String = issuer => {
val stsSettings: StsSettings = new StsSettings(system.settings.config)
val algorithm = Algorithm.HMAC256(stsSettings.decodeSecret)
JWT.create()
.withIssuer(issuer)
.withClaim("service", "rokku")
.sign(algorithm)
}

"Admin Api" should {
"check response" that {
"return OK if user is in admin groups and all FormFields are posted" in {
Expand Down Expand Up @@ -70,6 +82,23 @@ class AdminApiTest extends AnyWordSpec
assert(rejections.contains(AuthorizationFailedRejection))
}
}
"return Rejected if service token is missing" in {
Post("/admin/service/npa", FormData("npaAccount" -> "testNPA", "awsAccessKey" -> "SomeAccessKey", "awsSecretKey" -> "SomeSecretKey")) ~> testRoute ~> check {
assert(rejections.contains(MissingHeaderRejection("Authorization")))
}
}
"return OK if service token is correct" in {
Post("/admin/service/npa", FormData("npaAccount" -> "testNPA", "awsAccessKey" -> "SomeAccessKey", "awsSecretKey" -> "SomeSecretKey"))
.addHeader(RawHeader("Authorization", bearerToken("rokku"))) ~> testRoute ~> check {
assert(status == StatusCodes.OK)
}
}
"return Rejected if service token is not correct" in {
Post("/admin/service/npa", FormData("npaAccount" -> "testNPA1", "awsAccessKey" -> "SomeAccessKey", "awsSecretKey" -> "SomeSecretKey"))
.addHeader(RawHeader("Authorization", bearerToken("rokku1"))) ~> testRoute ~> check {
assert(status == StatusCodes.InternalServerError)
}
}
"return Rejected if user FormData is invalid" in {
Post("/admin/npa", FormData("npaAccount" -> "testNPA", "awsAccessKey" -> "SomeAccessKey")) ~> validOAuth2TokenHeader ~> testRoute ~> check {
assert(rejections.contains(MissingFormFieldRejection("awsSecretKey")))
Expand Down

0 comments on commit 2a98b9d

Please sign in to comment.