diff --git a/src/config.js b/src/config.js index 854d3b2..692ff9e 100644 --- a/src/config.js +++ b/src/config.js @@ -1,13 +1,13 @@ export default { config }; var config = { - "pep_credentials" : "pep_credentials", + "pep_credentials": "pep_credentials", "debug": true, - "legacy": true, "accounting": { - "scopes": ["authorized_scope1", "authorizeed_scope2"], + "scopes": ["authorized_scope1", "authorizeed_scope2"], "service_name": "docker_stack_name", - "host": "service_hostname" + "service_class": "Application", + "host": "service_hostname" }, "hosts": [ { diff --git a/src/pep.js b/src/pep.js index 6e2561b..7d8dedc 100644 --- a/src/pep.js +++ b/src/pep.js @@ -1,5 +1,6 @@ -export default { enforce_legacy }; +export default { enforce_legacy, enforce }; +import qs from 'querystring'; import defaultExport from './config.js'; function log(c, s) { @@ -7,16 +8,20 @@ function log(c, s) { } var _debug = defaultExport["config"]["debug"] -var _debug = true +// var _debug = true njs.dump(_debug); function debug(c, s) { if (_debug === true) { - log(c, s) + log(c, "[DEBUG] " + s) } } +function error(c, s) { + c.request.error(s) +} + function enforce(r) { var context = { @@ -37,61 +42,72 @@ function enforce_legacy(r) { request: r, config: defaultExport["config"] } - - debug(context, JSON.stringify(context.config["accounting"], null, 2)); + log(context, "Inside enforce_legacy for " + r.method + " @ " + r.headersIn.host + "/" + r.uri) + debug(context, "Accounting config:\n" + JSON.stringify(context.config["accounting"], null, 2)); var allowedcontexts = context.config["accounting"]["scopes"] - log(context, "Inside NJS enforce for " + r.method + " @ " + r.headersIn.host + "/" + r.uri) - debug(context, "debug is " + JSON.stringify(defaultExport["config"])) + debug(context, "Allowed Contexts: " + JSON.stringify(allowedcontexts)); + + // debug(context, "PEP config:\n" + JSON.stringify(defaultExport["config"], null, 2)) const token = getGCubeToken(context) - debug(context, JSON.stringify(context, null, 2)) - debug(context, "gcube token" + token) + if (token != null) { - debug(context, "[PEP] token is " + token) + debug(context, "gcube-tone is " + token) exportVariable(context, "auth_token", token) context.request.subrequest("/_gcube_user_info") .then(reply => { if (reply.status === 200) { - debug(context, "[Social Service] got response " + reply.responseText) + debug(context, "[Social Service] response " + reply.responseText) // var response = JSON.parse(reply.responseBody); var response = JSON.parse(reply.responseText); if (allowedcontexts.indexOf(response.result.context) === -1) { - debug(context, "[PEP] Unathorized context " + response.result.context) + error(context, "[PEP] Unathorized context " + response.result.context) throw new Error("Unauthorized") } + log(context, "Authorization successful for " + response.result.username + " in " + response.result.context) return response } else { - log(context, "[Social Service] failed " + reply.status + ":" + reply.responseText) + error(context, "[Social Service] failed " + reply.status + ":" + reply.responseText) throw new Error("Unauthorized") } }).then(userinfo => { - debug(context, "[Social Service] username is " + userinfo.result.username) - debug(context, njs.dump(context)); + debug(context, "Authorizated user: " + userinfo.result.username) + // debug(context, "Context again:\n" + njs.dump(context)); context.userinfo = userinfo - context.record = buildAccountingRecord_legacy(context) - return context.request.subrequest("/_backend", { method: context.request.method, args: JSON.stringify(context.request.args), headers: context.request.headersIn }) + context.record = buildAccountingRecord_legacy(context); + + // if (context.config["stripLegacyToken"] == true) { + // var subreq_args = JSON.parse(JSON.stringify(context.request.args)); + // delete subreq_args["gcube-token"]; + // } else { + // var subreq_args = context.request.args; + // } + // debug(context, "subrequest args:\n" + JSON.stringify(subreq_args), null, 2); + return context.request.subrequest("/_backend", { method: context.request.method, args: qs.stringify(context.request.args), headers: context.request.headersIn }) }).then(reply => { - debug(context, reply.responseText); - debug(context, "[SHINYPROXY] response status: " + reply.status) + // debug(context, "response from backend\n" + reply.responseText); + debug(context, "Response status from backend: " + reply.status) copyHeaders(context, reply.headersOut, r.headersOut) closeAccountingRecord_legacy(context.record, (reply.status === 200 || reply.status === 201 || reply.status === 204)) context.request.subrequest("/_accounting_legacy", { detached: true, body: JSON.stringify([context.record]) }) // r.return(reply.status, reply.responseBody) - debug(context, "Redirect URI: " + reply.headersOut["Location"]) - if(reply.status === 301 || reply.status === 302){ - debug(context, "sto per fare la redirect"); - r.return(reply.status, reply.headersOut["Location"]) - }else{ + log(context, "Accounting record sent:\n" + JSON.stringify(context.record, null, 2)) + debug(context, "Redirect URI: https://" + r.headersIn.host + reply.headersOut["Location"]) + if (reply.status === 301 || reply.status === 302) { + debug(context, "Redirecting..."); + r.return(reply.status, "https://" + r.headersIn.host + reply.headersOut["Location"]) + } else { r.return(reply.status, reply.responseText) - } - }).catch(e => { log(context, "Error .... " + njs.dump(e)); context.request.return(e.message === "Unauthorized" ? 403 : 500) }) + } + }).catch(e => { error(context, "Error .... " + njs.dump(e)); context.request.return(e.message === "Unauthorized" ? 403 : 500) }) return } + error(context, "No token provided: Unauthorized.") r.return(401, "Authorization required") } -function copyHeaders(context, hin, hout){ +function copyHeaders(context, hin, hout) { for (var h in hin) { - if(h !== "Location") hout[h] = hin[h]; + if (h !== "Location") hout[h] = hin[h]; } } @@ -344,7 +360,7 @@ function respondToClient(context) { for (let k in context.backendresponse.headersOut) { context.request.headersOut[k] = context.backendresponse.headersOut[k] } - context.request.return(context.backendresponse.status, context.backendresponse.responseText) + context.request.return(context.backendresponse.status, context.backendresponse.responseBuffer) return context } @@ -453,11 +469,11 @@ function buildAccountingRecord(context) { "callerQualifier": "TOKEN", "consumerId": getTokenField(context, "preferred_username"), "aggregated": true, - "serviceName": defaultExport["accounting"]["service_name"], + "serviceName": context.config["accounting"]["service_name"], "duration": 0, "maxInvocationTime": 0, - "scope": defaultExport["accounting"]["scopes"][0], // qui va cambiato per capire quale è lo scope corretto dell'utente, al momento viene preso il primo - "host": defaultExport["accounting"]["host"], + "scope": context.config["accounting"]["scopes"][0], // qui va cambiato per capire quale è lo scope corretto dell'utente, al momento viene preso il primo + "host": context.config["accounting"]["host"], "startTime": t, "id": uuid(), "calledMethod": context.request.method + " " + context.request.uri, @@ -503,15 +519,15 @@ function buildAccountingRecord_legacy(context) { "recordType": "ServiceUsageRecord", "operationCount": 1, "creationTime": t, - "callerHost": context.request.remoteAddress, - "serviceClass": "ShinyApp", + "callerHost": context.request.headersIn["x-forwarded-for"], + "serviceClass": context.config["accounting"]["service_class"], "callerQualifier": "TOKEN", - "consumerId": context.userinfo.username, + "consumerId": context.userinfo.result.username, "aggregated": true, - "serviceName": context.request.uri.split("app/")[1], + "serviceName": context.config["accounting"]["service_name"], "duration": 0, "maxInvocationTime": 0, - "scope": context.userinfo.context, + "scope": context.userinfo.result.context, "host": context.request.headersIn.host, "startTime": t, "id": uuid(),