Skip to content
This repository has been archived by the owner on Sep 29, 2023. It is now read-only.

Commit

Permalink
Merge pull request #62 from zalando-stups/issue-61-support-for-play-2…
Browse files Browse the repository at this point in the history
….7.0

Issue 61 support for play 2.7.0
  • Loading branch information
dmitrykrivaltsevich authored Mar 29, 2019
2 parents 5468593 + 0a04b57 commit 9780aa6
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 61 deletions.
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
language: scala

scala:
- 2.11.8
- 2.11.12
- 2.12.8

jdk:
- oraclejdk8

script:
- sbt clean coverage test
- sbt clean +coverage +test
after_success:
- sbt coverageReport coveralls
- sbt +coverageReport coveralls
- bash <(curl -s https://codecov.io/bash)

# go faster on travis
sudo: false

notifications:
email:
- [email protected]
- [email protected]
- [email protected]
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
## [Unreleased]
## [2.7.0] - 2019-03-28
### Changed
- Rename `PlugableMetrics` trait to `PluggableMetrics`. Rename all occurrences of `Plugable*` to `Pluggable*`.
- Add `Duration` support in configuration properties.
- Add support of Play! 2.7.0

## [0.3.4] - 2018-06-06
### Changed
Expand Down
3 changes: 1 addition & 2 deletions MAINTAINERS
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
Dmitry Krivaltsevich <[email protected]>
William Okuyama <[email protected]>
Raymond Chenon <[email protected]>
Mikhail Litvin <[email protected]>
15 changes: 2 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,7 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/fa1fb822bc1246508d343880c0b1868c)](https://www.codacy.com/app/dmitrykrivaltsevich/play-zhewbacca?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=zalando-stups/play-zhewbacca&amp;utm_campaign=Badge_Grade)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/zalando-stups/play-zhewbacca/master/LICENSE)


**[Table of Contents](http://tableofcontent.eu)**
<!-- Table of contents generated generated by http://tableofcontent.eu -->
- [Play-security library](#play-security-library)
- [Core Technical Concepts](#core-technical-concepts)
- [Known alternatives](#known-alternatives)
- [Getting Started](#getting-started)
- [Contributing](#contributing)
- [Contact](#contact)
- [License](#license)

Play! (v2.5 - 2.6) library to protect RESTful resource servers using OAuth2. According to [RFC 6749](https://tools.ietf.org/html/rfc6749#section-7):
Play! library to protect RESTful resource servers using OAuth2. Supported Play! Framework versions are 2.5.x, 2.6.x, 2.7.x. According to [RFC 6749](https://tools.ietf.org/html/rfc6749#section-7):

> The client accesses protected resources by presenting the _access
token_ to the _resource server_. The resource server MUST _validate_ the
Expand Down Expand Up @@ -67,7 +56,7 @@ We mainly decided to release this library because we saw the needs of OAuth2 pro
Configure libraries dependencies in your `build.sbt`:

```scala
libraryDependencies += "org.zalando" %% "play-zhewbacca" % "0.3.4"
libraryDependencies += "org.zalando" %% "play-zhewbacca" % "2.7.0"
```

To configure Development environment:
Expand Down
23 changes: 11 additions & 12 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import sbt.Keys._

import scalariform.formatter.preferences._

val playFrameworkVersion = "2.7.0"

val commonSettings = Seq(
organization := "org.zalando",
version := "0.3.4",
scalaVersion := "2.12.5",
crossScalaVersions := Seq("2.11.12", "2.12.5"),
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),
version := playFrameworkVersion,
scalaVersion := "2.12.8",
// play 2.7.0 started to use scalac version 2.13.0-M5, but
// we cannot use "2.13.0-M5" because of "atmos" library (it does not support scala 2.13 yet)
crossScalaVersions := Seq("2.11.12", "2.12.8"),
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8", "-Xfatal-warnings"),
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (isSnapshot.value) {
Expand All @@ -27,12 +31,10 @@ val commonSettings = Seq(
)
)

val playFrameworkVersion = "2.6.12"

lazy val testDependencies =
Seq(
"org.specs2" %% "specs2-core" % "4.0.3" % "test",
"org.specs2" %% "specs2-junit" % "4.0.3" % "test"
"org.specs2" %% "specs2-core" % "4.3.5" % "test",
"org.specs2" %% "specs2-junit" % "4.3.5" % "test"
)

lazy val playDependencies =
Expand Down Expand Up @@ -104,9 +106,6 @@ pomExtra := (
<name>Dmitry Krivaltsevich</name>
</developer>
<developer>
<name>William Okuyama</name>
</developer>
<developer>
<name>Raymond Chenon</name>
<name>Mikhail Litvin</name>
</developer>
</developers>)
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.0.2
sbt.version=1.2.7
4 changes: 3 additions & 1 deletion src/main/scala/org/zalando/zhewbacca/SecurityFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ class SecurityFilter @Inject() (
implicit val mat: Materializer,
implicit val ec: ExecutionContext) extends Filter {

private val logger = Logger(getClass)

override def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = {
rulesRepository.get(requestHeader).getOrElse {
Logger.debug(s"No security rules found for ${requestHeader.method} ${requestHeader.uri}. Access denied.")
logger.debug(s"No security rules found for ${requestHeader.method} ${requestHeader.uri}. Access denied.")
DenyAllRule
}.execute(nextFilter, requestHeader)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import play.api.mvc.RequestHeader

class SecurityRulesRepository @Inject() (configuration: Configuration, provider: AuthProvider) {

private val logger = Logger(getClass)

private val SupportedHttpMethods: Set[String] = Set(GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)

private val ConfigKeyMethod = "method"
Expand All @@ -26,7 +28,7 @@ class SecurityRulesRepository @Inject() (configuration: Configuration, provider:

private def load(): Seq[StrictRule] = {
val securityRulesFileName = configuration.getOptional[String]("authorisation.rules.file").getOrElse("security_rules.conf")
Logger.info(s"Configuration file for security rules: $securityRulesFileName")
logger.info(s"Configuration file for security rules: $securityRulesFileName")

if (configFileExists(securityRulesFileName)) {
ConfigFactory.load(securityRulesFileName)
Expand All @@ -40,15 +42,15 @@ class SecurityRulesRepository @Inject() (configuration: Configuration, provider:
private def toRule(config: Config): StrictRule = {
(getHttpMethod(config), config.getString(ConfigKeyPathRegex), getAllowedFlag(config), getScopeNames(config)) match {
case (Some(method), pathRegex, Some(true), _) =>
Logger.info(s"Explicitly allowed unauthorized requests for method: '$method' and path regex: '$pathRegex'")
logger.info(s"Explicitly allowed unauthorized requests for method: '$method' and path regex: '$pathRegex'")
ExplicitlyAllowedRule(method, pathRegex)

case (Some(method), pathRegex, Some(false), _) =>
Logger.info(s"Explicitly denied all requests for method: '$method' and path regex: '$pathRegex'")
logger.info(s"Explicitly denied all requests for method: '$method' and path regex: '$pathRegex'")
ExplicitlyDeniedRule(method, pathRegex)

case (Some(method), pathRegex, None, Some(scopeNames)) =>
Logger.info(s"Configured required scopes '$scopeNames' for method '$method' and path regex: '$pathRegex'")
logger.info(s"Configured required scopes '$scopeNames' for method '$method' and path regex: '$pathRegex'")
ValidateTokenRule(provider, method, pathRegex, Scope(scopeNames))

case _ =>
Expand Down
29 changes: 21 additions & 8 deletions src/test/scala/org/zalando/zhewbacca/IAMClientSpec.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.zalando.zhewbacca

import akka.actor.ActorSystem
import javax.inject.{Inject, Provider}
import org.specs2.mutable.Specification
import org.zalando.zhewbacca.metrics.NoOpPluggableMetrics
import play.api.http.{DefaultFileMimeTypes, FileMimeTypesConfiguration, Port}
import play.api.inject._
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.ws.WSClient
import play.api.mvc._
import play.api.routing.Router
import play.api.test.WsTestClient
import play.api.{Application, Configuration, Mode}
import play.core.server.Server
Expand Down Expand Up @@ -176,17 +179,14 @@ class IAMClientSpec extends Specification {
}

def fakeApp(delay: Duration = 0.second, response: Result = Results.Ok): Application = {
val routes: PartialFunction[(String, String), Handler] = {
case ("GET", "/tokeninfo") => Action {
Thread.sleep(delay.toMillis)
response
}
}

new GuiceApplicationBuilder()
.in(Mode.Test)
.routes(routes)
.configure("play.akka.actor-system" -> s"application_iam_client_${java.util.UUID.randomUUID}")
.bindings(
bind[Duration].toInstance(delay),
bind[Result].toInstance(response))
.overrides(
bind[Router].toProvider[IAMClientTestRouterProvider])
.build
}

Expand All @@ -210,3 +210,16 @@ class IAMClientSpec extends Specification {
new IAMClient(clientConfig, new NoOpPluggableMetrics, client, actorSystem, ExecutionContext.Implicits.global)
}
}

class IAMClientTestRouterProvider @Inject() (components: ControllerComponents, delay: Duration, response: Result) extends Provider[Router] {

import components.{actionBuilder => Action}
import play.api.routing.sird._

override def get(): Router = Router.from {
case GET(p"/tokeninfo") => Action {
Thread.sleep(delay.toMillis)
response
}
}
}
37 changes: 23 additions & 14 deletions src/test/scala/org/zalando/zhewbacca/SecurityFilterSpec.scala
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
package org.zalando.zhewbacca

import javax.inject.{Inject, Provider}
import play.api.inject._
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.mvc.Results._
import play.api.mvc._
import play.api.routing.Router
import play.api.test.{FakeRequest, PlaySpecification}
import play.api.{Application, Mode}

class SecurityFilterSpec extends PlaySpecification with BodyParsers {

val testTokenInfo = TokenInfo("", Scope.Empty, "token type", "user uid", realm = "/employees")

val routes: PartialFunction[(String, String), Handler] = {
// test action returning action type. Shows the usage and makes it possible to test basic behaviour
// security rules described in 'security_filter.conf' file
case ("GET", "/") => Action { request =>
import TokenInfoConverter._
Ok(request.tokenInfo.tokenType)
}

case ("GET", "/unprotected") => Action {
Ok
}
}

def appWithRoutes: Application = new GuiceApplicationBuilder()
.in(Mode.Test)
.bindings(bind[AuthProvider] to new AlwaysPassAuthProvider(testTokenInfo))
.routes(routes)
.overrides(
bind[Router].toProvider[SecurityFilterTestRouterProvider])
.configure(
"play.http.filters" -> "org.zalando.zhewbacca.TestingFilters",
"authorisation.rules.file" -> "security_filter.conf")
Expand All @@ -48,4 +38,23 @@ class SecurityFilterSpec extends PlaySpecification with BodyParsers {

}

}

class SecurityFilterTestRouterProvider @Inject() (components: ControllerComponents) extends Provider[Router] {

import components.{actionBuilder => Action}
import play.api.routing.sird._

override def get(): Router = Router.from {
// test action returning action type. Shows the usage and makes it possible to test basic behaviour
// security rules described in 'security_filter.conf' file
case GET(p"/") => Action { request =>
import TokenInfoConverter._
Ok(request.tokenInfo.tokenType)
}

case GET(p"/unprotected") => Action {
Ok
}
}
}

0 comments on commit 9780aa6

Please sign in to comment.