-
Notifications
You must be signed in to change notification settings - Fork 535
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
Adds support for hidden private keys in server tenants #23379
base: main
Are you sure you want to change the base?
Conversation
…to vermadhr/keylessAccessWork
server/routerlicious/packages/routerlicious-base/src/riddler/api.ts
Outdated
Show resolved
Hide resolved
@@ -142,11 +161,15 @@ export function create( | |||
const tenantCustomData: ITenantCustomData = request.body.customData | |||
? request.body.customData | |||
: {}; | |||
const enableKeylessAccess = request.body.enableKeylessAccess | |||
? request.body.enableKeylessAccess | |||
: null; | |||
const tenantP = manager.createTenant( |
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 method should also have "enableKeyAcess". Both "enableKeylessAcess" and "enableKeyAcess" can be true, either of them can be true. If both of them are false, then it is an error condition.
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 do not think we need another flag - enableKeyAccess
. Access via keys will continue to work even if enableKeylessAccess
is set to true.
server/routerlicious/packages/routerlicious-base/src/riddler/api.ts
Outdated
Show resolved
Hide resolved
const enableKeylessAccess = request.body.enableKeylessAccess | ||
? request.body.enableKeylessAccess | ||
: null; | ||
const storageP = manager.updateKeylessAccessPolicy(tenantId, enableKeylessAccess); |
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.
We should be able to update both enableKeylessAccess and enableKeyAccess. Ensure that both cannot be set to false.
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.
Ahh okay got it. So in case both are true, then we will have (key, secondaryKey)
and privateKeys
present for the tenant. In case only enableKeyAccess
is true, then we would only have (key, secondaryKey)
present. In case only enableKeylessAccess
is true, then we would only have privateKeys
present for the tenant. Is my understanding correct?
@@ -128,7 +146,8 @@ export function create( | |||
router.put("/tenants/:id/key", (request, response) => { | |||
const tenantId = request.params.id; | |||
const keyName = request.body.keyName as string; | |||
const refreshKeyP = manager.refreshTenantKey(tenantId, keyName); | |||
const refreshPrivateKey = request.body.refreshPrivateKey as boolean; |
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.
Ensure that the tenant cannot send us a request to "refreshPrivateKey".
"refreshPrivateKey" should be exposed only to internal APIs and not exposed to the 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.
Yes, the /tenants/:id/key
API with refreshPrivateKey
as true
would only be called by internal APIs that will refresh the private tenant keys periodically.
@@ -57,6 +60,9 @@ export interface ITenantDocument { | |||
// Timestamp of when this tenant will be hard deleted. | |||
// Only applicable if the tenant is disabled. | |||
scheduledDeletionTime?: string; | |||
|
|||
// Optional private keys, used for keyless tenants |
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.
Even (key, secondaryKey) can be optional. However, both (key, secondaryKey) and ITenantPrivateKeys cannot be optional. Only one can be at a given time.
@@ -261,6 +278,7 @@ export class TenantManager { | |||
storage: tenant.storage, | |||
customData: tenant.customData, | |||
scheduledDeletionTime: tenant.scheduledDeletionTime, | |||
enableKeylessAccess: tenant.privateKeys ? true : false, |
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 it should have another property "enableKeyAccess".
@@ -276,9 +294,55 @@ export class TenantManager { | |||
storage: tenant.storage, | |||
customData: tenant.customData, | |||
scheduledDeletionTime: tenant.scheduledDeletionTime, | |||
enableKeylessAccess: tenant.privateKeys ? true : false, |
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 should also have the property "enableKeyAccess"
@@ -287,6 +351,7 @@ export class TenantManager { | |||
storage: ITenantStorage, | |||
orderer: ITenantOrderer, | |||
customData: ITenantCustomData, | |||
enableKeylessAccess = false, | |||
): Promise<ITenantConfig & { key: string }> { | |||
const latestKeyVersion = this.secretManager.getLatestKeyVersion(); | |||
|
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.
The function above could be called "createTenantKeys" and it could be called twice. Once for non-private keys and once for private keys. Lines 358 to 376 would not be required.
const latestKeyVersion = this.secretManager.getLatestKeyVersion(); | ||
let privateKeys: ITenantPrivateKeys | undefined; | ||
// If the tenant is being converted to a keyless tenant, generate new private keys, otherwise update them to be undefined | ||
if (enableKeylessAccess) { |
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.
If enableKeylessAccess is false, should we remove it? Check Azure Store or Redis if they allow to reset keylessAcceess, once it has been enabled.
If enableKeylessAccess is true, and it was already true in tenantMetadata, should we just ignore and return success for this operation.
Description
This PR adds support for storing private keys in the tenants DB collection. These private keys will be used to sign tokens that are acquired for keyless access. These are never shared with the client and will be rotated based on their rotation schedule. It also adds a new claim in the fluid access token -
fluidRelayKeylessAccess
. This claim will be used to determine how to validate the access token - with the shared keys or the private keys. This allows to keep access tokens to be backward compatible while also supporting keyless access. It does introduce some new APIs and modifies existing APIs:/tenants/:id/keys
: Adds a new query parameter -getPrivateKeys
. When set totrue
, it returns the privateKeys for the tenant. By default, this flag is set to false./tenants/:id/keylessAccess
: Toggles theenableKeylessAccess
flag for a tenant./tenants/:id/key
: Refreshes the requested tenant key. WhenrefreshPrivateKey
istrue
it will refresh the private keys but does not return the refreshed keys. This is because key refreshes of the private keys will not be exposed to clients./tenants/:id?
: Creates a fluid tenant. This request accepts a new parameter in the body -enableKeylessAccess
. When this is set to true, a tenant with support for private keys will be created. By default, this is false.To support these, the following changes are done:
ITenantPrivateKeys
. The workflows essentially are the same as before but they include some new flags which helps riddler determine what keys to get/refresh/use for validation. The changes also include creating different caching keys for shared and private keys.fluidRelayKeylessAccess
which will be set totrue
when generating a keyless access token.tenantManager.ts
. This ensures the existing APIs work as before. It also tests the new functionality. To further test these changes, I ran the server locally using Docker.Breaking Changes
This adds a bunch of functionalities to support private hidden keys. However, these should not break existing changes.
Reviewer Guidance
getTenantKeys
rather than creating new interfaces.