riff-raff/app/conf/Secrets.scala (53 lines of code) (raw):

package conf import controllers.Logging import magenta.SecretProvider import software.amazon.awssdk.services.ssm.SsmClient import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest import scala.jdk.CollectionConverters._ import scala.util.control.NonFatal case class CredentialKey(service: String, account: String) class Secrets(config: Config, ssmClient: SsmClient) extends SecretProvider with Logging { var credentials = Map.empty[CredentialKey, String] override def lookup(service: String, account: String): Option[String] = { credentials.get(CredentialKey(service, account)) } def populate(): Unit = { credentials = getCredentialsFromSsm log.info(s"Populated credentials from SSM: ${credentials.keys.toList .sortBy(ck => ck.service -> ck.account)}") } def getCredentialsFromSsm: Map[CredentialKey, String] = { val prefix = s"${config.credentials.paramPrefix.stripSuffix("/")}/" val request = GetParametersByPathRequest .builder() .path(prefix) .withDecryption(true) .recursive(true) .build() try { val response = ssmClient.getParametersByPathPaginator(request) response.iterator.asScala .flatMap { response => response.parameters.asScala } .flatMap { parameter => val name = parameter.name val value = parameter.value name.stripPrefix(prefix).split("/").toList match { case service :: account :: Nil => Some(CredentialKey(service, account) -> value) case other => log.warn(s"Unable to ingest credential at $name ($other)") None } } .toMap } catch { case NonFatal(t) => log.warn(s"Unable to build credentials map from SSM", t) throw t } } }