mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-20 21:18:18 +00:00
feat(app-connections, PKI): Cloudflare as DNS provider
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import axios from "axios";
|
||||
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { TCloudflareConnectionConfig } from "@app/services/app-connection/cloudflare/cloudflare-connection-types";
|
||||
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
|
||||
|
||||
export const cloudflareInsertTxtRecord = async (
|
||||
connection: TCloudflareConnectionConfig,
|
||||
hostedZoneId: string,
|
||||
domain: string,
|
||||
value: string
|
||||
) => {
|
||||
const {
|
||||
credentials: { apiToken }
|
||||
} = connection;
|
||||
|
||||
try {
|
||||
await request.post(
|
||||
`${IntegrationUrls.CLOUDFLARE_API_URL}/client/v4/zones/${hostedZoneId}/dns_records`,
|
||||
{
|
||||
type: "TXT",
|
||||
name: domain,
|
||||
content: value,
|
||||
ttl: 60,
|
||||
proxied: false
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiToken}`,
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json"
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
const firstErrorMessage = (
|
||||
error.response?.data as {
|
||||
errors?: { message: string }[];
|
||||
}
|
||||
)?.errors?.[0]?.message;
|
||||
if (firstErrorMessage) {
|
||||
throw new Error(firstErrorMessage);
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const cloudflareDeleteTxtRecord = async (
|
||||
connection: TCloudflareConnectionConfig,
|
||||
hostedZoneId: string,
|
||||
domain: string,
|
||||
value: string
|
||||
) => {
|
||||
const {
|
||||
credentials: { apiToken }
|
||||
} = connection;
|
||||
|
||||
try {
|
||||
const listRecordsResponse = await request.get<{
|
||||
result: { id: string; type: string; name: string; content: string }[];
|
||||
}>(`${IntegrationUrls.CLOUDFLARE_API_URL}/client/v4/zones/${hostedZoneId}/dns_records`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiToken}`,
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json"
|
||||
},
|
||||
params: {
|
||||
type: "TXT",
|
||||
name: domain,
|
||||
content: value
|
||||
}
|
||||
});
|
||||
|
||||
const dnsRecords = listRecordsResponse.data?.result;
|
||||
|
||||
if (Array.isArray(dnsRecords) && dnsRecords.length > 0) {
|
||||
const recordToDelete = dnsRecords.find(
|
||||
(record) => record.type === "TXT" && record.name === domain && record.content === value
|
||||
);
|
||||
|
||||
if (recordToDelete) {
|
||||
await request.delete(
|
||||
`${IntegrationUrls.CLOUDFLARE_API_URL}/client/v4/zones/${hostedZoneId}/dns_records/${recordToDelete.id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiToken}`,
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json"
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
const firstErrorMessage = (
|
||||
error.response?.data as {
|
||||
errors?: { message: string }[];
|
||||
}
|
||||
)?.errors?.[0]?.message;
|
||||
if (firstErrorMessage) {
|
||||
throw new Error(firstErrorMessage);
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import { ChangeResourceRecordSetsCommand, Route53Client } from "@aws-sdk/client-route-53";
|
||||
|
||||
import { CustomAWSHasher } from "@app/lib/aws/hashing";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { AWSRegion } from "@app/services/app-connection/app-connection-enums";
|
||||
import { getAwsConnectionConfig } from "@app/services/app-connection/aws/aws-connection-fns";
|
||||
import { TAwsConnectionConfig } from "@app/services/app-connection/aws/aws-connection-types";
|
||||
|
||||
export const route53InsertTxtRecord = async (
|
||||
connection: TAwsConnectionConfig,
|
||||
hostedZoneId: string,
|
||||
domain: string,
|
||||
value: string
|
||||
) => {
|
||||
const config = await getAwsConnectionConfig(connection, AWSRegion.US_WEST_1); // REGION is irrelevant because Route53 is global
|
||||
const route53Client = new Route53Client({
|
||||
sha256: CustomAWSHasher,
|
||||
useFipsEndpoint: crypto.isFipsModeEnabled(),
|
||||
credentials: config.credentials!,
|
||||
region: config.region
|
||||
});
|
||||
|
||||
const command = new ChangeResourceRecordSetsCommand({
|
||||
HostedZoneId: hostedZoneId,
|
||||
ChangeBatch: {
|
||||
Comment: "Set ACME challenge TXT record",
|
||||
Changes: [
|
||||
{
|
||||
Action: "UPSERT",
|
||||
ResourceRecordSet: {
|
||||
Name: domain,
|
||||
Type: "TXT",
|
||||
TTL: 30,
|
||||
ResourceRecords: [{ Value: value }]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
await route53Client.send(command);
|
||||
};
|
||||
|
||||
export const route53DeleteTxtRecord = async (
|
||||
connection: TAwsConnectionConfig,
|
||||
hostedZoneId: string,
|
||||
domain: string,
|
||||
value: string
|
||||
) => {
|
||||
const config = await getAwsConnectionConfig(connection, AWSRegion.US_WEST_1); // REGION is irrelevant because Route53 is global
|
||||
const route53Client = new Route53Client({
|
||||
credentials: config.credentials!,
|
||||
region: config.region
|
||||
});
|
||||
|
||||
const command = new ChangeResourceRecordSetsCommand({
|
||||
HostedZoneId: hostedZoneId,
|
||||
ChangeBatch: {
|
||||
Comment: "Delete ACME challenge TXT record",
|
||||
Changes: [
|
||||
{
|
||||
Action: "DELETE",
|
||||
ResourceRecordSet: {
|
||||
Name: domain,
|
||||
Type: "TXT",
|
||||
TTL: 30,
|
||||
ResourceRecords: [{ Value: value }]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
await route53Client.send(command);
|
||||
};
|
||||
Reference in New Issue
Block a user