Skip to content

Commit 1b2aa91

Browse files
LtadrianAdrian Gracia
and
Adrian Gracia
authoredMar 14, 2025··
SQC-354 add mtls fields to hyperdrive (#8337)
Co-authored-by: Adrian Gracia <agracia@cloudflare.com>
1 parent d7ea498 commit 1b2aa91

File tree

7 files changed

+159
-9
lines changed

7 files changed

+159
-9
lines changed
 

‎.changeset/wise-points-love.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
Add mTLS configuration fields to Hyperdrive command
6+
7+
hyperdrive create test123 ... --ca-certificate-uuid=CA_CERT_UUID --mtls-certificate-uuid=MTLS_CERT_UUID

‎packages/wrangler/src/__tests__/hyperdrive.test.ts

+103-7
Original file line numberDiff line numberDiff line change
@@ -540,18 +540,58 @@ describe("hyperdrive commands", () => {
540540
`);
541541
});
542542

543+
it("should create a hyperdrive with mtls config", async () => {
544+
const reqProm = mockHyperdriveCreate();
545+
await runWrangler(
546+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --ca-certificate-uuid=12345 --mtls-certificate-uuid=1234"
547+
);
548+
await expect(reqProm).resolves.toMatchInlineSnapshot(`
549+
Object {
550+
"mtls": Object {
551+
"ca_certificate_uuid": "12345",
552+
"mtls_certificate_uuid": "1234",
553+
},
554+
"name": "test123",
555+
"origin": Object {
556+
"database": "neondb",
557+
"host": "example.com",
558+
"password": "password",
559+
"port": 1234,
560+
"scheme": "postgresql",
561+
"user": "test",
562+
},
563+
}
564+
`);
565+
expect(std.out).toMatchInlineSnapshot(`
566+
"🚧 Creating 'test123'
567+
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
568+
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
569+
570+
{
571+
\\"hyperdrive\\": [
572+
{
573+
\\"binding\\": \\"HYPERDRIVE\\",
574+
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\"
575+
}
576+
]
577+
}"
578+
`);
579+
});
580+
543581
it("should handle listing configs", async () => {
544582
mockHyperdriveGetListOrDelete();
545583
await runWrangler("hyperdrive list");
546584
expect(std.out).toMatchInlineSnapshot(`
547585
"📋 Listing Hyperdrive configs
548-
┌──────────────────────────────────────┬─────────┬────────┬────────────────┬──────┬──────────┬───────────────────┐
549-
│ id │ name │ user │ host │ port │ database │ caching │
550-
├──────────────────────────────────────┼─────────┼────────┼────────────────┼──────┼──────────┼───────────────────┤
551-
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ neondb │ │
552-
├──────────────────────────────────────┼─────────┼────────┼────────────────┼──────┼──────────┼───────────────────┤
553-
│ yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy │ new-db │ dbuser │ www.google.com │ 3211 │ mydb │ {\\"disabled\\":true} │
554-
└──────────────────────────────────────┴─────────┴────────┴────────────────┴──────┴──────────┴───────────────────┘"
586+
┌──────────────────────────────────────┬─────────────┬─────────┬────────────────┬──────┬───────────┬───────────────────┬───────────────────────────────────────────────────────────────┐
587+
│ id │ name │ user │ host │ port │ database │ caching │ mtls │
588+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
589+
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ neondb │ │ │
590+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
591+
│ yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy │ new-db │ dbuser │ www.google.com │ 3211 │ mydb │ {\\"disabled\\":true} │ │
592+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
593+
│ zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz │ new-db-mtls │ pg-mtls │ www.mtls.com │ 3212 │ mydb-mtls │ │ {\\"ca_certificate_uuid\\":\\"1234\\",\\"mtls_certificate_uuid\\":\\"1234\\"} │
594+
└──────────────────────────────────────┴─────────────┴─────────┴────────────────┴──────┴───────────┴───────────────────┴───────────────────────────────────────────────────────────────┘"
555595
`);
556596
});
557597

@@ -856,6 +896,40 @@ describe("hyperdrive commands", () => {
856896
"
857897
`);
858898
});
899+
900+
it("should handle updating a hyperdrive config's mtls configuration", async () => {
901+
const reqProm = mockHyperdriveUpdate();
902+
await runWrangler(
903+
"hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --ca-certificate-uuid=2345 --mtls-certificate-uuid=234"
904+
);
905+
await expect(reqProm).resolves.toMatchInlineSnapshot(`
906+
Object {
907+
"mtls": Object {
908+
"ca_certificate_uuid": "2345",
909+
"mtls_certificate_uuid": "234",
910+
},
911+
}
912+
`);
913+
expect(std.out).toMatchInlineSnapshot(`
914+
"🚧 Updating 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
915+
✅ Updated xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Hyperdrive config
916+
{
917+
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
918+
\\"name\\": \\"test123\\",
919+
\\"origin\\": {
920+
\\"scheme\\": \\"postgresql\\",
921+
\\"host\\": \\"example.com\\",
922+
\\"port\\": 5432,
923+
\\"database\\": \\"neondb\\",
924+
\\"user\\": \\"test\\"
925+
},
926+
\\"mtls\\": {
927+
\\"ca_certificate_uuid\\": \\"2345\\",
928+
\\"mtls_certificate_uuid\\": \\"234\\"
929+
}
930+
}"
931+
`);
932+
});
859933
});
860934

