-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Root encrypted data to kms encryption #2827
base: main
Are you sure you want to change the base?
Conversation
|
GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
---|---|---|---|---|---|
14456465 | Triggered | Generic High Entropy Secret | a0c2fce | backend/src/ee/services/hsm/hsm-service.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
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.
Left some small comments. For manual testing i tried with:
- ladap config [good]
- dynamic secret with pg [seems to save and all but says the password is wrong?]
- secret rotation [seems to save and all but says the password is wrong?]
- webhooks [good]
Also what about integrations and are there any other items we are missing on this pass? What about the server admin slack secrets?
DB_USER: zpStr(z.string().describe("Postgres database username").optional()), | ||
DB_PASSWORD: zpStr(z.string().describe("Postgres database password").optional()), | ||
DB_NAME: zpStr(z.string().describe("Postgres database name").optional()), | ||
// TODO(akhilmhdh): will be changed to one |
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.
Q: change what?
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.
Comment from previous config. It means the Encryption key
and Root encryption key
will become one key
ENCRYPTION_KEY: zpStr(z.string().optional()), | ||
ROOT_ENCRYPTION_KEY: zpStr(z.string().optional()), | ||
// HSM | ||
HSM_LIB_PATH: zpStr(z.string().optional()), |
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.
let's say the hsm was set up for this instance but the user didn't pass in the hsm params, then what wil happen? I think we should check if this instance has hsm configured and tell them these are required
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 HSM service handles it already.
createdAt: z.date(), | ||
updatedAt: z.date(), | ||
groupSearchBase: z.string().default(""), | ||
groupSearchFilter: z.string().default(""), | ||
searchFilter: z.string().default(""), | ||
uniqueUserAttribute: z.string().default("") | ||
uniqueUserAttribute: z.string().default(""), | ||
encryptedLdapBindDN: zodBuffer, |
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.
nit: in the other auth methods, you don't refer to the auth method in the field but for this one you do. to keep it consistent, maybe omit the ldap for these fields?
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.
It's added because the field is already used. There exist a field encryptedBindDN
.
@@ -25,7 +27,9 @@ export const WebhooksSchema = z.object({ | |||
urlCipherText: z.string().nullable().optional(), | |||
urlIV: z.string().nullable().optional(), | |||
urlTag: z.string().nullable().optional(), | |||
type: z.string().default("general").nullable().optional() | |||
type: z.string().default("general").nullable().optional(), | |||
encryptedPassKey: zodBuffer.nullable().optional(), |
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.
nit: encryptedWebhookKey
@@ -187,7 +188,7 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => { | |||
caCert: z.string().trim().default("") | |||
}), | |||
response: { | |||
200: LdapConfigsSchema | |||
200: SanitizedLdapConfigSchema |
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.
nit: I assume this is to filter out and define ony what we want the response fields to be like? Why don't we start a pattern where we call the schema of a API response V1APINameResponseSchema
? This would be more clear
@@ -16,28 +15,14 @@ import { WebhookType } from "./webhook-types"; | |||
|
|||
const WEBHOOK_TRIGGER_TIMEOUT = 15 * 1000; | |||
|
|||
export const decryptWebhookDetails = (webhook: TWebhooks) => { | |||
const { keyEncoding, iv, encryptedSecretKey, tag, urlCipherText, urlIV, urlTag, url } = webhook; | |||
export const decryptWebhookDetails = (webhook: TWebhooks, decryptor: (value: Buffer) => 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.
why not make a instance of the decrypted here from kms service? i see you are passing on the decryptor function it self. could we pass on the decrypted data in here so we keep those things a little more isolated?
@@ -0,0 +1,19 @@ | |||
export const newRingBuffer = <T>(bufferSize = 10) => { |
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.
Nit: This isn't a real ring buffer and more of a key-value store. Maybe call it createCircularCache
await knex.schema.alterTable(TableName.Webhook, (t) => { | ||
if (!hasEncryptedKey) t.binary("encryptedPassKey"); | ||
if (!hasEncryptedUrl) t.binary("encryptedUrl"); | ||
if (hasUrl) t.string("url").nullable().alter(); |
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.
did you mean does not have url
? because url doesn't exist currently
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.
URL does exist in webhook
updatedWebhooks.slice(i, i + BATCH_SIZE).map((el) => ({ | ||
id: el.id, | ||
envId: el.envId, | ||
url: "", |
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.
why is url being set to empty?
type: KmsDataKey.SecretManager, | ||
projectId | ||
}); | ||
projectEncryptionRingBuffer.push(projectId, projectKmsService); |
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 the cache loops over then don't you lose the id to projectKmsService
and that would mean you may be encrypting the same project with one or more kms key?
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 we loose the entire thing. It would also means we cannot find it anymore with project id, so we load it to the cache again
Description 📣
This PR adds migration to remove all directly root encrypted schemas with our new kms architecture. This also allows migrations to use kms features.
All the unused fields are kept nullable and not dropped. Will be doing a rolling migration for this to remove it later.
Type ✨
Tests 🛠️
# Here's some code block to paste some code snippets