-
Notifications
You must be signed in to change notification settings - Fork 104
feat(auth): start storing apiSecret in auth and add tenant signature middleware
#3696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ Deploy Preview for brilliant-pasca-3e80ec canceled.
|
🚀 Performance Test ResultsTest Configuration:
Test Metrics:
📜 Logs |
|
|
||
| if (idpConsentUrl || idpSecret) { | ||
| await deps.authServiceClient.tenant.update(id, { | ||
| apiSecret, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is sort of tangential - dont think there is anything wrong here. But I dont think we're actually able to update tenants from the UI. Are we supposed to be able to?
As-is, it seems like the API secret is only visible to operators. For any tenant (self or non-operators). But its disabled if you're an operator (enabled if you're not, but you cant see it).
Im not really sure what the intended behavior is supposed to be but I dont see any scenario where you can update from the UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed this too. For the information that the auth service already stores, like the idp secret or consent screen URL, any updates are handled initially by the backend service, then propagated through to the auth service. So I think the apiSecret has this same dynamic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think its coming back to me... just saw this when trying to update via bruno:
"Operator cannot update apiSecret over admin api"
So working as intended I think.
But this begs the question, what happens if we set the env var secret to different things? I believe they would just be different (or perhaps backed would overwrite what auth does itself if it starts up later). Obviously people should not do that but not sure if there is really a graceful way to warn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it looks like the only possibility of updating the apiSecret is if the tenant calls the updateTenant mutation directly via the API, and not the UI. Do you think that is OK behaviour?
If so, then we can keep this as is, and just propagate the apiSecret like the other fields. I also changed the conditional to make sure we get the change across to auth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it looks like the only possibility of updating the apiSecret is if the tenant calls the updateTenant mutation directly via the API, and not the UI.
I was able to update in bruno (add in ui, get id, change senderTenantId and backendApiSignatureSecret in bruno config, change id in bruno's "Rafiki Admin API" > "Update tenant" request variables).
After I did, I tried to use the admin ui with the new credentials. I saw the and saw some unauthorized errors. Seems like there is an issue there.
I also saw the same thing when I hastily added in an input for the secret for non-operator tenants.
Do you think that is OK behaviour?
I would expect that they can change it from the UI, if they are allowed to change it at all. Which I think they should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
never mind on part of that, but there is something we need to fix if we add a form input for the api secret for non operators. I added one (and the schema validator), submitted, and got unauthorized error. it did update the secret but the browser session didnt seem to udpate. worked fine when i manually cleared and re-entered. There is code that looks like it should be setting on the session but something is wrong there.
Although its interesting that we have that code to update the session... because as-is the code only shows a disabled input for the api secret if you are the operator. You cant update if you are non-operator, nor see it. So the code to update the session on api secret change would just never run? I think we intended to let the non operator update at one point at least.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tested as well and yes, I also need to clear the credentials and re-set them manually in Admin UI before it works.
We can put that as an enhancement but I don't see it being something of high priority to fix.
BlairCurrey
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good w/ the caveat in my comment:
But this begs the question, what happens if we set the env var secret to different things? I believe they would just be different (or perhaps backed would overwrite what auth does itself if it starts up later). Obviously people should not do that but not sure if there is really a graceful way to warn.
Not sure if there is much we can do about that.
| test('Gets a tenant', async (): Promise<void> => { | ||
| const tenant = await Tenant.query().insert({ | ||
| id: v4(), | ||
| apiSecret: v4(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is missing an assertion that this value was retrieved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, do we need this get route in the first place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think so. Anything the auth service knows about the tenant is also known by the backend, which already exposes a way to get a tenant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will do some cleanup in another PR
| import * as crypto from 'crypto' | ||
| import Koa from 'koa' | ||
|
|
||
| function getSignatureParts(signature: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not relavant to whether or not this gets merged in but I feel as though we are reaching the point where signature verification should be a shared library between the Rafiki services
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, especially now with the cards & POS services
| let appContainer: TestContainer | ||
| let redis: Redis | ||
|
|
||
| describe('admin api signatures', (): void => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these tests don't appear to be replaced elsewhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it still test stuff like if the signature is too old to be processed or if it has already been processed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good catch. Adding old signature tests
This wouldn't really be the case but you could have different API secrets in auth & backend, and as long as you use the correct API key to call each of the APIs its OK |
Yes I think you are right. I was conflating the operator/tenant flows in my head but they are different. Operator cannot update apiSecret via admin api. They must use environment variables. They may be different and clients can simply use these separate secrets. Fine. Tenants can update apiSecret via the backend mutation. This propagates to the auth client. They are always the same. Fine. I was thinking of the scenario where they are set both from the environment variables and the admin api which propagates. But this case isn't possible since the environment variables are for the operator and the operator cannot be updated via the admin api. |
Changes proposed in this pull request
apiSecretto tenant table inauthapiSecretfrom env variable for operatorapiSecretfrombackendtoauthwhen creating new tenantsauthstartup, updateapiSecretif it has changedtableManagertests to properly handle tenant testsContext
Fixes #3692 | RAF-1191
Checklist
fixes #numberuser-docslabel (if necessary)