mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 05:26:25 +00:00
Add DNS made easy stuff
This commit is contained in:
@@ -4,6 +4,7 @@ import { getConfig } from "@app/lib/config/env";
|
|||||||
import { request } from "@app/lib/config/request";
|
import { request } from "@app/lib/config/request";
|
||||||
import { crypto } from "@app/lib/crypto/cryptography";
|
import { crypto } from "@app/lib/crypto/cryptography";
|
||||||
import { BadRequestError } from "@app/lib/errors";
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
import { logger } from "@app/lib/logger";
|
||||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
|
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ export const validateDNSMadeEasyConnectionCredentials = async (config: TDNSMadeE
|
|||||||
message: `Failed to validate credentials: ${error.response?.data?.error?.[0] || error.message || "Unknown error"}`
|
message: `Failed to validate credentials: ${error.response?.data?.error?.[0] || error.message || "Unknown error"}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
logger.error(error, "Error validating DNS Made Easy connection credentials");
|
||||||
throw new BadRequestError({
|
throw new BadRequestError({
|
||||||
message: "Unable to validate connection: verify credentials"
|
message: "Unable to validate connection: verify credentials"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export enum AcmeDnsProvider {
|
export enum AcmeDnsProvider {
|
||||||
Route53 = "route53",
|
Route53 = "route53",
|
||||||
Cloudflare = "cloudflare"
|
Cloudflare = "cloudflare",
|
||||||
|
DNSMadeEasy = "dns-made-easy"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import {
|
|||||||
} from "./acme-certificate-authority-types";
|
} from "./acme-certificate-authority-types";
|
||||||
import { cloudflareDeleteTxtRecord, cloudflareInsertTxtRecord } from "./dns-providers/cloudflare";
|
import { cloudflareDeleteTxtRecord, cloudflareInsertTxtRecord } from "./dns-providers/cloudflare";
|
||||||
import { route53DeleteTxtRecord, route53InsertTxtRecord } from "./dns-providers/route54";
|
import { route53DeleteTxtRecord, route53InsertTxtRecord } from "./dns-providers/route54";
|
||||||
|
import { TDNSMadeEasyConnection } from "@app/services/app-connection/dns-made-easy/dns-made-easy-connection-types";
|
||||||
|
|
||||||
type TAcmeCertificateAuthorityFnsDeps = {
|
type TAcmeCertificateAuthorityFnsDeps = {
|
||||||
appConnectionDAL: Pick<TAppConnectionDALFactory, "findById">;
|
appConnectionDAL: Pick<TAppConnectionDALFactory, "findById">;
|
||||||
@@ -263,6 +264,15 @@ export const orderCertificate = async (
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case AcmeDnsProvider.DNSMadeEasy: {
|
||||||
|
await dnsMadeEasyInsertTxtRecord(
|
||||||
|
connection as TDNSMadeEasyConnection,
|
||||||
|
acmeCa.configuration.dnsProviderConfig.hostedZoneId,
|
||||||
|
recordName,
|
||||||
|
recordValue
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new Error(`Unsupported DNS provider: ${acmeCa.configuration.dnsProviderConfig.provider as string}`);
|
throw new Error(`Unsupported DNS provider: ${acmeCa.configuration.dnsProviderConfig.provider as string}`);
|
||||||
}
|
}
|
||||||
@@ -291,6 +301,14 @@ export const orderCertificate = async (
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case AcmeDnsProvider.DNSMadeEasy: {
|
||||||
|
await dnsMadeEasyDeleteTxtRecord(
|
||||||
|
connection as TDNSMadeEasyConnection,
|
||||||
|
acmeCa.configuration.dnsProviderConfig.hostedZoneId,
|
||||||
|
recordName,
|
||||||
|
recordValue
|
||||||
|
);
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new Error(`Unsupported DNS provider: ${acmeCa.configuration.dnsProviderConfig.provider as string}`);
|
throw new Error(`Unsupported DNS provider: ${acmeCa.configuration.dnsProviderConfig.provider as string}`);
|
||||||
}
|
}
|
||||||
@@ -413,6 +431,12 @@ export const AcmeCertificateAuthorityFns = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dnsProviderConfig.provider === AcmeDnsProvider.DNSMadeEasy && appConnection.app !== AppConnection.DNSMadeEasy) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `App connection with ID '${dnsAppConnectionId}' is not a DNS Made Easy connection`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// validates permission to connect
|
// validates permission to connect
|
||||||
await appConnectionService.validateAppConnectionUsageById(
|
await appConnectionService.validateAppConnectionUsageById(
|
||||||
appConnection.app as AppConnection,
|
appConnection.app as AppConnection,
|
||||||
@@ -508,6 +532,15 @@ export const AcmeCertificateAuthorityFns = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
dnsProviderConfig.provider === AcmeDnsProvider.DNSMadeEasy &&
|
||||||
|
appConnection.app !== AppConnection.DNSMadeEasy
|
||||||
|
) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `App connection with ID '${dnsAppConnectionId}' is not a DNS Made Easy connection`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const ca = await certificateAuthorityDAL.findById(id);
|
const ca = await certificateAuthorityDAL.findById(id);
|
||||||
|
|
||||||
if (!ca) {
|
if (!ca) {
|
||||||
|
|||||||
@@ -106,8 +106,8 @@ export enum IntegrationUrls {
|
|||||||
|
|
||||||
GITHUB_USER_INSTALLATIONS = "https://api.github.com/user/installations",
|
GITHUB_USER_INSTALLATIONS = "https://api.github.com/user/installations",
|
||||||
CHEF_API_URL = "https://api.chef.io",
|
CHEF_API_URL = "https://api.chef.io",
|
||||||
DNS_MADE_EASY_API_URL = "https://api.dnsmadeeasy.com/V2.0",
|
DNS_MADE_EASY_API_URL = "https://api.dnsmadeeasy.com",
|
||||||
DNS_MADE_EASY_SANDBOX_API_URL = "https://api.sandbox.dnsmadeeasy.com/V2.0"
|
DNS_MADE_EASY_SANDBOX_API_URL = "https://api.sandbox.dnsmadeeasy.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getIntegrationOptions = async () => {
|
export const getIntegrationOptions = async () => {
|
||||||
|
|||||||
@@ -16,12 +16,14 @@ export const caStatusToNameMap: { [K in CaStatus]: string } = {
|
|||||||
|
|
||||||
export const ACME_DNS_PROVIDER_NAME_MAP: Record<AcmeDnsProvider, string> = {
|
export const ACME_DNS_PROVIDER_NAME_MAP: Record<AcmeDnsProvider, string> = {
|
||||||
[AcmeDnsProvider.ROUTE53]: "Route53",
|
[AcmeDnsProvider.ROUTE53]: "Route53",
|
||||||
[AcmeDnsProvider.Cloudflare]: "Cloudflare"
|
[AcmeDnsProvider.Cloudflare]: "Cloudflare",
|
||||||
|
[AcmeDnsProvider.DNSMadeEasy]: "DNS Made Easy"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ACME_DNS_PROVIDER_APP_CONNECTION_MAP: Record<AcmeDnsProvider, AppConnection> = {
|
export const ACME_DNS_PROVIDER_APP_CONNECTION_MAP: Record<AcmeDnsProvider, AppConnection> = {
|
||||||
[AcmeDnsProvider.ROUTE53]: AppConnection.AWS,
|
[AcmeDnsProvider.ROUTE53]: AppConnection.AWS,
|
||||||
[AcmeDnsProvider.Cloudflare]: AppConnection.Cloudflare
|
[AcmeDnsProvider.Cloudflare]: AppConnection.Cloudflare,
|
||||||
|
[AcmeDnsProvider.DNSMadeEasy]: AppConnection.DNSMadeEasy
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CA_TYPE_CAPABILITIES_MAP: Record<CaType, CaCapability[]> = {
|
export const CA_TYPE_CAPABILITIES_MAP: Record<CaType, CaCapability[]> = {
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ export enum CaRenewalType {
|
|||||||
|
|
||||||
export enum AcmeDnsProvider {
|
export enum AcmeDnsProvider {
|
||||||
ROUTE53 = "route53",
|
ROUTE53 = "route53",
|
||||||
Cloudflare = "cloudflare"
|
Cloudflare = "cloudflare",
|
||||||
|
DNSMadeEasy = "dns-made-easy"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CaCapability {
|
export enum CaCapability {
|
||||||
|
|||||||
+45
-1
@@ -27,6 +27,10 @@ import {
|
|||||||
TCloudflareZone,
|
TCloudflareZone,
|
||||||
useCloudflareConnectionListZones
|
useCloudflareConnectionListZones
|
||||||
} from "@app/hooks/api/appConnections/cloudflare";
|
} from "@app/hooks/api/appConnections/cloudflare";
|
||||||
|
import {
|
||||||
|
TDNSMadeEasyZone,
|
||||||
|
useDNSMadeEasyConnectionListZones
|
||||||
|
} from "@app/hooks/api/appConnections/dns-made-easy";
|
||||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||||
import {
|
import {
|
||||||
AcmeDnsProvider,
|
AcmeDnsProvider,
|
||||||
@@ -211,6 +215,11 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
enabled: caType === CaType.ACME
|
enabled: caType === CaType.ACME
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: availableDNSMadeEasyConnections, isPending: isDNSMadeEasyPending } =
|
||||||
|
useListAvailableAppConnections(AppConnection.DNSMadeEasy, currentProject.id, {
|
||||||
|
enabled: caType === CaType.ACME
|
||||||
|
});
|
||||||
|
|
||||||
const { data: availableAzureConnections, isPending: isAzurePending } =
|
const { data: availableAzureConnections, isPending: isAzurePending } =
|
||||||
useListAvailableAppConnections(AppConnection.AzureADCS, currentProject.id, {
|
useListAvailableAppConnections(AppConnection.AzureADCS, currentProject.id, {
|
||||||
enabled: caType === CaType.AZURE_AD_CS
|
enabled: caType === CaType.AZURE_AD_CS
|
||||||
@@ -225,11 +234,15 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
caType,
|
caType,
|
||||||
availableRoute53Connections,
|
availableRoute53Connections,
|
||||||
availableCloudflareConnections,
|
availableCloudflareConnections,
|
||||||
|
availableDNSMadeEasyConnections,
|
||||||
availableAzureConnections
|
availableAzureConnections
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const isPending =
|
const isPending =
|
||||||
isRoute53Pending || isCloudflarePending || (isAzurePending && caType === CaType.AZURE_AD_CS);
|
isRoute53Pending ||
|
||||||
|
isCloudflarePending ||
|
||||||
|
isDNSMadeEasyPending ||
|
||||||
|
(isAzurePending && caType === CaType.AZURE_AD_CS);
|
||||||
|
|
||||||
const dnsAppConnection =
|
const dnsAppConnection =
|
||||||
caType === CaType.ACME && configuration && "dnsAppConnection" in configuration
|
caType === CaType.ACME && configuration && "dnsAppConnection" in configuration
|
||||||
@@ -241,6 +254,11 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
enabled: dnsProvider === AcmeDnsProvider.Cloudflare && !!dnsAppConnection.id
|
enabled: dnsProvider === AcmeDnsProvider.Cloudflare && !!dnsAppConnection.id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: dnsMadeEasyZones = [], isPending: isDNSMadeEasyZonesPending } =
|
||||||
|
useDNSMadeEasyConnectionListZones(dnsAppConnection.id, {
|
||||||
|
enabled: dnsProvider === AcmeDnsProvider.DNSMadeEasy && !!dnsAppConnection.id
|
||||||
|
});
|
||||||
|
|
||||||
// Populate form with CA data when editing
|
// Populate form with CA data when editing
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ca && !isCaLoading) {
|
if (ca && !isCaLoading) {
|
||||||
@@ -500,6 +518,32 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{dnsProvider === AcmeDnsProvider.DNSMadeEasy && (
|
||||||
|
<Controller
|
||||||
|
name="configuration.dnsProviderConfig.hostedZoneId"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
label="Zone"
|
||||||
|
>
|
||||||
|
<FilterableSelect
|
||||||
|
isLoading={isDNSMadeEasyZonesPending && !!dnsAppConnection.id}
|
||||||
|
isDisabled={!dnsAppConnection.id}
|
||||||
|
value={dnsMadeEasyZones.find((zone) => zone.id === value)}
|
||||||
|
onChange={(option) => {
|
||||||
|
onChange((option as SingleValue<TDNSMadeEasyZone>)?.id ?? null);
|
||||||
|
}}
|
||||||
|
options={dnsMadeEasyZones}
|
||||||
|
placeholder="Select a zone..."
|
||||||
|
getOptionLabel={(option) => option.name}
|
||||||
|
getOptionValue={(option) => option.id}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
defaultValue=""
|
defaultValue=""
|
||||||
|
|||||||
Reference in New Issue
Block a user