Skip to content

Commit bedde48

Browse files
committed
refactor: Use new ConnectSettings.DnsNames field to validate the server certificate's server name.
1 parent cb1716e commit bedde48

File tree

6 files changed

+59
-26
lines changed

6 files changed

+59
-26
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@
8383
"url": "git+https://github.com/GoogleCloudPlatform/cloud-sql-nodejs-connector"
8484
},
8585
"dependencies": {
86-
"@googleapis/sqladmin": "^24.0.0",
86+
"@googleapis/sqladmin": "^27.0.0",
8787
"gaxios": "^6.1.1",
8888
"google-auth-library": "^9.2.0",
8989
"p-throttle": "^7.0.0"
9090
}
91-
}
91+
}

src/connector.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ export class Connector {
232232
port,
233233
privateKey,
234234
serverCaCert,
235-
serverCaMode,
236235
dnsName,
237236
} = cloudSqlInstance;
238237

@@ -251,8 +250,8 @@ export class Connector {
251250
port,
252251
privateKey,
253252
serverCaCert,
254-
serverCaMode,
255-
dnsName: instanceInfo.domainName || dnsName, // use the configured domain name, or the instance dnsName.
253+
instanceDnsName: dnsName,
254+
serverName: instanceInfo.domainName || dnsName, // use the configured domain name, or the instance dnsName.
256255
});
257256
tlsSocket.once('error', () => {
258257
cloudSqlInstance.forceRefresh();

src/socket.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ interface SocketOptions {
2626
instanceInfo: InstanceConnectionInfo;
2727
privateKey: string;
2828
serverCaCert: SslCert;
29-
serverCaMode: string;
30-
dnsName: string;
29+
instanceDnsName: string;
30+
serverName: string;
3131
}
3232

3333
export function validateCertificate(
3434
instanceInfo: InstanceConnectionInfo,
35-
serverCaMode: string,
36-
dnsName: string
35+
instanceDnsName: string,
36+
serverName: string
3737
) {
3838
return (hostname: string, cert: tls.PeerCertificate): Error | undefined => {
39-
if (!serverCaMode || serverCaMode === 'GOOGLE_MANAGED_INTERNAL_CA') {
39+
if (!instanceDnsName) {
4040
// Legacy CA Mode
4141
if (!cert || !cert.subject) {
4242
return new CloudSQLConnectorError({
@@ -54,7 +54,7 @@ export function validateCertificate(
5454
return undefined;
5555
} else {
5656
// Standard TLS Verify Full hostname verification using SAN
57-
return tls.checkServerIdentity(dnsName, cert);
57+
return tls.checkServerIdentity(serverName, cert);
5858
}
5959
};
6060
}
@@ -66,8 +66,8 @@ export function getSocket({
6666
instanceInfo,
6767
privateKey,
6868
serverCaCert,
69-
serverCaMode,
70-
dnsName,
69+
instanceDnsName,
70+
serverName,
7171
}: SocketOptions): tls.TLSSocket {
7272
const socketOpts = {
7373
host,
@@ -80,8 +80,8 @@ export function getSocket({
8080
}),
8181
checkServerIdentity: validateCertificate(
8282
instanceInfo,
83-
serverCaMode,
84-
dnsName
83+
instanceDnsName,
84+
serverName
8585
),
8686
};
8787
const tlsSocket = tls.connect(socketOpts);

src/sqladmin-fetcher.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ export class SQLAdminFetcher {
132132
private parseIpAddresses(
133133
ipResponse: sqladmin_v1beta4.Schema$IpMapping[] | undefined,
134134
dnsName: string | null | undefined,
135+
dnsNames: sqladmin_v1beta4.Schema$DnsNameMapping[] | null | undefined,
135136
pscEnabled: boolean | null | undefined
136137
): IpAddresses {
137138
const ipAddresses: IpAddresses = {};
@@ -149,8 +150,24 @@ export class SQLAdminFetcher {
149150
// Resolve dnsName into IP address for PSC enabled instances.
150151
// Note that we have to check for PSC enablement because CAS instances
151152
// also set the dnsName field.
152-
if (dnsName && pscEnabled) {
153-
ipAddresses.psc = dnsName;
153+
if (pscEnabled) {
154+
// Search the dns_names field for the PSC DNS Name.
155+
if (dnsNames) {
156+
for (const dnm of dnsNames) {
157+
if (
158+
dnm.name &&
159+
dnm.connectionType === 'PRIVATE_SERVICE_CONNECT' &&
160+
dnm.dnsScope === 'INSTANCE'
161+
) {
162+
ipAddresses.psc = dnm.name;
163+
break;
164+
}
165+
}
166+
}
167+
// If the psc dns name was not found, use the legacy dns_name field
168+
if (!ipAddresses.psc && dnsName) {
169+
ipAddresses.psc = dnsName;
170+
}
154171
}
155172

156173
if (!ipAddresses.public && !ipAddresses.private && !ipAddresses.psc) {
@@ -188,6 +205,7 @@ export class SQLAdminFetcher {
188205
const ipAddresses = this.parseIpAddresses(
189206
res.data.ipAddresses,
190207
res.data.dnsName,
208+
res.data.dnsNames,
191209
res.data.pscEnabled
192210
);
193211

@@ -214,6 +232,16 @@ export class SQLAdminFetcher {
214232
}
215233

216234
cleanGaxiosConfig();
235+
// Find a DNS name to use to validate the certificate from the dns_names field. Any
236+
// name in the list may be used to validate the server TLS certificate.
237+
// Fall back to legacy dns_name field if necessary.
238+
let serverName = null;
239+
if (res.data.dnsNames && res.data.dnsNames.length > 0) {
240+
serverName = res.data.dnsNames[0].name;
241+
}
242+
if (serverName === null) {
243+
serverName = res.data.dnsName;
244+
}
217245

218246
return {
219247
ipAddresses,
@@ -222,7 +250,7 @@ export class SQLAdminFetcher {
222250
expirationTime: serverCaCert.expirationTime,
223251
},
224252
serverCaMode: res.data.serverCaMode || '',
225-
dnsName: res.data.dnsName || '',
253+
dnsName: serverName || '',
226254
};
227255
}
228256

test/sqladmin-fetcher.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,13 @@ const mockSQLAdminGetInstanceMetadata = (
9898

9999
sqlAdminClient.get = () => ({
100100
data: {
101-
dnsName: 'abcde.12345.us-central1.sql.goog',
101+
dnsNames: [
102+
{
103+
name: 'abcde.12345.us-central1.sql.goog',
104+
connectionType: 'PRIVATE_SERVICE_CONNECT',
105+
dnsScope: 'INSTANCE',
106+
},
107+
],
102108
ipAddresses: [
103109
{
104110
type: 'PRIMARY',

0 commit comments

Comments
 (0)