Skip to content

Instantly share code, notes, and snippets.

@pawelkaczor
Created September 27, 2017 07:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pawelkaczor/8009c05eed30f67099cae70401939e55 to your computer and use it in GitHub Desktop.
Save pawelkaczor/8009c05eed30f67099cae70401939e55 to your computer and use it in GitHub Desktop.
Extension methods to Typesafe Config to support Docker Swarm secrets
package com.typesafe.config.impl
import com.typesafe.config.ConfigFactory.parseMap
import com.typesafe.config.{Config, ConfigFactory}
import scala.collection.JavaConverters._
import scala.io.Source
import scala.util.Try
// discussion: https://groups.google.com/forum/#!topic/play-framework-dev/t2g-TWbqtzY
trait ConfigExtensions {
implicit class ExtConfig(config: Config) {
val rawConfig: Config = ConfigFactory.defaultApplication()
def withSecretAt(path: String*): Config = {
val secretConfig = parseMap(path.map(p => (p, Try(getSecretUnsafe(p)).toOption.orNull)).filterNot(_._2 == null).toMap.asJava)
secretConfig.withFallback(config)
}
def getSecret(path: String): String =
Try {
getSecretUnsafe(path)
}.recover {
case _ => config.getString(path)
}.get
private def getSecretUnsafe(path: String) = {
val p: Path = Path.newPath(path)
val last: String = p.last()
val rs = new ResolveSource(rawConfig.getObject(path.stripSuffix(s".$last")).asInstanceOf[AbstractConfigObject])
val envVarName = rs.root.get(last) match {
case cr: ConfigReference =>
cr.expression.path.render
case cdm: ConfigDelayedMerge =>
cdm.unmergedValues().iterator().next().render().stripPrefix("${").stripPrefix("?").stripSuffix("}")
}
String.valueOf(Source.fromFile(s"/run/secrets/$envVarName").toArray)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment