review fixes

This commit is contained in:
x032205
2025-05-12 16:42:48 -04:00
parent 0b4675e7b5
commit c3c907788a
5 changed files with 123 additions and 46 deletions

View File

@@ -0,0 +1,26 @@
// Code generated by automation script, DO NOT EDIT.
// Automated by pulling database and generating zod schema
// To update. Just run npm run generate:schema
// Written by akhilmhdh.
import { z } from "zod";
import { TImmutableDBKeys } from "./models";
export const IdentityOciAuthsSchema = z.object({
id: z.string().uuid(),
accessTokenTTL: z.coerce.number().default(7200),
accessTokenMaxTTL: z.coerce.number().default(7200),
accessTokenNumUsesLimit: z.coerce.number().default(0),
accessTokenTrustedIps: z.unknown(),
createdAt: z.date(),
updatedAt: z.date(),
identityId: z.string().uuid(),
type: z.string(),
tenancyOcid: z.string(),
allowedUsernames: z.string().nullable().optional()
});
export type TIdentityOciAuths = z.infer<typeof IdentityOciAuthsSchema>;
export type TIdentityOciAuthsInsert = Omit<z.input<typeof IdentityOciAuthsSchema>, TImmutableDBKeys>;
export type TIdentityOciAuthsUpdate = Partial<Omit<z.input<typeof IdentityOciAuthsSchema>, TImmutableDBKeys>>;

View File

