Skip to content
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

Secret replication #1775

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

akhilmhdh
Copy link
Member

Description 📣

  1. Implemented secret replication feature for import
  2. Resync feature to do manual resync

Type ✨

  • Bug fix
  • New feature
  • Breaking change
  • Documentation

Tests 🛠️

# Here's some code block to paste some code snippets

@akhilmhdh akhilmhdh added the 🚀 feature request New feature or request label May 2, 2024
@akhilmhdh akhilmhdh requested a review from maidul98 May 2, 2024 15:58
@akhilmhdh akhilmhdh self-assigned this May 2, 2024
DynamicSecretRevocation = "dynamic-secret-revocation"
DynamicSecretRevocation = "dynamic-secret-revocation",
SecretReplication = "secret-replication",
SecretSync = "secret-sync" // parent queue to push integration sync, webhook, and secret replication
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we update all direct calls of syncIntegration to use this secretSync queue instead?

Comment on lines +287 to +294
// check if user has permission to import from target path
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, {
environment: secretImportDoc.importEnv.slug,
secretPath: secretImportDoc.importPath
})
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait is this the same with checking if the user has sufficient permission to import from the source?

Comment on lines +12 to +39
const findSecrets = async (filter: { folderId: string; secrets: { id: string; version: number }[] }, tx?: Knex) => {
if (!filter.secrets) return [];

const sqlRawDocs = await (tx || db)(TableName.SecretVersion)
.where({ folderId: filter.folderId })
.andWhere((bd) => {
filter.secrets.forEach((el) => {
void bd.orWhere({
[`${TableName.SecretVersion}.secretId` as "secretId"]: el.id,
[`${TableName.SecretVersion}.version` as "version"]: el.version
});
});
})
.leftJoin<TSecretVersions>(
(tx || db)(TableName.SecretVersion)
.where("isReplicated", true)
.groupBy("secretId")
.max("version")
.select("secretId")
.as("latestVersion"),
`${TableName.SecretVersion}.secretId`,
"latestVersion.secretId"
)
.select(db.ref("max").withSchema("latestVersion").as("latestReplicatedVersion"))
.select(selectAllTableCols(TableName.SecretVersion));

return sqlRawDocs;
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fetches secret versions right? maybe let's rename the method?


const replicatedSecretsGroupBySecretId = groupBy(replicatedSecrets, (i) => i.secretId);
const lock = await keyStore.acquireLock(
replicatedSecrets.map(({ id }) => id),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this have some sort of a prefix so that the lock is specific for replication purposes?

Comment on lines +98 to +101
const hasJobCompleted = await keyStore.getItem(
keystoreReplicationSuccessKey(job.id as string, secretImport.id),
KeyStorePrefixes.SecretReplication
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! we can now add something like this to the integration sync flow

Comment on lines +339 to +341
queueService.listen(QueueName.SecretReplication, "failed", (job, err) => {
logger.error(err, "Failed to replicate secret", job?.data);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how are we informing users regarding failed replication jobs?

Comment on lines +97 to +117
const handleResyncSecretReplication = async () => {
if (resyncSecretReplication.isLoading) return;
try {
await resyncSecretReplication.mutateAsync({
id,
environment,
path: secretPath,
projectId: currentWorkspace?.id || ""
});
createNotification({
text: "Kindly refresh the board to see changes.",
type: "success"
});
} catch (error) {
console.error(error);
createNotification({
text: "Failed to resync replication",
type: "error"
});
}
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for this one, can we do the refetch behind the scenes instead of prompting to user to explicitly refresh?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🚀 feature request New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants