From cc4f4e3c53b6cf16f857136ae72e70c4f5b89800 Mon Sep 17 00:00:00 2001 From: John Green Date: Fri, 14 Jul 2023 09:20:57 +0100 Subject: [PATCH] API-7018: Improve Content Security Policy using latest play-bootstrap (#471) * API-7018: Tidy up of CSP to remove config done by play-bootstrap 7.15.0 and above * API-7018: Build cleanup * API-7018: Style and formatting * API-7018: PR recommendations * API-7018: Switch off CSP report-uri for local testing --- .../config/ApplicationConfig.scala | 2 +- .../controllers/AuthorisationController.scala | 2 +- .../controllers/DocumentationController.scala | 12 ++++---- .../OpenApiDocumentationController.scala | 5 ++-- .../views/OpenApiPreviewView.scala.html | 2 +- .../views/TermsOfUseNotMeetingView.scala.html | 4 +-- .../views/TermsOfUseView.scala.html | 2 +- .../TermsOfUseWhatYouCanExpectView.scala.html | 4 +-- build.sbt | 22 ++++++++------- conf/application.conf | 28 +------------------ project/AppDependencies.scala | 4 +-- project/Silencer.scala | 17 ----------- run_local_with_dependencies.sh | 2 +- .../DocumentationControllerSpec.scala | 3 +- .../models/DocumentationSpec.scala | 6 ++-- .../views/include/IndexViewSpec.scala | 2 +- 16 files changed, 37 insertions(+), 80 deletions(-) delete mode 100644 project/Silencer.scala diff --git a/app/uk/gov/hmrc/apidocumentation/config/ApplicationConfig.scala b/app/uk/gov/hmrc/apidocumentation/config/ApplicationConfig.scala index b1bfdee6..0972d0eb 100644 --- a/app/uk/gov/hmrc/apidocumentation/config/ApplicationConfig.scala +++ b/app/uk/gov/hmrc/apidocumentation/config/ApplicationConfig.scala @@ -106,7 +106,7 @@ class ApplicationConfigImpl @Inject() (config: Configuration) val cookieSettingsUrl: String = s"/${getString("tracking-consent-frontend.cookie-settings-path")}" - val oasFetchResolvedMaxDuration: Long = config.getMillis("oasFetchResolvedMaxDurationMilliseconds") + val oasFetchResolvedMaxDuration: Long = config.getMillis("oasFetchResolvedMaxDurationMilliseconds") val oasFetchResolvedUsingHttps: Boolean = getBoolean("oasFetchResolvedUsingHttps") private def platformBaseUrl(key: String) = { diff --git a/app/uk/gov/hmrc/apidocumentation/controllers/AuthorisationController.scala b/app/uk/gov/hmrc/apidocumentation/controllers/AuthorisationController.scala index 2477b35d..78752b4e 100644 --- a/app/uk/gov/hmrc/apidocumentation/controllers/AuthorisationController.scala +++ b/app/uk/gov/hmrc/apidocumentation/controllers/AuthorisationController.scala @@ -23,7 +23,7 @@ import play.api.mvc._ import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController import uk.gov.hmrc.apidocumentation.config.ApplicationConfig -import uk.gov.hmrc.apidocumentation.models.{Breadcrumbs, Crumb} +import uk.gov.hmrc.apidocumentation.models.Crumb import uk.gov.hmrc.apidocumentation.services._ import uk.gov.hmrc.apidocumentation.util.ApplicationLogger import uk.gov.hmrc.apidocumentation.views.html._ diff --git a/app/uk/gov/hmrc/apidocumentation/controllers/DocumentationController.scala b/app/uk/gov/hmrc/apidocumentation/controllers/DocumentationController.scala index 3545bc37..cda8e6e5 100644 --- a/app/uk/gov/hmrc/apidocumentation/controllers/DocumentationController.scala +++ b/app/uk/gov/hmrc/apidocumentation/controllers/DocumentationController.scala @@ -56,7 +56,6 @@ class DocumentationController @Inject() ( with TermsCrumb with ApplicationLogger { - def indexPage(): Action[AnyContent] = headerNavigation { def extractDeveloperIdentifier(f: Future[Option[Developer]]): Future[Option[DeveloperIdentifier]] = { f.map(o => @@ -64,11 +63,12 @@ class DocumentationController @Inject() ( ) } - implicit request => navLinks => - for { - userId <- extractDeveloperIdentifier(loggedInUserService.fetchLoggedInUser()) - isLoggedIn = userId.isDefined - } yield Ok(indexView("Home", navLinks, isLoggedIn)) + implicit request => + navLinks => + for { + userId <- extractDeveloperIdentifier(loggedInUserService.fetchLoggedInUser()) + isLoggedIn = userId.isDefined + } yield Ok(indexView("Home", navLinks, isLoggedIn)) } def tutorialsPage(): Action[AnyContent] = headerNavigation { diff --git a/app/uk/gov/hmrc/apidocumentation/controllers/OpenApiDocumentationController.scala b/app/uk/gov/hmrc/apidocumentation/controllers/OpenApiDocumentationController.scala index cf6e5b66..0b83927e 100644 --- a/app/uk/gov/hmrc/apidocumentation/controllers/OpenApiDocumentationController.scala +++ b/app/uk/gov/hmrc/apidocumentation/controllers/OpenApiDocumentationController.scala @@ -22,6 +22,7 @@ import javax.inject.{Inject, Singleton} import scala.concurrent.Future.successful import scala.concurrent.duration.FiniteDuration import scala.concurrent.{ExecutionContext, Future, blocking} +import scala.jdk.CollectionConverters._ import akka.actor.ActorSystem import io.swagger.v3.core.util.Yaml @@ -43,8 +44,6 @@ import uk.gov.hmrc.apidocumentation.services.{ApiDefinitionService, LoggedInUser import uk.gov.hmrc.apidocumentation.util.ApplicationLogger import uk.gov.hmrc.apidocumentation.views.html._ -import scala.jdk.CollectionConverters._ - @Singleton class OpenApiDocumentationController @Inject() ( openApiViewRedoc: OpenApiViewRedoc, @@ -138,7 +137,7 @@ class OpenApiDocumentationController @Inject() ( parseOptions.setResolve(true) parseOptions.setResolveFully(true) - val emptyAuthList = java.util.Collections.emptyList[io.swagger.v3.parser.core.models.AuthorizationValue]() + val emptyAuthList = java.util.Collections.emptyList[io.swagger.v3.parser.core.models.AuthorizationValue]() val fetchUsingHttps = appConfig.oasFetchResolvedUsingHttps val oasFileLocation = routes.OpenApiDocumentationController.fetchOas(service, version).absoluteURL(fetchUsingHttps) diff --git a/app/uk/gov/hmrc/apidocumentation/views/OpenApiPreviewView.scala.html b/app/uk/gov/hmrc/apidocumentation/views/OpenApiPreviewView.scala.html index e6102fa5..984ebe71 100644 --- a/app/uk/gov/hmrc/apidocumentation/views/OpenApiPreviewView.scala.html +++ b/app/uk/gov/hmrc/apidocumentation/views/OpenApiPreviewView.scala.html @@ -46,7 +46,7 @@

- + Reset diff --git a/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseNotMeetingView.scala.html b/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseNotMeetingView.scala.html index 1f3f317f..0ea8da48 100644 --- a/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseNotMeetingView.scala.html +++ b/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseNotMeetingView.scala.html @@ -44,8 +44,8 @@

If your software doesn’t meet our terms of use

diff --git a/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseView.scala.html b/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseView.scala.html index 2c0400cd..156d3cda 100644 --- a/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseView.scala.html +++ b/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseView.scala.html @@ -29,7 +29,7 @@

The current Terms of Use could not be loaded. - Please try again later. + Please try again later.

} diff --git a/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseWhatYouCanExpectView.scala.html b/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseWhatYouCanExpectView.scala.html index 28d1ebe4..dd6e65fd 100644 --- a/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseWhatYouCanExpectView.scala.html +++ b/app/uk/gov/hmrc/apidocumentation/views/TermsOfUseWhatYouCanExpectView.scala.html @@ -41,8 +41,8 @@

