Skip to content

Commit

Permalink
replace some hard coded clauses of the Content-Security-Policy with v…
Browse files Browse the repository at this point in the history
…alues from config to remove guardian specific stuff
  • Loading branch information
twrichards committed Mar 25, 2024
1 parent e37e3ac commit 94b144a
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 6 deletions.
4 changes: 3 additions & 1 deletion dev/script/generate-config/service-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ function getKahunaConfig(config){
| host: "https://pinboard.${config.DOMAIN}",
| path: "pinboard.loader.js",
| async: true,
| permission: "pinboard"
| permission: "pinboard",
| additionalFrameSourcesForCSP: ["https://www.youtube.com"]
| additionalImageSourcesForCSP: ["https://*.googleusercontent.com"]
| }
|]`;

Expand Down
6 changes: 3 additions & 3 deletions kahuna/app/KahunaComponents.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object KahunaSecurityConfig {
config.services.guardianWitnessBaseUri
)

val frameSources = s"frame-src ${config.services.authBaseUri} ${config.services.kahunaBaseUri} https://accounts.google.com https://www.youtube.com ${config.scriptsToLoad.map(_.host).mkString(" ")}"
val frameSources = s"frame-src ${config.services.authBaseUri} ${config.services.kahunaBaseUri} ${config.scriptsToLoad.flatMap(_.cspFrameSources).mkString(" ")}"
val frameAncestors = s"frame-ancestors ${config.frameAncestors.mkString(" ")}"
val connectSources = s"connect-src 'self' ${(services :+ config.imageOrigin).mkString(" ")} ${config.connectSources.mkString(" ")}"

Expand All @@ -49,13 +49,13 @@ object KahunaSecurityConfig {
URI.ensureSecure(config.thumbOrigin).toString,
URI.ensureSecure(config.cropOrigin).toString,
URI.ensureSecure("app.getsentry.com").toString,
"https://*.googleusercontent.com",
config.scriptsToLoad.flatMap(_.cspImageSources).mkString(" "),
"'self'"
).mkString(" ")}"

val fontSources = s"font-src data: 'self' ${config.fontSources.mkString(" ")}"

val scriptSources = s"script-src 'self' 'unsafe-inline' ${config.scriptsToLoad.map(_.host).mkString(" ")}"
val scriptSources = s"script-src 'self' 'unsafe-inline' ${config.scriptsToLoad.flatMap(_.cspScriptSources).mkString(" ")}"

base.copy(
// covered by frame-ancestors in contentSecurityPolicy
Expand Down
15 changes: 13 additions & 2 deletions kahuna/app/lib/KahunaConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import com.gu.mediaservice.lib.auth.Permissions.Pinboard
import com.gu.mediaservice.lib.auth.SimplePermission
import com.gu.mediaservice.lib.config.{CommonConfig, GridConfigResources}

import scala.jdk.CollectionConverters.iterableAsScalaIterableConverter

case class ScriptToLoad(
host: String,
path: String,
async: Option[Boolean],
permission: Option[SimplePermission],
shouldLoadWhenIFramed: Option[Boolean]
)
shouldLoadWhenIFramed: Option[Boolean],
additionalFrameSourcesForCSP: Option[Set[String]] = None,
additionalImageSourcesForCSP: Option[Set[String]] = None,
) {
def cspScriptSources: Set[String] = Set(host)
def cspFrameSources: Set[String] = additionalFrameSourcesForCSP.getOrElse(Set.empty) + host
def cspImageSources: Set[String] = additionalImageSourcesForCSP.getOrElse(Set.empty)
}

class KahunaConfig(resources: GridConfigResources) extends CommonConfig(resources) {
val rootUri: String = services.kahunaBaseUri
Expand Down Expand Up @@ -41,6 +49,7 @@ class KahunaConfig(resources: GridConfigResources) extends CommonConfig(resource

val showDenySyndicationWarning: Option[Boolean] = booleanOpt("showDenySyndicationWarning")

val frameSources: Set[String] = getStringSet("security.frameSources")
val frameAncestors: Set[String] = getStringSet("security.frameAncestors")
val connectSources: Set[String] = getStringSet("security.connectSources") ++ maybeIngestBucket.map { ingestBucket =>
if (isDev) "https://localstack.media.local.dev-gutools.co.uk"
Expand All @@ -55,6 +64,8 @@ class KahunaConfig(resources: GridConfigResources) extends CommonConfig(resource
// FIXME ideally the below would not hardcode reference to pinboard - hopefully future iterations of the pluggable authorisation will support evaluating permissions without a corresponding case object
permission = if (entry.hasPath("permission") && entry.getString("permission") == "pinboard") Some(Pinboard) else None,
shouldLoadWhenIFramed = if (entry.hasPath("shouldLoadWhenIFramed")) Some(entry.getBoolean("shouldLoadWhenIFramed")) else None,
additionalFrameSourcesForCSP = if (entry.hasPath("additionalFrameSourcesForCSP")) Some(entry.getStringList("additionalFrameSourcesForCSP").asScala.toSet) else None,
additionalImageSourcesForCSP = if (entry.hasPath("additionalImageSourcesForCSP")) Some(entry.getStringList("additionalImageSourcesForCSP").asScala.toSet) else None,
))

val metadataTemplates: Seq[MetadataTemplate] = configuration.get[Seq[MetadataTemplate]]("metadata.templates")
Expand Down

0 comments on commit 94b144a

Please sign in to comment.