Skip to content

Commit

Permalink
refactor: misc fixes for creating new apps, keyring and example secre…
Browse files Browse the repository at this point in the history
…ts (#86)

* fix: ensure keyring is present to create example secrets

* fix: return the env seed and salt specific to the user making the query

* fix: misc fixes to env initialization and starter secrets
  • Loading branch information
rohan-chaturvedi authored Oct 17, 2023
1 parent 883fbdc commit 575f07a
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 46 deletions.
16 changes: 16 additions & 0 deletions backend/backend/graphene/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,22 @@ class Meta:
fields = ('id', 'name', 'env_type', 'identity_key',
'wrapped_seed', 'wrapped_salt', 'created_at', 'updated_at')

def resolve_wrapped_seed(self, info):
org_member = OrganisationMember.objects.get(
user=info.context.user, organisation=self.app.organisation, deleted_at=None)
user_env_key = EnvironmentKey.objects.get(
environment=self, user=org_member, deleted_at=None)

return user_env_key.wrapped_seed

def resolve_wrapped_salt(self, info):
org_member = OrganisationMember.objects.get(
user=info.context.user, organisation=self.app.organisation, deleted_at=None)
user_env_key = EnvironmentKey.objects.get(
environment=self, user=org_member, deleted_at=None)

return user_env_key.wrapped_salt


class EnvironmentKeyType(DjangoObjectType):
class Meta:
Expand Down
132 changes: 86 additions & 46 deletions frontend/components/apps/NewAppDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,20 +121,23 @@ export default function NewAppDialog(props: {
})
}

async function processSecrets(
appId: string,
envType: ApiEnvironmentEnvTypeChoices,
secrets: Array<Partial<SecretType>>
) {
const { data: appEnvsData } = await getAppEnvs({ variables: { appId } })
/**
* Encrypts a set of secrets for the given env and creates them server-side
*
* @param {EnvironmentType} env - The environment in which the secrets will be created.
* @param {Array<Partial<SecretType>>} secrets - An array of secrets to be processed.
* @returns {Promise<void>} A Promise that resolves when the all secrets are encrypted and stored on the server.
*
* @throws {Error} If the specified environment is invalid or if an error occurs during processing.
*/
async function processSecrets(env: EnvironmentType, secrets: Array<Partial<SecretType>>) {
const keyring = await validateKeyring(pw)

const userKxKeys = {
publicKey: await getUserKxPublicKey(keyring!.publicKey),
privateKey: await getUserKxPrivateKey(keyring!.privateKey),
publicKey: await getUserKxPublicKey(keyring.publicKey),
privateKey: await getUserKxPrivateKey(keyring.privateKey),
}

const env = appEnvsData.appEnvironments.find((env: EnvironmentType) => env.envType === envType)

const envSalt = await decryptAsymmetric(
env.wrappedSalt,
userKxKeys.privateKey,
Expand Down Expand Up @@ -167,6 +170,12 @@ export default function NewAppDialog(props: {
return Promise.all(promises)
}

/**
* Handles the creation of example secrets for a given app. Defines the set of example secrets, fetches all envs for this app and handles creation of each set of secrets with the respective envs
*
* @param {string} appId
* @returns {Promise<void>}
*/
const createExampleSecrets = async (appId: string) => {
const DEV_SECRETS = [
{
Expand Down Expand Up @@ -253,47 +262,72 @@ export default function NewAppDialog(props: {
},
]

await processSecrets(appId, ApiEnvironmentEnvTypeChoices.Dev, DEV_SECRETS)
await processSecrets(appId, ApiEnvironmentEnvTypeChoices.Staging, STAG_SECRETS)
await processSecrets(appId, ApiEnvironmentEnvTypeChoices.Prod, PROD_SECRETS)
}
const { data: appEnvsData } = await getAppEnvs({ variables: { appId } })

const initAppEnvs = async (appId: string) => {
const mutationPayload = {
devEnv: await createNewEnv(
appId,
'Development',
ApiEnvironmentEnvTypeChoices.Dev,
orgAdminsData.organisationAdminsAndSelf
await processSecrets(
appEnvsData.appEnvironments.find(
(env: EnvironmentType) => env.envType === ApiEnvironmentEnvTypeChoices.Dev
),
stagingEnv: await createNewEnv(
appId,
'Staging',
ApiEnvironmentEnvTypeChoices.Staging,
orgAdminsData.organisationAdminsAndSelf
DEV_SECRETS
)
await processSecrets(
appEnvsData.appEnvironments.find(
(env: EnvironmentType) => env.envType === ApiEnvironmentEnvTypeChoices.Staging
),
prodEnv: await createNewEnv(
appId,
'Production',
ApiEnvironmentEnvTypeChoices.Prod,
orgAdminsData.organisationAdminsAndSelf
STAG_SECRETS
)
await processSecrets(
appEnvsData.appEnvironments.find(
(env: EnvironmentType) => env.envType === ApiEnvironmentEnvTypeChoices.Prod
),
}
PROD_SECRETS
)
}

await initAppEnvironments({
variables: {
devEnv: mutationPayload.devEnv.createEnvPayload,
stagingEnv: mutationPayload.stagingEnv.createEnvPayload,
prodEnv: mutationPayload.prodEnv.createEnvPayload,
devAdminKeys: mutationPayload.devEnv.adminKeysPayload,
stagAdminKeys: mutationPayload.stagingEnv.adminKeysPayload,
prodAdminKeys: mutationPayload.prodEnv.adminKeysPayload,
},
})
/**
* Initialize application environments for a given application ID.
*
* @param {string} appId - The ID of the application for which environments will be initialized.
* @returns {Promise<boolean>} A Promise that resolves to `true` when initialization is complete.
*
* @throws {Error} If there are any errors during the environment initialization process.
*/
const initAppEnvs = async (appId: string) => {
return new Promise<boolean>(async (resolve, reject) => {
const mutationPayload = {
devEnv: await createNewEnv(
appId,
'Development',
ApiEnvironmentEnvTypeChoices.Dev,
orgAdminsData.organisationAdminsAndSelf
),
stagingEnv: await createNewEnv(
appId,
'Staging',
ApiEnvironmentEnvTypeChoices.Staging,
orgAdminsData.organisationAdminsAndSelf
),
prodEnv: await createNewEnv(
appId,
'Production',
ApiEnvironmentEnvTypeChoices.Prod,
orgAdminsData.organisationAdminsAndSelf
),
}

if (createStarters) {
await createExampleSecrets(appId)
}
await initAppEnvironments({
variables: {
devEnv: mutationPayload.devEnv.createEnvPayload,
stagingEnv: mutationPayload.stagingEnv.createEnvPayload,
prodEnv: mutationPayload.prodEnv.createEnvPayload,
devAdminKeys: mutationPayload.devEnv.adminKeysPayload,
stagAdminKeys: mutationPayload.stagingEnv.adminKeysPayload,
prodAdminKeys: mutationPayload.prodEnv.adminKeysPayload,
},
})

resolve(true)
})
}

const handleCreateApp = async () => {
Expand Down Expand Up @@ -336,7 +370,13 @@ export default function NewAppDialog(props: {
],
})

await initAppEnvs(data.createApp.app.id)
const newAppId = data.createApp.app.id

await initAppEnvs(newAppId)

if (createStarters) {
await createExampleSecrets(newAppId)
}

setAppSecret(`pss:v${APP_VERSION}:${appToken}:${appKeyShares[0]}:${wrapKey}`)
setAppId(`phApp:v${APP_VERSION}:${appKeys.publicKey}`)
Expand Down

0 comments on commit 575f07a

Please sign in to comment.