ucd-library / fin

FIN (Fedora IN docker) Base Services
MIT License
0 stars 0 forks source link

Transform Service Not Propagateing user credentials and/or dbsync "discovery" #80

Open qjhart opened 5 months ago

qjhart commented 5 months ago

Direct transform service request

If I'm logged in as an elevated user, I can get a resource, but not the transformed resource; eg:

http --headers get  http://localhost/fcrepo/rest/expert/51d37fccfdb86059c507a75b46cb0f66 Authorization:"Bearer $jwt" | grep ^HTTP
#HTTP/1.1 200 OK

But

http --headers get  http://localhost/fcrepo/rest/expert/51d37fccfdb86059c507a75b46cb0f66/svc:node Authorization:"Bearer $jwt" | grep ^HTT
#HTTP/1.1 500 Internal Server Error

The response is:

{
    "details": {
        "message": "403 <!doctype html><html lang=\"en\"><head><title>HTTP Status 403 – Forbidden</title><style type=\"text/css\">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 403 – Forbidden</h1><hr class=\"line\" /><p><b>Type</b> Status Report</p><p><b>Description</b> The server understood the request but refuses to authorize it.</p><hr class=\"line\" /><h3>Apache Tomcat/9.0.65</h3></body></html>",
        "stack": "Error: 403 <!doctype html><html lang=\"en\"><head><title>HTTP Status 403 – Forbidden</title><style type=\"text/css\">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 403 – Forbidden</h1><hr class=\"line\" /><p><b>Type</b> Status Report</p><p><b>Description</b> The server understood the request but refuses to authorize it.</p><hr class=\"line\" /><h3>Apache Tomcat/9.0.65</h3></body></html>\n    at TransformService.exec (/fin/services/gateway/models/transform.js:659:15)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at async parsed (/fin/services/gateway/models/service-proxy/transform-service.js:24:23)"
    },
    "error": true,
    "message": "Unable to render from transform service node"
}

This Error is thrown here:

https://github.com/ucd-library/fin/blob/8e73bfa637398d21db336da9186e444ecfbc332e/services/fin/gateway/models/transform.js#L657

Where I don't see the original request's either directAccess or jwt token being propogated.

Default Model

The model code for dbsync has similar problems. However, there may be an additional problem in the model as well. Here, I don't see how dbsync propagates a (What I would guess to be a direct access as discovery) request to the transform service.

https://github.com/ucd-library/fin/blob/8e73bfa637398d21db336da9186e444ecfbc332e/services/fin/dbsync/lib/model.js#L512

qjhart commented 5 months ago

From @jrmerz How about this, we allow admins to override their roles with a header. so if the JWT token is authenticated and has role admin AND there is a fin-principal header, (ex: fin-principal: foo, bar ) then the request to fcrepo will ONLY have the supplied principles. This would allow admins in impersonate users for testing as well.

3114e79a0f0f5d878b426f250ea50fef746ff9dc

You need to make sure the finPrinciples array includes fedoraUser... Forgot to do that.

Then update the DB sync get container function to use the service account token (see the keycloak module) and set the fin-principle header to discover

qjhart commented 5 months ago

@jrmerz I have been testing sandbox, and this is still not working. In short, dbsync calls transform services, and these services are calling the underlying fcrepo setup as public.

Here's the long description:

The gateway proxy divides fcrepo requests into proxyRequests or middleware.

Dbsync calls a transform service, so it goes to the middleware, to the transformService to the renderTransform which execs the transform.

But here, we are calling a simple api.get(options) to fetch the fcrepo data.

I'm not sure how you think best to solve this. I can see that for (some) middleware, all the way back in the proxy, it makes sense to call the normal proxyRequest, get the container, and then call the transform. Alternatively, you could propogate the original request to that api.get request, the issue there is that request has already been run through the gateway, so I'm not sure if at that point you want to make a direct request, or just start the whole process over, and if the latter, do you just forward the fin-principal and Authorization, or a larger header set?

Examples:

This works, since we've set the principal

http http://localhost/fcrepo/rest/expert/66356b7eec24c51f01e757af2b27ebb8 Authorization:"Bearer $jwt" fin-principal:discover

This sets the principal to an unallowed user, and properly fails

http http://localhost/fcrepo/rest/expert/66356b7eec24c51f01e757af2b27ebb8 Authorization:"Bearer $jwt" fin-principal:foo

This should work, but also fails, since the service makes a public request.

http http://localhost/fcrepo/rest/expert/66356b7eec24c51f01e757af2b27ebb8/svc:node Authorization:"Bearer $jwt" fin-principal:discover