auth middleware: no print secret (#11050)

At the moment, the OAuth2 Middleware prints its config at startup.
Unfortunately that config includes a secret, which presumably we'd
prefer not to show.

CHANGELOG_BEGIN
- The OAuth2 Middleware now obfuscates its Client Secret when logging
  its config.
CHANGELOG_END
This commit is contained in:
Gary Verhaegen 2021-09-28 17:00:01 +02:00 committed by GitHub
parent a885f52c4d
commit 9641fd5f83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 26 additions and 22 deletions

View File

@ -32,11 +32,15 @@ case class Config(
oauthRefreshTemplate: Option[Path],
// OAuth2 client properties
clientId: String,
clientSecret: String,
clientSecret: SecretString,
// Token verification
tokenVerifier: JwtVerifierBase,
)
case class SecretString(value: String) {
override def toString: String = "###"
}
object Config {
val DefaultHttpPort: Int = 3000
val DefaultCookieSecure: Boolean = true
@ -134,7 +138,7 @@ object Config {
opt[String]("secret")
.hidden()
.action((x, c) => c.copy(clientSecret = x))
.action((x, c) => c.copy(clientSecret = SecretString(x)))
.withFallback(() => sys.env.getOrElse("DAML_CLIENT_SECRET", ""))
.validate(x =>
if (x.isEmpty) failure("Environment variable DAML_CLIENT_SECRET must not be empty")

View File

@ -18,7 +18,7 @@ import scala.util.Try
private[oauth2] class RequestTemplates(
clientId: String,
clientSecret: String,
clientSecret: SecretString,
authTemplate: Option[Path],
tokenTemplate: Option[Path],
refreshTemplate: Option[Path],
@ -99,6 +99,11 @@ private[oauth2] class RequestTemplates(
interpretJsonnet(jsonnet_src, jsonnet_path, args).flatMap(toRequestParams)
}
private lazy val config: ujson.Value = ujson.Obj(
"clientId" -> clientId,
"clientSecret" -> clientSecret.value,
)
private lazy val authJsonnetSource: (String, sjsonnet.Path) =
jsonnetSource(authTemplate, authResourcePath)
private def authArguments(
@ -107,10 +112,7 @@ private[oauth2] class RequestTemplates(
redirectUri: Uri,
): Map[String, ujson.Value] =
Map(
"config" -> ujson.Obj(
"clientId" -> clientId,
"clientSecret" -> clientSecret,
),
"config" -> config,
"request" -> ujson.Obj(
"claims" -> ujson.Obj(
"admin" -> claims.admin,
@ -136,10 +138,7 @@ private[oauth2] class RequestTemplates(
private lazy val tokenJsonnetSource: (String, sjsonnet.Path) =
jsonnetSource(tokenTemplate, tokenResourcePath)
private def tokenArguments(code: String, redirectUri: Uri): Map[String, ujson.Value] = Map(
"config" -> ujson.Obj(
"clientId" -> clientId,
"clientSecret" -> clientSecret,
),
"config" -> config,
"request" -> ujson.Obj(
"code" -> code,
"redirectUri" -> redirectUri.toString,
@ -151,10 +150,7 @@ private[oauth2] class RequestTemplates(
private lazy val refreshJsonnetSource: (String, sjsonnet.Path) =
jsonnetSource(refreshTemplate, refreshResourcePath)
private def refreshArguments(refreshToken: RefreshToken): Map[String, ujson.Value] = Map(
"config" -> ujson.Obj(
"clientId" -> clientId,
"clientSecret" -> clientSecret,
),
"config" -> config,
"request" -> ujson.Obj(
"refreshToken" -> RefreshToken.unwrap(refreshToken)
),
@ -168,7 +164,7 @@ object RequestTemplates {
def apply(
clientId: String,
clientSecret: String,
clientSecret: SecretString,
authTemplate: Option[Path],
tokenTemplate: Option[Path],
refreshTemplate: Option[Path],

View File

@ -107,7 +107,7 @@ trait TestFixture
oauthTokenTemplate = None,
oauthRefreshTemplate = None,
clientId = "middleware",
clientSecret = "middleware-secret",
clientSecret = SecretString("middleware-secret"),
tokenVerifier = new JwtVerifier(
JWT
.require(Algorithm.HMAC256(jwtSecret))

View File

@ -22,7 +22,7 @@ class TestRequestTemplates
with TryValues
with PartialFunctionValues {
private val clientId = "client-id"
private val clientSecret = "client-secret"
private val clientSecret = SecretString("client-secret")
private def getTemplates(
authTemplate: Option[Path] = None,
@ -191,7 +191,7 @@ class TestRequestTemplates
val params = templates.createTokenRequest(code, redirectUri).success.value
params shouldBe Map(
"client_id" -> clientId,
"client_secret" -> clientSecret,
"client_secret" -> clientSecret.value,
"code" -> code,
"grant_type" -> "authorization_code",
"redirect_uri" -> redirectUri.toString,
@ -205,7 +205,7 @@ class TestRequestTemplates
val params = templates.createRefreshRequest(refreshToken).success.value
params shouldBe Map(
"client_id" -> clientId,
"client_secret" -> clientSecret,
"client_secret" -> clientSecret.value,
"grant_type" -> "refresh_code",
"refresh_token" -> refreshToken,
)

View File

@ -19,7 +19,11 @@ import com.auth0.jwt.JWTVerifier.BaseVerification
import com.auth0.jwt.algorithms.Algorithm
import com.auth0.jwt.interfaces.{Clock => Auth0Clock}
import com.daml.auth.middleware.api.{Client => AuthClient}
import com.daml.auth.middleware.oauth2.{Config => MiddlewareConfig, Server => MiddlewareServer}
import com.daml.auth.middleware.oauth2.{
Config => MiddlewareConfig,
Server => MiddlewareServer,
SecretString,
}
import com.daml.auth.oauth2.test.server.{Config => OAuthConfig, Server => OAuthServer}
import com.daml.bazeltools.BazelRunfiles
import com.daml.clock.AdjustableClock
@ -225,7 +229,7 @@ trait AuthMiddlewareFixture
oauthTokenTemplate = None,
oauthRefreshTemplate = None,
clientId = "oauth-middleware-id",
clientSecret = "oauth-middleware-secret",
clientSecret = SecretString("oauth-middleware-secret"),
tokenVerifier = authVerifier,
)
middleware <- Resource(MiddlewareServer.start(middlewareConfig))(closeServerBinding)