861935
const defaultConfig: HyperdriveConfig = {
@@ -908,6 +982,21 @@ function mockHyperdriveGetListOrDelete() {
908982
disabled: true,
909983
},
910984
},
985+
{
986+
id: "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz",
987+
name: "new-db-mtls",
988+
origin: {
989+
host: "www.mtls.com",
990+
port: 3212,
991+
database: "mydb-mtls",
992+
user: "pg-mtls",
993+
scheme: "pg-mtls",
994+
},
995+
mtls: {
996+
ca_certificate_uuid: "1234",
997+
mtls_certificate_uuid: "1234",
998+
},
999+
},
9111000
],
9121001
true
9131002
)
@@ -955,6 +1044,11 @@ function mockHyperdriveUpdate(): Promise<PatchHyperdriveBody> {
9551044
delete origin.port;
9561045
}
9571046
}
1047+
const mtls = defaultConfig.mtls;
1048+
if (mtls && reqBody.mtls) {
1049+
mtls.ca_certificate_uuid = reqBody.mtls.ca_certificate_uuid;
1050+
mtls.mtls_certificate_uuid = reqBody.mtls.mtls_certificate_uuid;
1051+
}
9581052

9591053
return HttpResponse.json(
9601054
createFetchResult(
@@ -963,6 +1057,7 @@ function mockHyperdriveUpdate(): Promise<PatchHyperdriveBody> {
9631057
name: reqBody.name ?? defaultConfig.name,
9641058
origin,
9651059
caching: reqBody.caching ?? defaultConfig.caching,
1060+
mtls: reqBody.mtls,
9661061
},
9671062
true
9681063
)
@@ -999,6 +1094,7 @@ function mockHyperdriveCreate(): Promise<CreateUpdateHyperdriveBody> {
9991094
access_client_id: reqBody.origin.access_client_id,
10001095
},
10011096
caching: reqBody.caching,
1097+
mtls: reqBody.mtls,
10021098
},
10031099
true
10041100
)

‎packages/wrangler/src/hyperdrive/client.ts

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type HyperdriveConfig = {
77
name: string;
88
origin: PublicOrigin;
99
caching?: CachingOptions;
10+
mtls?: Mtls;
1011
};
1112

