mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Implement mark valid cascade
This commit is contained in:
@@ -1,14 +1,61 @@
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName, TPkiAcmeAccounts, TPkiAcmeAuths } from "@app/db/schemas";
|
||||
import { TableName, TPkiAcmeChallenges } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
|
||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
||||
import { Knex } from "knex";
|
||||
import { AcmeAuthStatus, AcmeChallengeStatus, AcmeOrderStatus } from "./pki-acme-schemas";
|
||||
|
||||
export type TPkiAcmeChallengeDALFactory = ReturnType<typeof pkiAcmeChallengeDALFactory>;
|
||||
|
||||
export const pkiAcmeChallengeDALFactory = (db: TDbClient) => {
|
||||
const pkiAcmeChallengeOrm = ormify(db, TableName.PkiAcmeChallenge);
|
||||
|
||||
const markAsValidCascadeById = async (id: string, tx?: Knex): Promise<TPkiAcmeChallenges> => {
|
||||
try {
|
||||
const [challenge] = (await (tx || db)(TableName.PkiAcmeChallenge)
|
||||
.where({ id })
|
||||
.update({ status: AcmeChallengeStatus.Valid, validatedAt: new Date() })
|
||||
.returning("*")) as [TPkiAcmeChallenges];
|
||||
|
||||
// Update pending auth to valid as well
|
||||
const updatedAuths = await (tx || db)(TableName.PkiAcmeAuth)
|
||||
.where({ id: challenge.authId, status: AcmeAuthStatus.Pending })
|
||||
.update({ status: AcmeAuthStatus.Valid })
|
||||
.returning("id");
|
||||
|
||||
if (updatedAuths.length > 0) {
|
||||
// Update status for pending orders that have all auths valid
|
||||
await (tx || db)(TableName.PkiAcmeOrder)
|
||||
.whereIn("id", (qb) => {
|
||||
qb.select("id")
|
||||
.from(TableName.PkiAcmeOrder)
|
||||
.join(TableName.PkiAcmeOrderAuth, `${TableName.PkiAcmeOrder}.id`, `${TableName.PkiAcmeOrderAuth}.orderId`)
|
||||
.join(TableName.PkiAcmeAuth, `${TableName.PkiAcmeOrderAuth}.authId`, `${TableName.PkiAcmeAuth}.id`)
|
||||
.groupBy(`${TableName.PkiAcmeOrder}.id`)
|
||||
// All auths should be valid for the order to be ready
|
||||
.havingRaw(
|
||||
`SUM(CASE WHEN :authTable:.status = :authStatus: THEN 1 ELSE 0 END) = COUNT(DISTINCT :authTable:.id)`,
|
||||
{
|
||||
authTable: TableName.PkiAcmeAuth,
|
||||
authStatus: AcmeAuthStatus.Valid
|
||||
}
|
||||
)
|
||||
// We only update orders that are pending
|
||||
.where(`${TableName.PkiAcmeOrder}.status`, AcmeOrderStatus.Pending)
|
||||
.whereIn(
|
||||
`${TableName.PkiAcmeAuth}.id`,
|
||||
updatedAuths.map((auth) => auth.id)
|
||||
);
|
||||
})
|
||||
.update({ status: AcmeOrderStatus.Ready });
|
||||
}
|
||||
|
||||
return challenge;
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Update certificate profile" });
|
||||
}
|
||||
};
|
||||
|
||||
const findByAccountAuthAndChallengeId = async (accountId: string, authId: string, challengeId: string, tx?: Knex) => {
|
||||
try {
|
||||
const challenge = await (tx || db)(TableName.PkiAcmeChallenge)
|
||||
@@ -78,6 +125,7 @@ export const pkiAcmeChallengeDALFactory = (db: TDbClient) => {
|
||||
|
||||
return {
|
||||
...pkiAcmeChallengeOrm,
|
||||
markAsValidCascadeById,
|
||||
findByAccountAuthAndChallengeId,
|
||||
findByIdForChallengeValidation
|
||||
};
|
||||
|
||||
@@ -11,7 +11,10 @@ import { TPkiAcmeChallengeServiceFactory } from "./pki-acme-types";
|
||||
|
||||
type TPkiAcmeChallengeServiceFactoryDep = {
|
||||
acmeAuthDAL: Pick<TPkiAcmeAuthDALFactory, "updateById">;
|
||||
acmeChallengeDAL: Pick<TPkiAcmeChallengeDALFactory, "transaction" | "findByIdForChallengeValidation" | "updateById">;
|
||||
acmeChallengeDAL: Pick<
|
||||
TPkiAcmeChallengeDALFactory,
|
||||
"transaction" | "findByIdForChallengeValidation" | "markAsValidCascadeById"
|
||||
>;
|
||||
};
|
||||
|
||||
export const pkiAcmeChallengeServiceFactory = ({
|
||||
@@ -65,13 +68,7 @@ export const pkiAcmeChallengeServiceFactory = ({
|
||||
if (challengeResponseBody !== expectedChallengeResponseBody) {
|
||||
throw new AcmeIncorrectResponseError({ message: "ACME challenge response is not correct" });
|
||||
}
|
||||
await acmeChallengeDAL.updateById(
|
||||
challengeId,
|
||||
{ status: AcmeChallengeStatus.Valid, validatedAt: new Date() },
|
||||
tx
|
||||
);
|
||||
await acmeAuthDAL.updateById(challenge.auth.account.id, { status: AcmeAuthStatus.Valid }, tx);
|
||||
// TODO: trigger a check for order status as well
|
||||
await acmeChallengeDAL.markAsValidCascadeById(challengeId, tx);
|
||||
} catch (error) {
|
||||
logger.error(error, "Error validating ACME challenge response");
|
||||
// TODO: we should retry the challenge validation a few times, but let's keep it simple for now
|
||||
|
||||
Reference in New Issue
Block a user