@@ -117,18 +117,19 @@ export const listOCIVaults = async (appConnection: TOCIConnection, compartmentOc
export const listOCIVaultKeys = async (appConnection: TOCIConnection, compartmentOcid: string, vaultOcid: string) => {
const provider = await getOCIProvider(appConnection);
const vaultIdMatch = vaultOcid.match(/ocid1\.vault\.[^.]+\.[^.]+\.([^.]+)/);
if (!vaultIdMatch || !vaultIdMatch[1]) {
throw new BadRequestError({
message: "Invalid vault OCID format"
});
}
const kmsVaultClient = new keymanagement.KmsVaultClient({
authenticationDetailsProvider: provider
});
const vault = await kmsVaultClient.getVault({
vaultId: vaultOcid
});
const keyManagementClient = new keymanagement.KmsManagementClient({
authenticationDetailsProvider: provider
});
keyManagementClient.endpoint = `https://${vaultIdMatch[1].replace(/[^a-zA-Z0-9]/g, "")}-management.kms.${appConnection.credentials.region}.oraclecloud.com`;
keyManagementClient.endpoint = vault.vault.managementEndpoint;
const keys = await keyManagementClient.listKeys({
compartmentId: compartmentOcid

View File

@@ -1,5 +1,6 @@
import { secrets, vault } from "oci-sdk";
import { delay } from "@app/lib/delay";
import { getOCIProvider } from "@app/services/app-connection/oci";
import {
TCreateOCIVaultVariable,
@@ -121,11 +122,28 @@ export const OCIVaultSyncFns = {
const provider = await getOCIProvider(connection);
const variables = await listOCIVaultVariables({ provider, compartmentId: compartmentOcid, vaultId: vaultOcid });
// Throw an error if any keys are updating in OCI vault to prevent skipped updates
if (
Object.entries(variables).some(
([, secret]) =>
secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Updating ||
secret.lifecycleState === vault.models.SecretSummary.LifecycleState.CancellingDeletion ||
secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Creating ||
secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Deleting ||
secret.lifecycleState === vault.models.SecretSummary.LifecycleState.SchedulingDeletion
)
) {
throw new SecretSyncError({
error: "Cannot sync while keys are updating in OCI Vault."
});
}
// Create secrets
for await (const entry of Object.entries(secretMap)) {
const [key, { value }] = entry;
const existingVariable = Object.values(variables).find((v) => v.secretName === key);
if (!Object.values(variables).some((v) => v.secretName === key)) {
if (!existingVariable) {
try {
await createOCIVaultVariable({
compartmentId: compartmentOcid,
@@ -141,27 +159,45 @@ export const OCIVaultSyncFns = {
secretKey: key
});
}
} else {
} else if (existingVariable.lifecycleState === vault.models.SecretSummary.LifecycleState.PendingDeletion) {
// If a secret exists but is pending deletion, cancel the deletion and update the secret
const secretPendingDeletion = Object.values(variables).find(
(s) => s.secretName === key && s.lifecycleState === vault.models.SecretSummary.LifecycleState.PendingDeletion
);
await unmarkOCIVaultVariableFromDeletion({
provider,
compartmentId: compartmentOcid,
vaultId: vaultOcid,
secretId: existingVariable.id
});
if (secretPendingDeletion) {
await unmarkOCIVaultVariableFromDeletion({
provider,
compartmentId: compartmentOcid,
vaultId: vaultOcid,
secretId: secretPendingDeletion.id
const vaultsClient = new vault.VaultsClient({ authenticationDetailsProvider: provider });
const MAX_RETRIES = 10;
for (let i = 0; i < MAX_RETRIES; i += 1) {
// eslint-disable-next-line no-await-in-loop
await delay(5000);
// eslint-disable-next-line no-await-in-loop
const secret = await vaultsClient.getSecret({
secretId: existingVariable.id
});
await updateOCIVaultVariable({
provider,
compartmentId: compartmentOcid,
vaultId: vaultOcid,
secretId: secretPendingDeletion.id,
value
});
if (secret.secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Active) {
// eslint-disable-next-line no-await-in-loop
await updateOCIVaultVariable({
provider,
compartmentId: compartmentOcid,
vaultId: vaultOcid,
secretId: existingVariable.id,
value
});
break;
}
if (i === MAX_RETRIES - 1) {
throw new SecretSyncError({
error: "Failed to update secret after cancelling deletion.",
secretKey: key
});
}
}
}
}

View File

@@ -157,3 +157,21 @@ description: "Learn how to configure an Oracle Cloud Infrastructure Vault Sync f
```
</Tab>
</Tabs>
## FAQ
<AccordionGroup>
<Accordion title="How are non-active lifecycle states treated?">
When Infisical attempts to sync secrets, the sync will fail and attempt to re-sync if **any secret** has one of the following lifecycle states:
- SchedulingDeletion
- CancellingDeletion
- Deleting
- Creating
- Updating
We do this to prevent any desync issues.
</Accordion>
<Accordion title="What happens if I create / update a variable that's scheduled for deletion in OCI Vault?">
In the case that a variable is created or updated while it's scheduled for deletion in OCI Vault, we cancel the deletion and update the variable. This action may take up to a minute since Infisical must wait for OCI to completely cancel the deletion and then update the variable.
</Accordion>
</AccordionGroup>

View File

@@ -1,37 +1,33 @@
import { faHome } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
createFileRoute,
linkOptions,
stripSearchParams,
} from '@tanstack/react-router'
import { zodValidator } from '@tanstack/zod-adapter'
import { z } from 'zod'
import { faHome } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createFileRoute, linkOptions, stripSearchParams } from "@tanstack/react-router";
import { zodValidator } from "@tanstack/zod-adapter";
import { z } from "zod";
import { SettingsPage } from './SettingsPage'
import { SettingsPage } from "./SettingsPage";
const SettingsPageQueryParams = z.object({
selectedTab: z.string().catch(''),
})
selectedTab: z.string().catch("")
});
export const Route = createFileRoute(
'/_authenticate/_inject-org-details/_org-layout/organization/settings/',
"/_authenticate/_inject-org-details/_org-layout/organization/settings/"
)({
component: SettingsPage,
validateSearch: zodValidator(SettingsPageQueryParams),
search: {
middlewares: [stripSearchParams({ selectedTab: '' })],
middlewares: [stripSearchParams({ selectedTab: "" })]
},
context: () => ({
breadcrumbs: [
{
label: 'Home',
label: "Home",
icon: () => <FontAwesomeIcon icon={faHome} />,
link: linkOptions({ to: '/' }),
link: linkOptions({ to: "/" })
},
{
label: 'Settings',
},
],
}),
})
label: "Settings"
}
]
})
});