Skip to content

Commit 3993374

Browse files
LtadrianAdrian Gracia
andauthored
Add sslmode field to hyperdrive command (#8727)
* SQC-480 update -uuid to -id per api changes * SQC-480 implement sslmode field for hyperdrive --------- Co-authored-by: Adrian Gracia <[email protected]>
1 parent 8dcc50f commit 3993374

File tree

4 files changed

+152
-28
lines changed

4 files changed

+152
-28
lines changed

.changeset/every-wolves-roll.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
add sslmode to hyperdrive and update mtls flags

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

Lines changed: 118 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -625,16 +625,17 @@ describe("hyperdrive commands", () => {
625625
`);
626626
});
627627

628-
it("should create a hyperdrive with mtls config", async () => {
628+
it("should successfully create a hyperdrive with mtls config and sslmode=verify-full", async () => {
629629
const reqProm = mockHyperdriveCreate();
630630
await runWrangler(
631-
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --ca-certificate-uuid=12345 --mtls-certificate-uuid=1234"
631+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --ca-certificate-id=12345 --mtls-certificate-id=1234 --sslmode=verify-full"
632632
);
633633
await expect(reqProm).resolves.toMatchInlineSnapshot(`
634634
Object {
635635
"mtls": Object {
636-
"ca_certificate_uuid": "12345",
637-
"mtls_certificate_uuid": "1234",
636+
"ca_certificate_id": "12345",
637+
"mtls_certificate_id": "1234",
638+
"sslmode": "verify-full",
638639
},
639640
"name": "test123",
640641
"origin": Object {
@@ -663,20 +664,112 @@ describe("hyperdrive commands", () => {
663664
`);
664665
});
665666

667+
it("should successfully create a hyperdrive with mtls config and sslmode=require", async () => {
668+
const reqProm = mockHyperdriveCreate();
669+
await runWrangler(
670+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --mtls-certificate-id=1234 --sslmode=require"
671+
);
672+
await expect(reqProm).resolves.toMatchInlineSnapshot(`
673+
Object {
674+
"mtls": Object {
675+
"mtls_certificate_id": "1234",
676+
"sslmode": "require",
677+
},
678+
"name": "test123",
679+
"origin": Object {
680+
"database": "neondb",
681+
"host": "example.com",
682+
"password": "password",
683+
"port": 1234,
684+
"scheme": "postgresql",
685+
"user": "test",
686+
},
687+
}
688+
`);
689+
expect(std.out).toMatchInlineSnapshot(`
690+
"🚧 Creating 'test123'
691+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
692+
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
693+
694+
{
695+
\\"hyperdrive\\": [
696+
{
697+
\\"binding\\": \\"HYPERDRIVE\\",
698+
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\"
699+
}
700+
]
701+
}"
702+
`);
703+
});
704+
705+
it("should error on create hyperdrive with mtls config sslmode=require and CA flag set", async () => {
706+
await expect(() =>
707+
runWrangler(
708+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --ca-certificate-id=1234 --sslmode=require"
709+
)
710+
).rejects.toThrow();
711+
expect(std.err).toMatchInlineSnapshot(`
712+
"X [ERROR] CA not allowed when sslmode = 'require' is set
713+
714+
"
715+
`);
716+
});
717+
718+
it("should error on create hyperdrive with mtls config sslmode=verify-ca missing CA", async () => {
719+
await expect(() =>
720+
runWrangler(
721+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --mtls-certificate-id=1234 --sslmode=verify-ca"
722+
)
723+
).rejects.toThrow();
724+
expect(std.err).toMatchInlineSnapshot(`
725+
"X [ERROR] CA required when sslmode = 'verify-ca' or 'verify-full' is set
726+
727+
"
728+
`);
729+
});
730+
731+
it("should error on create hyperdrive with mtls config sslmode=verify-full missing CA", async () => {
732+
await expect(() =>
733+
runWrangler(
734+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --mtls-certificate-id=1234 --sslmode=verify-full"
735+
)
736+
).rejects.toThrow();
737+
expect(std.err).toMatchInlineSnapshot(`
738+
"X [ERROR] CA required when sslmode = 'verify-ca' or 'verify-full' is set
739+
740+
"
741+
`);
742+
});
743+
744+
it("should error on create hyperdrive with mtls config sslmode=random", async () => {
745+
await expect(() =>
746+
runWrangler(
747+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --mtls-certificate-id=1234 --sslmode=random"
748+
)
749+
).rejects.toThrow();
750+
expect(std.err).toMatchInlineSnapshot(`
751+
"X [ERROR] Invalid values:
752+
753+
Argument: sslmode, Given: \\"random\\", Choices: \\"require\\", \\"verify-ca\\", \\"verify-full\\"
754+
755+
"
756+
`);
757+
});
758+
666759
it("should handle listing configs", async () => {
667760
mockHyperdriveGetListOrDelete();
668761
await runWrangler("hyperdrive list");
669762
expect(std.out).toMatchInlineSnapshot(`
670763
"📋 Listing Hyperdrive configs
671-
┌──────────────────────────────────────┬─────────────┬─────────┬────────────────┬──────┬────────────┬───────────┬──────────┬───────────────────────────────────────────────────────────────┐
672-
│ id │ name │ user │ host │ port │ scheme │ database │ caching │ mtls │
673-
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼──────────┼───────────────────────────────────────────────────────────────┤
674-
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ PostgreSQL │ neondb │ enabled │ │
675-
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼──────────┼───────────────────────────────────────────────────────────────┤
676-
│ yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy │ new-db │ dbuser │ www.google.com │ 3211 │ PostgreSQL │ mydb │ disabled │ │
677-
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼──────────┼───────────────────────────────────────────────────────────────┤
678-
│ zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz │ new-db-mtls │ pg-mtls │ www.mtls.com │ 3212 │ │ mydb-mtls │ enabled │ {\\"ca_certificate_uuid\\":\\"1234\\",\\"mtls_certificate_uuid\\":\\"1234\\"} │
679-
└──────────────────────────────────────┴─────────────┴─────────┴────────────────┴──────┴────────────┴───────────┴──────────┴───────────────────────────────────────────────────────────────┘"
764+
┌──────────────────────────────────────┬─────────────┬─────────┬────────────────┬──────┬────────────┬───────────┬──────────┬───────────────────────────────────────────────────────────────────────────────────
765+
│ id │ name │ user │ host │ port │ scheme │ database │ caching │ mtls
766+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼──────────┼───────────────────────────────────────────────────────────────────────────────────
767+
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ PostgreSQL │ neondb │ enabled │
768+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼──────────┼───────────────────────────────────────────────────────────────────────────────────
769+
│ yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy │ new-db │ dbuser │ www.google.com │ 3211 │ PostgreSQL │ mydb │ disabled │
770+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼──────────┼───────────────────────────────────────────────────────────────────────────────────
771+
│ zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz │ new-db-mtls │ pg-mtls │ www.mtls.com │ 3212 │ │ mydb-mtls │ enabled │ {\\"ca_certificate_id\\":\\"1234\\",\\"mtls_certificate_id\\":\\"1234\\",\\"sslmode\\":\\"verify-full\\"} │
772+
└──────────────────────────────────────┴─────────────┴─────────┴────────────────┴──────┴────────────┴───────────┴──────────┴───────────────────────────────────────────────────────────────────────────────────┘"
680773
`);
681774
});
682775

@@ -985,13 +1078,14 @@ describe("hyperdrive commands", () => {
9851078
it("should handle updating a hyperdrive config's mtls configuration", async () => {
9861079
const reqProm = mockHyperdriveUpdate();
9871080
await runWrangler(
988-
"hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --ca-certificate-uuid=2345 --mtls-certificate-uuid=234"
1081+
"hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --ca-certificate-id=2345 --mtls-certificate-id=234 --sslmode=verify-full"
9891082
);
9901083
await expect(reqProm).resolves.toMatchInlineSnapshot(`
9911084
Object {
9921085
"mtls": Object {
993-
"ca_certificate_uuid": "2345",
994-
"mtls_certificate_uuid": "234",
1086+
"ca_certificate_id": "2345",
1087+
"mtls_certificate_id": "234",
1088+
"sslmode": "verify-full",
9951089
},
9961090
}
9971091
`);
@@ -1009,8 +1103,9 @@ describe("hyperdrive commands", () => {
10091103
\\"user\\": \\"test\\"
10101104
},
10111105
\\"mtls\\": {
1012-
\\"ca_certificate_uuid\\": \\"2345\\",
1013-
\\"mtls_certificate_uuid\\": \\"234\\"
1106+
\\"ca_certificate_id\\": \\"2345\\",
1107+
\\"mtls_certificate_id\\": \\"234\\",
1108+
\\"sslmode\\": \\"verify-full\\"
10141109
}
10151110
}"
10161111
`);
@@ -1078,8 +1173,9 @@ function mockHyperdriveGetListOrDelete() {
10781173
scheme: "pg-mtls",
10791174
},
10801175
mtls: {
1081-
ca_certificate_uuid: "1234",
1082-
mtls_certificate_uuid: "1234",
1176+
ca_certificate_id: "1234",
1177+
mtls_certificate_id: "1234",
1178+
sslmode: "verify-full",
10831179
},
10841180
},
10851181
],
@@ -1131,8 +1227,8 @@ function mockHyperdriveUpdate(): Promise<PatchHyperdriveBody> {
11311227
}
11321228
const mtls = defaultConfig.mtls;
11331229
if (mtls && reqBody.mtls) {
1134-
mtls.ca_certificate_uuid = reqBody.mtls.ca_certificate_uuid;
1135-
mtls.mtls_certificate_uuid = reqBody.mtls.mtls_certificate_uuid;
1230+
mtls.ca_certificate_id = reqBody.mtls.ca_certificate_id;
1231+
mtls.mtls_certificate_id = reqBody.mtls.mtls_certificate_id;
11361232
}
11371233

11381234
return HttpResponse.json(

packages/wrangler/src/hyperdrive/client.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,13 @@ export type PatchHyperdriveBody = {
8585
};
8686

8787
export type Mtls = {
88-
ca_certificate_uuid?: string;
89-
mtls_certificate_uuid?: string;
88+
ca_certificate_id?: string;
89+
mtls_certificate_id?: string;
90+
sslmode?: string;
9091
};
9192

93+
export const Sslmode = ["require", "verify-ca", "verify-full"];
94+
9295
export async function createConfig(
9396
config: Config,
9497
body: CreateUpdateHyperdriveBody

packages/wrangler/src/hyperdrive/index.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,23 @@ export function upsertOptions<T>(yargs: Argv<T>) {
117117
describe:
118118
"Indicates the number of seconds cache may serve the response after it becomes stale, cannot be set when caching is disabled",
119119
},
120-
"ca-certificate-uuid": {
120+
"ca-certificate-id": {
121+
alias: "ca-certificate-uuid",
121122
type: "string",
122123
describe:
123124
"Sets custom CA certificate when connecting to origin database. Must be valid UUID of already uploaded CA certificate.",
124125
},
125-
"mtls-certificate-uuid": {
126+
"mtls-certificate-id": {
127+
alias: "mtls-certificate-uuid",
126128
type: "string",
127129
describe:
128130
"Sets custom mTLS client certificates when connecting to origin database. Must be valid UUID of already uploaded public/private key certificates.",
129131
},
132+
sslmode: {
133+
type: "string",
134+
choices: ["require", "verify-ca", "verify-full"],
135+
describe: "Sets CA sslmode for connecting to database.",
136+
},
130137
})
131138
.group(
132139
["connection-string"],
@@ -321,13 +328,26 @@ export function getMtlsFromArgs(
321328
args: StrictYargsOptionsToInterface<typeof upsertOptions>
322329
): Mtls | undefined {
323330
const mtls = {
324-
ca_certificate_uuid: args.caCertificateUuid,
325-
mtls_certificate_uuid: args.mtlsCertificateUuid,
331+
ca_certificate_id: args.caCertificateId,
332+
mtls_certificate_id: args.mtlsCertificateId,
333+
sslmode: args.sslmode,
326334
};
327335

328336
if (JSON.stringify(mtls) === "{}") {
329337
return undefined;
330338
} else {
339+
if (mtls.sslmode == "require" && mtls.ca_certificate_id?.trim()) {
340+
throw new UserError("CA not allowed when sslmode = 'require' is set");
341+
}
342+
343+
if (
344+
(mtls.sslmode == "verify-ca" || mtls.sslmode == "verify-full") &&
345+
!mtls.ca_certificate_id?.trim()
346+
) {
347+
throw new UserError(
348+
"CA required when sslmode = 'verify-ca' or 'verify-full' is set"
349+
);
350+
}
331351
return mtls;
332352
}
333353
}

0 commit comments

Comments
 (0)