Skip to content

Instantly share code, notes, and snippets.

@maheshkelkar
Last active October 23, 2015 18:30
Show Gist options
  • Save maheshkelkar/878cf6bc15c4666573c5 to your computer and use it in GitHub Desktop.
Save maheshkelkar/878cf6bc15c4666573c5 to your computer and use it in GitHub Desktop.
Adding endpoint concept to keymaster
/******* Option-1: **********/
/**
* Keymaster Config:
*
* "keymaster" {
* "upstreamEndpoints" : {
* identityProvider" : {
* "hosts" : "localhost:8081", // CSV of servers
* "path" : "/identityProvider" // use this path upstream
* },
* "accessIssuer" : {
* "hosts" : "localhost:8081", // CSV of servers
* "path" : "/accessIssuer" // use this path upstream
* },
* "loginForm" : {
* "hosts" : "localhost:8081", // CSV of servers
* "path" : null // use actual url on upstream
* }
* },
* unauthenticatedEndpoints: [{ // all Methods
* "hosts" : "localhost:8081", // CSV of servers
* "path" : "/a/recover" // path to match on request
* }]
* }
*/
case class Endpoint(hosts: String, path: Option[Path])
case class KeymasterUpstreamEndpoints(identityProvider: Endpoint, accessIssuer: Endpoint, loginForm: Endpoint)
case class KeymasterConfig(upstreamEndpoints: KeymasterUpstreamEndpoints, unauthenticatedEndpoints: List[Endpoint])
// Top level Routing Service
// Keymaster specific
// Method.any -> /a/login => KeymasterMethodMuxLoginFilter andThen KeymasterIdpService
// Method.any -> /a/recover => EndpointService(endpoint) // This is direct access; a sort of opening a pinhole in our firewall
// Method.any -> _ => allOtherRequests
// How to instantiate "KeymasterMethodMuxLoginFilter"
// - IMO KeymasterMethodMuxLoginFilter we should limit this to "GET /a/login" => loginForm and "POST /a/login" => keymasterIdpService
KeymasterMethodMuxLoginFilter(keymasterConfig.upstreamEndpoints.loginForm) {
case Method.Get -> keymasterConfig.upstreamEndpoints.loginForm
case Method.post -> continue to KeymasterLoginFilter andThen KeymasterIdentityService
case _ => Request.NotFound
}
/******* Option-2: **********/
/**
* Keymaster Config:
*
* "keymaster" {
* "path" : "/a"
* "upstreamEndpoints" : {
* identityProvider" : {
* "hosts" : "localhost:8081", // CSV of servers
* "path" : "/a/login",
* "upstreamPath" : "/identityProvider" // use this path upstream
* },
* "accessIssuer" : {
* "hosts" : "localhost:8081", // CSV of servers
* "path" : null, // Not necessary
* "upstreamPath" : "/accessIssuer" // use this path upstream
* },
* "loginForm" : {
* "hosts" : "localhost:8081", // CSV of servers
* "path" : "/a/login" // use actual url on upstream
* "upstreamPath" : null // optional; but use this path upstream
* }
* },
* unauthenticatedEndpoints: [{ // all Methods
* "hosts" : "localhost:8081", // CSV of servers
* "path" : "/a/recover",
* "upstreamPath" : null // optional; but use this path upstream
* }]
* }
*/
case class Endpoint(hosts: String, path: Option[Path], upstreamPath: Option[Path])
case class KeymasterUpstreamEndpoints(identityProvider: Endpoint, accessIssuer: Endpoint, loginForm: Endpoint)
case class KeymasterConfig(path: Path, upstreamEndpoints: KeymasterUpstreamEndpoints, unauthenticatedEndpoints: List[Endpoint])
// Top level Routing Service
// Keymaster specific
// Method.any -> keymasterConfig.path / _ => KeymasterMethodMuxLoginFilter andThen KeymasterLoginService andThen KeymasterIdentityProvider
// Method.any -> _ => allOtherRequests
// How to instantiate "KeymasterMethodMuxLoginFilter"
KeymasterMethodMuxLoginFilter(keymasterConfig.upstreamEndpoints.loginForm) {
// We are assuming keymasterConfig.upstreamEndpoints.loginForm.path is same as keymasterConfig.upstreamEndpoints.identityProvider.path
case Method.Get -> keymasterConfig.upstreamEndpoints.path => Httpx.newClient(keymasterConfig.upstreamEndpoints.loginForm.hosts)(request)
case Method.Post -> keymasterConfig.upstreamEndpoints.loginForm.path => continue to KeymasterLoginFilter andThen KeymasterIdentityService
case _ -> keymasterConfig.upstreamEndpoints.loginForm.path => Request.BadRequest
case _ -> path in keymasterConfig.unauthenticatedEndpoints(x) => Httpx.newClient(x.hosts)(request)
case _ => Request.BadRequest
}
/******* Option-3: **********/
/**
* Keymaster Config:
*
* "keymaster" {
* "path" : "/a"
* identityProvider" : {
* "inputPath" : "/a/login",
* "upstreamHosts" : "localhost:8081", // CSV of servers
* "upstreamPath" : "/identityProvider" // use this path upstream
* },
* "accessIssuer" : {
* "inputPath" : null, // Not necessary
* "upstreamHosts" : "localhost:8081", // CSV of servers
* "upstreamPath" : "/accessIssuer" // use this path upstream
* },
* "routes" : [{
* "inputMethod" : "GET",
* "inputPath" : "/a/login",
* "upstreamHosts" : "localhost:8081", // CSV of servers
* "upstreamPath" : null // use inputPath as upstreamPath
* },{
* "inputMethod" : "*", // all paths
* "inputPath" : "/a/recover",
* "upstreamHosts" : "localhost:8081", // CSV of servers
* "upstreamPath" : null // use inputPath as upstreamPath
* }]
* }
*/
case class Route(inputMethod: Option[Method], inputPath: Option[Path], upstreamHosts: String, upstreamPath: Option[Path])
case class KeymasterConfig(path: Path, identityProvider: Route, accessIssuer: Route, routes: Route)
// Top level Routing Service
// Keymaster specific
// Method.any -> keymasterConfig.path / _ => KeymasterMethodMuxLoginFilter andThen KeymasterLoginService andThen KeymasterIdentityProvider
// Method.any -> _ => allOtherRequests
// How to instantiate "KeymasterMethodMuxLoginFilter"
KeymasterMethodMuxLoginFilter(keymasterConfig) {
val routeMap = keymasterConfig.routes.map(r => (r.method, r.path) -> r)
case Method.Post -> keymasterConfig.identityProvider.inputPath => continue to KeymasterLoginFilter andThen KeymasterIdentityService
routeMap(req.method, req.path) match {
case Some(r) => Httpx.newClient(r.upstreamHosts)(request)
case None => BadRequest
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment