Skip to content

Commit 64a3d17

Browse files
committed
feat: Support Private CA for server certificates.
test: Integration test for Customer Private CA CAS instance.
1 parent 25f5ccd commit 64a3d17

File tree

6 files changed

+100
-17
lines changed

6 files changed

+100
-17
lines changed

.github/workflows/tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ jobs:
161161
POSTGRES_DB:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_DB
162162
POSTGRES_CAS_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CAS_CONNECTION_NAME
163163
POSTGRES_CAS_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CAS_PASS
164+
POSTGRES_CUSTOMER_CAS_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_CONNECTION_NAME
165+
POSTGRES_CUSTOMER_CAS_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_PASS
164166
SQLSERVER_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_CONNECTION_NAME
165167
SQLSERVER_USER:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_USER
166168
SQLSERVER_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_PASS
@@ -188,6 +190,8 @@ jobs:
188190
POSTGRES_DB: "${{ steps.secrets.outputs.POSTGRES_DB }}"
189191
POSTGRES_CAS_CONNECTION_NAME: "${{ steps.secrets.outputs.POSTGRES_CAS_CONNECTION_NAME }}"
190192
POSTGRES_CAS_PASS: "${{ steps.secrets.outputs.POSTGRES_CAS_PASS }}"
193+
POSTGRES_CUSTOMER_CAS_CONNECTION_NAME: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_CONNECTION_NAME }}"
194+
POSTGRES_CUSTOMER_CAS_PASS: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_PASS }}"
191195
SQLSERVER_CONNECTION_NAME: "${{ steps.secrets.outputs.SQLSERVER_CONNECTION_NAME }}"
192196
SQLSERVER_USER: "${{ steps.secrets.outputs.SQLSERVER_USER }}"
193197
SQLSERVER_PASS: "${{ steps.secrets.outputs.SQLSERVER_PASS }}"

package-lock.json

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/socket.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,26 @@ export function validateCertificate(
3636
dnsName: string
3737
) {
3838
return (hostname: string, cert: tls.PeerCertificate): Error | undefined => {
39-
if (serverCaMode === 'GOOGLE_MANAGED_CAS_CA') {
39+
if (!serverCaMode || serverCaMode !== 'GOOGLE_MANAGED_INTERNAL_CA') {
40+
// Legacy CA Mode
41+
if (!cert || !cert.subject) {
42+
return new CloudSQLConnectorError({
43+
message: 'No certificate to verify',
44+
code: 'ENOSQLADMINVERIFYCERT',
45+
});
46+
}
47+
const expectedCN = `${instanceInfo.projectId}:${instanceInfo.instanceId}`;
48+
if (cert.subject.CN !== expectedCN) {
49+
return new CloudSQLConnectorError({
50+
message: `Certificate had CN ${cert.subject.CN}, expected ${expectedCN}`,
51+
code: 'EBADSQLADMINVERIFYCERT',
52+
});
53+
}
54+
return undefined;
55+
} else {
56+
// Standard TLS Verify Full hostname verification using SAN
4057
return tls.checkServerIdentity(dnsName, cert);
4158
}
42-
if (!cert || !cert.subject) {
43-
return new CloudSQLConnectorError({
44-
message: 'No certificate to verify',
45-
code: 'ENOSQLADMINVERIFYCERT',
46-
});
47-
}
48-
const expectedCN = `${instanceInfo.projectId}:${instanceInfo.instanceId}`;
49-
if (cert.subject.CN !== expectedCN) {
50-
return new CloudSQLConnectorError({
51-
message: `Certificate had CN ${cert.subject.CN}, expected ${expectedCN}`,
52-
code: 'EBADSQLADMINVERIFYCERT',
53-
});
54-
}
55-
return undefined;
5659
};
5760
}
5861

system-test/pg-connect.cjs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,29 @@ t.test(
9393
connector.close();
9494
}
9595
);
96+
97+
t.test(
98+
'open connection to Customer Private CAS-based CA instance and retrieves standard pg tables',
99+
async t => {
100+
const connector = new Connector();
101+
const clientOpts = await connector.getOptions({
102+
instanceConnectionName: String(
103+
process.env.POSTGRES_CUSTOMER_CAS_CONNECTION_NAME
104+
),
105+
});
106+
const client = new Client({
107+
...clientOpts,
108+
user: String(process.env.POSTGRES_USER),
109+
password: String(process.env.POSTGRES_CUSTOMER_CAS_PASS),
110+
database: String(process.env.POSTGRES_DB),
111+
});
112+
client.connect();
113+
const {
114+
rows: [result],
115+
} = await client.query('SELECT NOW();');
116+
const returnedDate = result['now'];
117+
t.ok(returnedDate.getTime(), 'should have valid returned date object');
118+
await client.end();
119+
connector.close();
120+
}
121+
);

system-test/pg-connect.mjs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,29 @@ t.test(
9393
connector.close();
9494
}
9595
);
96+
97+
t.test(
98+
'open connection to Customer Private CAS-based CA instance and retrieves standard pg tables',
99+
async t => {
100+
const connector = new Connector();
101+
const clientOpts = await connector.getOptions({
102+
instanceConnectionName: String(
103+
process.env.POSTGRES_CUSTOMER_CAS_CONNECTION_NAME
104+
),
105+
});
106+
const client = new Client({
107+
...clientOpts,
108+
user: String(process.env.POSTGRES_USER),
109+
password: String(process.env.POSTGRES_CUSTOMER_CAS_PASS),
110+
database: String(process.env.POSTGRES_DB),
111+
});
112+
client.connect();
113+
const {
114+
rows: [result],
115+
} = await client.query('SELECT NOW();');
116+
const returnedDate = result['now'];
117+
t.ok(returnedDate.getTime(), 'should have valid returned date object');
118+
await client.end();
119+
connector.close();
120+
}
121+
);

system-test/pg-connect.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,29 @@ t.test(
9393
connector.close();
9494
}
9595
);
96+
97+
t.test(
98+
'open connection to Customer Private CAS-based CA instance and retrieves standard pg tables',
99+
async t => {
100+
const connector = new Connector();
101+
const clientOpts = await connector.getOptions({
102+
instanceConnectionName: String(
103+
process.env.POSTGRES_CUSTOMER_CAS_CONNECTION_NAME
104+
),
105+
});
106+
const client = new Client({
107+
...clientOpts,
108+
user: String(process.env.POSTGRES_USER),
109+
password: String(process.env.POSTGRES_CUSTOMER_CAS_PASS),
110+
database: String(process.env.POSTGRES_DB),
111+
});
112+
client.connect();
113+
const {
114+
rows: [result],
115+
} = await client.query('SELECT NOW();');
116+
const returnedDate = result['now'];
117+
t.ok(returnedDate.getTime(), 'should have valid returned date object');
118+
await client.end();
119+
connector.close();
120+
}
121+
);

0 commit comments

Comments
 (0)