What you can expect from us


} diff --git a/build.sbt b/build.sbt index a872c865..c1e35ceb 100644 --- a/build.sbt +++ b/build.sbt @@ -11,18 +11,14 @@ import bloop.integrations.sbt.BloopDefaults Global / bloopAggregateSourceDependencies := true +scalaVersion := "2.13.8" + ThisBuild / scalafixDependencies += "com.github.liancheng" %% "organize-imports" % "0.6.0" +ThisBuild / semanticdbEnabled := true +ThisBuild / semanticdbVersion := scalafixSemanticdb.revision ThisBuild / evictionWarningOptions := EvictionWarningOptions.default.withWarnScalaVersionEviction(false) -inThisBuild( - List( - scalaVersion := "2.13.8", - semanticdbEnabled := true, - semanticdbVersion := scalafixSemanticdb.revision - ) -) - lazy val plugins: Seq[Plugins] = Seq(PlayScala, SbtDistributablesPlugin) lazy val playSettings: Seq[Setting[_]] = Seq.empty lazy val microservice = Project(appName, file(".")) @@ -86,10 +82,16 @@ lazy val microservice = Project(appName, file(".")) .settings(DefaultBuildSettings.integrationTestSettings()) - .settings(scalaVersion := "2.13.8") .settings(headerSettings(AcceptanceTest) ++ automateHeaderSettings(AcceptanceTest)) - .settings(SilencerSettings()) + .settings( + scalacOptions ++= Seq( + "-Wconf:cat=unused&src=views/.*\\.scala:s", + "-Wconf:cat=unused&src=.*RoutesPrefix\\.scala:s", + "-Wconf:cat=unused&src=.*Routes\\.scala:s", + "-Wconf:cat=unused&src=.*ReverseRoutes\\.scala:s" + ) + ) lazy val AcceptanceTest = config("acceptance") extend Test lazy val appName = "api-documentation-frontend" diff --git a/conf/application.conf b/conf/application.conf index bdef8b1c..ec9ad24f 100644 --- a/conf/application.conf +++ b/conf/application.conf @@ -28,12 +28,6 @@ appName = "api-documentation-frontend" # !!!WARNING!!! DO NOT CHANGE THIS ROUTER play.http.router = prod.Routes -# An ApplicationLoader that uses Guice to bootstrap the application. -play.application.loader = "uk.gov.hmrc.play.bootstrap.ApplicationLoader" - -# Primary entry point for all HTTP requests on Play applications -play.http.requestHandler = "uk.gov.hmrc.play.bootstrap.http.RequestHandler" - # Provides an implementation of AuditConnector. Use `uk.gov.hmrc.play.bootstrap.AuditModule` or create your own. # An audit connector must be provided. play.modules.enabled += "uk.gov.hmrc.play.audit.AuditModule" @@ -59,15 +53,6 @@ feedbackBanner { } } -metrics { - name = ${appName} - rateUnit = SECONDS - durationUnit = SECONDS - showSamples = true - jvm = false - enabled = false -} - platform { production { api { @@ -87,7 +72,7 @@ platform { } } -play.filters.csp.directives.script-src = ${play.filters.csp.nonce.pattern} "'strict-dynamic' 'unsafe-inline' https: http:" +play.filters.csp.directives.report-uri = 'none' retryCount = 3 retryDelayMilliseconds = 500 @@ -127,17 +112,6 @@ features { subordinateBaseUrl = "https://api.development.tax.service.gov.uk" } -auditing { - enabled = false - - consumer { - baseUri { - host = "localhost" - port = 8100 - } - } -} - xml-api { base-url = "https://www.gov.uk" } diff --git a/project/AppDependencies.scala b/project/AppDependencies.scala index 0152b973..76128026 100644 --- a/project/AppDependencies.scala +++ b/project/AppDependencies.scala @@ -6,7 +6,7 @@ object AppDependencies { def apply(): Seq[ModuleID] = compile ++ test lazy val playJsonVersion = "2.9.2" - lazy val bootstrapVersion = "7.14.0" + lazy val bootstrapVersion = "7.19.0" lazy val seleniumVersion = "4.2.0" lazy val jacksonDatabindVersion = "2.10.5.1" lazy val jacksonVersion = "2.10.5" @@ -17,7 +17,7 @@ object AppDependencies { "uk.gov.hmrc" %% "bootstrap-frontend-play-28" % bootstrapVersion, "uk.gov.hmrc" %% "http-metrics" % "2.7.0", "uk.gov.hmrc" %% "play-partials" % "8.4.0-play-28", - "uk.gov.hmrc" %% "play-frontend-hmrc" % "7.3.0-play-28", + "uk.gov.hmrc" %% "play-frontend-hmrc" % "7.14.0-play-28", "org.typelevel" %% "cats-core" % "2.6.1", "org.commonjava.googlecode.markdown4j" % "markdown4j" % "2.2-cj-1.1", "com.typesafe.play" %% "play-json" % playJsonVersion, diff --git a/project/Silencer.scala b/project/Silencer.scala deleted file mode 100644 index c2333ef3..00000000 --- a/project/Silencer.scala +++ /dev/null @@ -1,17 +0,0 @@ -import sbt.{CrossVersion, compilerPlugin} -import sbt.Keys._ -import sbt._ - -object SilencerSettings { - // stop "unused import" warnings from routes files - def apply() = Seq( - libraryDependencies ++= Seq( - compilerPlugin("com.github.ghik" % "silencer-plugin" % "1.7.9" cross CrossVersion.full), - "com.github.ghik" % "silencer-lib" % "1.7.9" % Provided cross CrossVersion.full - ), - // silence all warnings on autogenerated files - scalacOptions += "-P:silencer:pathFilters=target/.*", - // Make sure you only exclude warnings for the project directories, i.e. make builds reproducible - scalacOptions += s"-P:silencer:sourceRoots=${baseDirectory.value.getCanonicalPath}" - ) -} \ No newline at end of file diff --git a/run_local_with_dependencies.sh b/run_local_with_dependencies.sh index 02e96c08..46bcb62f 100755 --- a/run_local_with_dependencies.sh +++ b/run_local_with_dependencies.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -sm --start API_DEFINITION THIRD_PARTY_APPLICATION API_EXAMPLE_MICROSERVICE API_PLATFORM_MICROSERVICE THIRD_PARTY_DEVELOPER_FRONTEND CONTACT_FRONTEND API_PLATFORM_XML_SERVICES +sm2 --start API_DEFINITION THIRD_PARTY_APPLICATION API_EXAMPLE_MICROSERVICE API_PLATFORM_MICROSERVICE THIRD_PARTY_DEVELOPER_FRONTEND CONTACT_FRONTEND API_PLATFORM_XML_SERVICES ./run_local.sh diff --git a/test/uk/gov/hmrc/apidocumentation/controllers/DocumentationControllerSpec.scala b/test/uk/gov/hmrc/apidocumentation/controllers/DocumentationControllerSpec.scala index e6c4ad99..a2ddab70 100644 --- a/test/uk/gov/hmrc/apidocumentation/controllers/DocumentationControllerSpec.scala +++ b/test/uk/gov/hmrc/apidocumentation/controllers/DocumentationControllerSpec.scala @@ -32,10 +32,9 @@ import uk.gov.hmrc.apidocumentation.controllers.utils._ import uk.gov.hmrc.apidocumentation.mocks.config._ import uk.gov.hmrc.apidocumentation.mocks.services._ import uk.gov.hmrc.apidocumentation.models._ -import uk.gov.hmrc.apidocumentation.services.PartialsService +import uk.gov.hmrc.apidocumentation.services.{LoggedInUserService, PartialsService} import uk.gov.hmrc.apidocumentation.views.html.{TermsOfUseNotMeetingView, TermsOfUseWhatYouCanExpectView, _} import uk.gov.hmrc.apidocumentation.{ErrorHandler, controllers} -import uk.gov.hmrc.apidocumentation.services.LoggedInUserService class DocumentationControllerSpec extends CommonControllerBaseSpec diff --git a/test/uk/gov/hmrc/apidocumentation/models/DocumentationSpec.scala b/test/uk/gov/hmrc/apidocumentation/models/DocumentationSpec.scala index 9d7c7871..7adff361 100644 --- a/test/uk/gov/hmrc/apidocumentation/models/DocumentationSpec.scala +++ b/test/uk/gov/hmrc/apidocumentation/models/DocumentationSpec.scala @@ -393,17 +393,17 @@ class DocumentationSpec extends HmrcSpec { "nameAsId" should { "swap spaces for hyphens and lower case" in { - val api1 = anApiDefinition("Hello World") + val api1 = anApiDefinition("Hello World") api1.nameAsId shouldBe "hello-world" } "remove brackets" in { - val api1 = anApiDefinition("Income Tax (MTD) end-to-end service guide") + val api1 = anApiDefinition("Income Tax (MTD) end-to-end service guide") api1.nameAsId shouldBe "income-tax-mtd-end-to-end-service-guide" } "remove any other chars" in { - val api1 = anApiDefinition("Income Tax (MTD):+{}=#@£!& [end-to-end service guide]") + val api1 = anApiDefinition("Income Tax (MTD):+{}=#@£!& [end-to-end service guide]") api1.nameAsId shouldBe "income-tax-mtd-end-to-end-service-guide" } } diff --git a/test/uk/gov/hmrc/apidocumentation/views/include/IndexViewSpec.scala b/test/uk/gov/hmrc/apidocumentation/views/include/IndexViewSpec.scala index f3d097ca..ac41df97 100644 --- a/test/uk/gov/hmrc/apidocumentation/views/include/IndexViewSpec.scala +++ b/test/uk/gov/hmrc/apidocumentation/views/include/IndexViewSpec.scala @@ -52,7 +52,7 @@ class IndexViewSpec extends CommonViewSpec { renderedHtml.body should include("Sign up to use our APIs and get email updates.") renderedHtml.body should include("sign in") } - + "render without sign in components if signed in" in new TestCase { val renderedHtml = new IndexView(main)(pageTitle, navLinks, true) renderedHtml.body shouldNot include("Get an account")