1213
export type OriginDatabase = {
@@ -73,12 +74,19 @@ export type CreateUpdateHyperdriveBody = {
7374
name: string;
7475
origin: OriginWithSecrets;
7576
caching?: CachingOptions;
77+
mtls?: Mtls;
7678
};
7779

7880
export type PatchHyperdriveBody = {
7981
name?: string;
8082
origin?: OriginWithSecretsPartial;
8183
caching?: CachingOptions;
84+
mtls?: Mtls;
85+
};
86+
87+
export type Mtls = {
88+
ca_certificate_uuid?: string;
89+
mtls_certificate_uuid?: string;
8290
};
8391

8492
export async function createConfig(

‎packages/wrangler/src/hyperdrive/create.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { configFileName, formatConfigSnippet, readConfig } from "../config";
22
import { logger } from "../logger";
33
import { createConfig } from "./client";
4-
import { getCacheOptionsFromArgs, getOriginFromArgs, upsertOptions } from ".";
4+
import {
5+
getCacheOptionsFromArgs,
6+
getMtlsFromArgs,
7+
getOriginFromArgs,
8+
upsertOptions,
9+
} from ".";
510
import type {
611
CommonYargsArgv,
712
StrictYargsOptionsToInterface,
@@ -32,6 +37,7 @@ export async function handler(
3237
name: args.name,
3338
origin,
3439
caching: getCacheOptionsFromArgs(args),
40+
mtls: getMtlsFromArgs(args),
3541
});
3642
logger.log(`✅ Created new Hyperdrive config: ${database.id}`);
3743
logger.log(

‎packages/wrangler/src/hyperdrive/index.ts

+26
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
} from "../yargs-types";
1313
import type {
1414
CachingOptions,
15+
Mtls,
1516
NetworkOriginWithSecrets,
1617
OriginDatabaseWithSecrets,
1718
OriginWithSecrets,
@@ -116,6 +117,16 @@ export function upsertOptions<T>(yargs: Argv<T>) {
116117
describe:
117118
"Indicates the number of seconds cache may serve the response after it becomes stale, cannot be set when caching is disabled",
118119
},
120+
"ca-certificate-uuid": {
121+
type: "string",
122+
describe:
123+
"Sets custom CA certificate when connecting to origin database. Must be valid UUID of already uploaded CA certificate.",
124+
},
125+
"mtls-certificate-uuid": {
126+
type: "string",
127+
describe:
128+
"Sets custom mTLS client certificates when connecting to origin database. Must be valid UUID of already uploaded public/private key certificates.",
129+
},
119130
})
120131
.group(
121132
["connection-string"],
@@ -297,3 +308,18 @@ export function getCacheOptionsFromArgs(
297308
return caching;
298309
}
299310
}
311+
312+
export function getMtlsFromArgs(
313+
args: StrictYargsOptionsToInterface<typeof upsertOptions>
314+
): Mtls | undefined {
315+
const mtls = {
316+
ca_certificate_uuid: args.caCertificateUuid,
317+
mtls_certificate_uuid: args.mtlsCertificateUuid,
318+
};
319+
320+
if (JSON.stringify(mtls) === "{}") {
321+
return undefined;
322+
} else {
323+
return mtls;
324+
}
325+
}

‎packages/wrangler/src/hyperdrive/list.ts

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export async function handler(
2626
port: database.origin.port?.toString() ?? "",
2727
database: database.origin.database ?? "",
2828
caching: JSON.stringify(database.caching),
29+
mtls: JSON.stringify(database.mtls),
2930
}))
3031
);
3132
}

‎packages/wrangler/src/hyperdrive/update.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { readConfig } from "../config";
22
import { logger } from "../logger";
33
import { patchConfig } from "./client";
4-
import { getCacheOptionsFromArgs, getOriginFromArgs, upsertOptions } from ".";
4+
import {
5+
getCacheOptionsFromArgs,
6+
getMtlsFromArgs,
7+
getOriginFromArgs,
8+
upsertOptions,
9+
} from ".";
510
import type {
611
CommonYargsArgv,
712
StrictYargsOptionsToInterface,
@@ -32,6 +37,7 @@ export async function handler(
3237
name: args.name,
3338
origin,
3439
caching: getCacheOptionsFromArgs(args),
40+
mtls: getMtlsFromArgs(args),
3541
});
3642
logger.log(
3743
`✅ Updated ${updated.id} Hyperdrive config\n`,

0 commit comments

Comments
 (0)
Please sign in to comment.