mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 20:27:43 +00:00
Add url check
This commit is contained in:
@@ -121,7 +121,10 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { payload, protectedHeader } = await server.services.pkiAcme.validateNewAccountJwsPayload(req.body);
|
const { payload, protectedHeader } = await server.services.pkiAcme.validateNewAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
|
rawJwsPayload: req.body
|
||||||
|
});
|
||||||
const { alg, jwk } = protectedHeader;
|
const { alg, jwk } = protectedHeader;
|
||||||
return sendAcmeResponse(
|
return sendAcmeResponse(
|
||||||
res,
|
res,
|
||||||
@@ -161,6 +164,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { payload, profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { payload, profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body,
|
rawJwsPayload: req.body,
|
||||||
schema: DeactivateAcmeAccountBodySchema,
|
schema: DeactivateAcmeAccountBodySchema,
|
||||||
@@ -202,6 +206,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body,
|
rawJwsPayload: req.body,
|
||||||
schema: CreateAcmeOrderBodySchema
|
schema: CreateAcmeOrderBodySchema
|
||||||
@@ -243,6 +248,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body
|
rawJwsPayload: req.body
|
||||||
});
|
});
|
||||||
@@ -283,6 +289,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body,
|
rawJwsPayload: req.body,
|
||||||
schema: FinalizeAcmeOrderBodySchema
|
schema: FinalizeAcmeOrderBodySchema
|
||||||
@@ -324,6 +331,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body,
|
rawJwsPayload: req.body,
|
||||||
schema: ListAcmeOrdersPayloadSchema,
|
schema: ListAcmeOrdersPayloadSchema,
|
||||||
@@ -365,6 +373,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body
|
rawJwsPayload: req.body
|
||||||
});
|
});
|
||||||
@@ -401,6 +410,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
url: req.url,
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body
|
rawJwsPayload: req.body
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
AcmeBadPublicKeyError,
|
AcmeBadPublicKeyError,
|
||||||
AcmeMalformedError,
|
AcmeMalformedError,
|
||||||
AcmeServerInternalError,
|
AcmeServerInternalError,
|
||||||
|
AcmeUnauthorizedError,
|
||||||
AcmeUnsupportedIdentifierError
|
AcmeUnsupportedIdentifierError
|
||||||
} from "./pki-acme-errors";
|
} from "./pki-acme-errors";
|
||||||
import { TPkiAcmeOrderAuthDALFactory } from "./pki-acme-order-auth-dal";
|
import { TPkiAcmeOrderAuthDALFactory } from "./pki-acme-order-auth-dal";
|
||||||
@@ -92,11 +93,17 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
const validateJwsPayload = async <
|
const validateJwsPayload = async <
|
||||||
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
||||||
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
||||||
>(
|
>({
|
||||||
rawJwsPayload: TRawJwsPayload,
|
url,
|
||||||
getJWK: (protectedHeader: JWSHeaderParameters) => Promise<JsonWebKey>,
|
rawJwsPayload,
|
||||||
schema?: TSchema
|
getJWK,
|
||||||
): Promise<TJwsPayload<T>> => {
|
schema
|
||||||
|
}: {
|
||||||
|
url: string;
|
||||||
|
rawJwsPayload: TRawJwsPayload;
|
||||||
|
getJWK: (protectedHeader: JWSHeaderParameters) => Promise<JsonWebKey>;
|
||||||
|
schema?: TSchema;
|
||||||
|
}): Promise<TJwsPayload<T>> => {
|
||||||
let result: FlattenedVerifyResult;
|
let result: FlattenedVerifyResult;
|
||||||
try {
|
try {
|
||||||
result = await flattenedVerify(rawJwsPayload, async (protectedHeader: JWSHeaderParameters | undefined) => {
|
result = await flattenedVerify(rawJwsPayload, async (protectedHeader: JWSHeaderParameters | undefined) => {
|
||||||
@@ -119,6 +126,9 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
const { protectedHeader: rawProtectedHeader, payload: rawPayload } = result;
|
const { protectedHeader: rawProtectedHeader, payload: rawPayload } = result;
|
||||||
try {
|
try {
|
||||||
const protectedHeader = ProtectedHeaderSchema.parse(rawProtectedHeader);
|
const protectedHeader = ProtectedHeaderSchema.parse(rawProtectedHeader);
|
||||||
|
if (protectedHeader.url !== url) {
|
||||||
|
throw new AcmeUnauthorizedError({ detail: "URL mismatch in the protected header" });
|
||||||
|
}
|
||||||
// TODO: consume the nonce here
|
// TODO: consume the nonce here
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
const textPayload = decoder.decode(rawPayload);
|
const textPayload = decoder.decode(rawPayload);
|
||||||
@@ -136,39 +146,47 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateNewAccountJwsPayload = async (
|
const validateNewAccountJwsPayload = async ({
|
||||||
rawJwsPayload: TRawJwsPayload
|
url,
|
||||||
): Promise<TJwsPayload<TCreateAcmeAccountPayload>> => {
|
rawJwsPayload
|
||||||
return await validateJwsPayload(
|
}: {
|
||||||
|
url: string;
|
||||||
|
rawJwsPayload: TRawJwsPayload;
|
||||||
|
}): Promise<TJwsPayload<TCreateAcmeAccountPayload>> => {
|
||||||
|
return await validateJwsPayload({
|
||||||
|
url,
|
||||||
rawJwsPayload,
|
rawJwsPayload,
|
||||||
async (protectedHeader) => {
|
getJWK: async (protectedHeader) => {
|
||||||
if (!protectedHeader.jwk) {
|
if (!protectedHeader.jwk) {
|
||||||
throw new AcmeMalformedError({ detail: "JWK is required in the protected header" });
|
throw new AcmeMalformedError({ detail: "JWK is required in the protected header" });
|
||||||
}
|
}
|
||||||
return protectedHeader.jwk as unknown as JsonWebKey;
|
return protectedHeader.jwk as unknown as JsonWebKey;
|
||||||
},
|
},
|
||||||
CreateAcmeAccountBodySchema
|
schema: CreateAcmeAccountBodySchema
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateExistingAccountJwsPayload = async <
|
const validateExistingAccountJwsPayload = async <
|
||||||
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
||||||
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
||||||
>({
|
>({
|
||||||
|
url,
|
||||||
profileId,
|
profileId,
|
||||||
rawJwsPayload,
|
rawJwsPayload,
|
||||||
schema,
|
schema,
|
||||||
expectedAccountId
|
expectedAccountId
|
||||||
}: {
|
}: {
|
||||||
|
url: string;
|
||||||
profileId: string;
|
profileId: string;
|
||||||
rawJwsPayload: TRawJwsPayload;
|
rawJwsPayload: TRawJwsPayload;
|
||||||
schema?: TSchema;
|
schema?: TSchema;
|
||||||
expectedAccountId?: string;
|
expectedAccountId?: string;
|
||||||
}): Promise<TAuthenciatedJwsPayload<T>> => {
|
}): Promise<TAuthenciatedJwsPayload<T>> => {
|
||||||
const profile = await validateAcmeProfile(profileId);
|
const profile = await validateAcmeProfile(profileId);
|
||||||
const result = await validateJwsPayload(
|
const result = await validateJwsPayload({
|
||||||
|
url,
|
||||||
rawJwsPayload,
|
rawJwsPayload,
|
||||||
async (protectedHeader) => {
|
getJWK: async (protectedHeader) => {
|
||||||
if (!protectedHeader.kid) {
|
if (!protectedHeader.kid) {
|
||||||
throw new AcmeMalformedError({ detail: "KID is required in the protected header" });
|
throw new AcmeMalformedError({ detail: "KID is required in the protected header" });
|
||||||
}
|
}
|
||||||
@@ -186,7 +204,7 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
return account.publicKey as JsonWebKey;
|
return account.publicKey as JsonWebKey;
|
||||||
},
|
},
|
||||||
schema
|
schema
|
||||||
);
|
});
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
accountId: extractAccountIdFromKid(result.protectedHeader.kid!, profileId),
|
accountId: extractAccountIdFromKid(result.protectedHeader.kid!, profileId),
|
||||||
@@ -194,15 +212,6 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => {
|
|
||||||
const profile = await validateAcmeProfile(profileId);
|
|
||||||
return {
|
|
||||||
newNonce: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-nonce`),
|
|
||||||
newAccount: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-account`),
|
|
||||||
newOrder: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-order`)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildAcmeOrderResource = ({
|
const buildAcmeOrderResource = ({
|
||||||
profileId,
|
profileId,
|
||||||
order
|
order
|
||||||
@@ -233,6 +242,15 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => {
|
||||||
|
const profile = await validateAcmeProfile(profileId);
|
||||||
|
return {
|
||||||
|
newNonce: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-nonce`),
|
||||||
|
newAccount: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-account`),
|
||||||
|
newOrder: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-order`)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const getAcmeNewNonce = async (profileId: string): Promise<string> => {
|
const getAcmeNewNonce = async (profileId: string): Promise<string> => {
|
||||||
const profile = await validateAcmeProfile(profileId);
|
const profile = await validateAcmeProfile(profileId);
|
||||||
// FIXME: Implement ACME new nonce generation
|
// FIXME: Implement ACME new nonce generation
|
||||||
|
|||||||
@@ -52,21 +52,35 @@ export type TPkiAcmeServiceFactory = {
|
|||||||
validateJwsPayload: <
|
validateJwsPayload: <
|
||||||
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
||||||
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
||||||
>(
|
>({
|
||||||
rawJwsPayload: TRawJwsPayload,
|
url,
|
||||||
getJWK: (protectedHeader: JWSHeaderParameters) => Promise<JsonWebKey>,
|
rawJwsPayload,
|
||||||
schema?: TSchema
|
getJWK,
|
||||||
) => Promise<TJwsPayload<T>>;
|
schema
|
||||||
validateNewAccountJwsPayload: (rawJwsPayload: TRawJwsPayload) => Promise<TJwsPayload<TCreateAcmeAccountPayload>>;
|
}: {
|
||||||
|
url: string;
|
||||||
|
rawJwsPayload: TRawJwsPayload;
|
||||||
|
getJWK: (protectedHeader: JWSHeaderParameters) => Promise<JsonWebKey>;
|
||||||
|
schema?: z.ZodSchema<any>;
|
||||||
|
}) => Promise<TJwsPayload<any>>;
|
||||||
|
validateNewAccountJwsPayload: ({
|
||||||
|
url,
|
||||||
|
rawJwsPayload
|
||||||
|
}: {
|
||||||
|
url: string;
|
||||||
|
rawJwsPayload: TRawJwsPayload;
|
||||||
|
}) => Promise<TJwsPayload<TCreateAcmeAccountPayload>>;
|
||||||
validateExistingAccountJwsPayload: <
|
validateExistingAccountJwsPayload: <
|
||||||
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
TSchema extends z.ZodSchema<any> | undefined = undefined,
|
||||||
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
T = TSchema extends z.ZodSchema<infer R> ? R : string
|
||||||
>({
|
>({
|
||||||
|
url,
|
||||||
profileId,
|
profileId,
|
||||||
rawJwsPayload,
|
rawJwsPayload,
|
||||||
schema,
|
schema,
|
||||||
expectedAccountId
|
expectedAccountId
|
||||||
}: {
|
}: {
|
||||||
|
url: string;
|
||||||
profileId: string;
|
profileId: string;
|
||||||
rawJwsPayload: TRawJwsPayload;
|
rawJwsPayload: TRawJwsPayload;
|
||||||
schema?: TSchema;
|
schema?: TSchema;
|
||||||
|
|||||||
Reference in New Issue
Block a user