oracledb 6.8.0 → 6.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -3
- package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqMessage.js +10 -1
- package/lib/configProviders/file.js +72 -0
- package/lib/connection.js +87 -2
- package/lib/dbObject.js +9 -0
- package/lib/errors.js +56 -31
- package/lib/impl/connection.js +9 -0
- package/lib/impl/pool.js +10 -1
- package/lib/impl/resultset.js +5 -4
- package/lib/lob.js +9 -1
- package/lib/oracledb.js +129 -16
- package/lib/pool.js +12 -1
- package/lib/poolStatistics.js +3 -1
- package/lib/thin/connection.js +117 -10
- package/lib/thin/dbObject.js +8 -6
- package/lib/thin/lob.js +2 -3
- package/lib/thin/pool.js +105 -28
- package/lib/thin/protocol/capabilities.js +7 -3
- package/lib/thin/protocol/constants.js +29 -1
- package/lib/thin/protocol/messages/auth.js +13 -0
- package/lib/thin/protocol/messages/base.js +98 -9
- package/lib/thin/protocol/messages/dataType.js +2 -1
- package/lib/thin/protocol/messages/execute.js +46 -4
- package/lib/thin/protocol/messages/lobOp.js +5 -22
- package/lib/thin/protocol/messages/logOff.js +0 -1
- package/lib/thin/protocol/messages/sessionRelease.js +0 -1
- package/lib/thin/protocol/messages/transactionSwitch.js +12 -4
- package/lib/thin/protocol/protocol.js +2 -1
- package/lib/thin/sqlnet/connStrategy.js +2 -1
- package/lib/thin/sqlnet/navNodes.js +1 -1
- package/lib/thin/sqlnet/networkSession.js +9 -3
- package/lib/thin/sqlnet/packet.js +2 -1
- package/lib/thin/sqlnet/sessionAtts.js +2 -3
- package/lib/types.js +0 -5
- package/lib/util.js +76 -2
- package/lib/version.js +1 -1
- package/package/install.js +3 -3
- package/package/prunebinaries.js +6 -12
- package/package.json +2 -2
- package/{lib/configProviders/azure.js → plugins/configProviders/azure/index.js} +70 -63
- package/plugins/configProviders/azurevault/index.js +84 -0
- package/{lib → plugins}/configProviders/base.js +13 -3
- package/{lib/configProviders/ociobject.js → plugins/configProviders/ociobject/index.js} +43 -78
- package/plugins/configProviders/ocivault/index.js +100 -0
- package/plugins/token/extensionOci/index.js +71 -35
- package/build/Release/oracledb-6.8.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.8.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.8.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.8.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.8.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.8.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.8.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.8.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.8.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.8.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.8.0-win32-x64.node-buildinfo.txt +0 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2024, Oracle and/or its affiliates.
|
|
2
|
-
|
|
1
|
+
// Copyright (c) 2024, 2025, Oracle and/or its affiliates.
|
|
3
2
|
//-----------------------------------------------------------------------------
|
|
4
3
|
//
|
|
5
4
|
// This software is dual-licensed to you under the Universal Permissive License
|
|
@@ -25,12 +24,11 @@
|
|
|
25
24
|
//-----------------------------------------------------------------------------
|
|
26
25
|
|
|
27
26
|
'use strict';
|
|
28
|
-
|
|
29
27
|
let AppConfigurationClient;
|
|
30
28
|
let ClientSecretCredential, ClientCertificateCredential, ChainedTokenCredential, ManagedIdentityCredential, EnvironmentCredential;
|
|
31
|
-
const
|
|
32
|
-
const { base } = require("
|
|
33
|
-
|
|
29
|
+
const util = require('node:util');
|
|
30
|
+
const { base } = require("../base.js");
|
|
31
|
+
const oracledb = require('oracledb');
|
|
34
32
|
class AzureProvider extends base {
|
|
35
33
|
constructor(provider_arg, urlExtendedPart) {
|
|
36
34
|
super(urlExtendedPart);
|
|
@@ -44,36 +42,16 @@ class AzureProvider extends base {
|
|
|
44
42
|
//---------------------------------------------------------------------------
|
|
45
43
|
init() {
|
|
46
44
|
({ AppConfigurationClient } = require("@azure/app-configuration"));
|
|
47
|
-
({ ClientSecretCredential, ClientCertificateCredential, ChainedTokenCredential, ManagedIdentityCredential, EnvironmentCredential } = require("@azure/identity"));
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
//---------------------------------------------------------------------------
|
|
51
|
-
// _withChainedTokenCredential()
|
|
52
|
-
//
|
|
53
|
-
// Use of ChainedTokenCredential class which provides the ability to link
|
|
54
|
-
// together multiple credential instances to be tried sequentially when authenticating.
|
|
55
|
-
// Default authentication to try when no authentication parameter is given by the user
|
|
56
|
-
//---------------------------------------------------------------------------
|
|
57
|
-
_withChainedTokenCredential() {
|
|
58
|
-
const tokens = [];
|
|
59
|
-
if ((this.paramMap.get("azure_client_secret")))
|
|
60
|
-
tokens.push(new ClientSecretCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_secret")));
|
|
61
|
-
if ((this.paramMap.get("azure_client_certificate_path")))
|
|
62
|
-
tokens.push(new ClientCertificateCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_certificate_path")));
|
|
63
|
-
if ((this.paramMap.get('azure_managed_identity_client_id')))
|
|
64
|
-
tokens.push(this.paramMap.get('azure_managed_identity_client_id'));
|
|
65
|
-
tokens.push(new EnvironmentCredential());
|
|
66
|
-
const credential = new ChainedTokenCredential(...tokens);
|
|
67
|
-
return credential;
|
|
68
45
|
}
|
|
69
46
|
|
|
70
47
|
//---------------------------------------------------------------------------
|
|
71
|
-
//
|
|
48
|
+
// returnCredential()
|
|
72
49
|
//
|
|
73
50
|
// Returns credential to access Azure Config Store on the basis of
|
|
74
51
|
// authentication parameters given by the user.
|
|
75
52
|
//---------------------------------------------------------------------------
|
|
76
|
-
|
|
53
|
+
returnAzureCredential() {
|
|
54
|
+
({ ClientSecretCredential, ClientCertificateCredential, ChainedTokenCredential, ManagedIdentityCredential, EnvironmentCredential } = require("@azure/identity"));
|
|
77
55
|
let auth = null;
|
|
78
56
|
if (this.paramMap.get('authentication')) {
|
|
79
57
|
auth = this.paramMap.get('authentication').toUpperCase();
|
|
@@ -86,82 +64,98 @@ class AzureProvider extends base {
|
|
|
86
64
|
else if (this.paramMap.get("azure_client_secret"))
|
|
87
65
|
return new ClientSecretCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_secret"));
|
|
88
66
|
else
|
|
89
|
-
|
|
67
|
+
throw new Error('Azure service principal authentication requires either a client certificate path or a client secret string');
|
|
90
68
|
} else if (auth == 'AZURE_MANAGED_IDENTITY') {
|
|
91
69
|
return new ManagedIdentityCredential(this.paramMap.get('azure_managed_identity_client_id'));
|
|
92
70
|
} else {
|
|
93
|
-
|
|
71
|
+
const errmsg = util.format('Azure Authentication Failed: The authentication parameter value %s may be incorrect', auth);
|
|
72
|
+
throw new Error(errmsg);
|
|
94
73
|
}
|
|
95
74
|
} else {
|
|
96
75
|
//return default token credential
|
|
97
76
|
return this._withChainedTokenCredential();
|
|
98
77
|
}
|
|
99
78
|
}
|
|
100
|
-
|
|
101
79
|
//---------------------------------------------------------------------------
|
|
102
|
-
//
|
|
80
|
+
// _withChainedTokenCredential()
|
|
103
81
|
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
82
|
+
// Use of ChainedTokenCredential class which provides the ability to link
|
|
83
|
+
// together multiple credential instances to be tried sequentially when authenticating.
|
|
84
|
+
// Default authentication to try when no authentication parameter is given by the user
|
|
106
85
|
//---------------------------------------------------------------------------
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
86
|
+
_withChainedTokenCredential() {
|
|
87
|
+
const tokens = [];
|
|
88
|
+
if ((this.paramMap.get("azure_client_secret")))
|
|
89
|
+
tokens.push(new ClientSecretCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_secret")));
|
|
90
|
+
if ((this.paramMap.get("azure_client_certificate_path")))
|
|
91
|
+
tokens.push(new ClientCertificateCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_certificate_path")));
|
|
92
|
+
if ((this.paramMap.get('azure_managed_identity_client_id')))
|
|
93
|
+
tokens.push(this.paramMap.get('azure_managed_identity_client_id'));
|
|
94
|
+
tokens.push(new EnvironmentCredential());
|
|
95
|
+
const credential = new ChainedTokenCredential(...tokens);
|
|
96
|
+
return credential;
|
|
110
97
|
}
|
|
111
|
-
|
|
112
98
|
async returnConfig() {
|
|
113
99
|
const configObject = {};
|
|
114
100
|
const label = this.paramMap.get("label");
|
|
115
|
-
|
|
101
|
+
try {
|
|
102
|
+
this.credential = await this.returnAzureCredential();
|
|
103
|
+
} catch (err) {
|
|
104
|
+
const errmsg = util.format('Azure Authentication Failed: The authentication parameter value %s may be incorrect', err.message);
|
|
105
|
+
throw new Error(errmsg);
|
|
106
|
+
}
|
|
116
107
|
// azure config store
|
|
117
108
|
const client = new AppConfigurationClient(
|
|
118
109
|
"https://" + this.paramMap.get("appconfigname"), // ex: <https://<your appconfig resource>.azconfig.io>
|
|
119
110
|
this.credential
|
|
120
111
|
);
|
|
121
112
|
// retrieve connect_description
|
|
122
|
-
configObject.connectString = (await this.
|
|
123
|
-
|
|
113
|
+
configObject.connectString = (await this.retrieveParamValueFromAzureConfigurationProvider(client, label, 'connect_descriptor'));
|
|
124
114
|
// retrieve node-oracledb parameters
|
|
125
|
-
|
|
126
|
-
|
|
115
|
+
const params = (await this.retrieveParamValueFromAzureConfigurationProvider(client, label, 'njs'));
|
|
116
|
+
if (params) {
|
|
127
117
|
const obj = JSON.parse(params);
|
|
128
118
|
for (const key in obj) {
|
|
129
119
|
var val = obj[key];
|
|
130
120
|
configObject[key] = val;
|
|
131
121
|
}
|
|
132
|
-
}
|
|
133
|
-
configObject['
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
// retrieve user
|
|
137
|
-
configObject.user = (await this._getConfigurationSetting(client, this.paramMap.get("key") + 'user', label)).value;
|
|
138
|
-
} catch {
|
|
139
|
-
configObject.user = null;
|
|
122
|
+
} else {
|
|
123
|
+
configObject['njs'] = null;
|
|
140
124
|
}
|
|
125
|
+
// retrieve user
|
|
126
|
+
configObject.user = (await this.retrieveParamValueFromAzureConfigurationProvider(client, label, 'user'));
|
|
127
|
+
|
|
141
128
|
//retrieve password
|
|
142
|
-
configObject.password = await this.
|
|
129
|
+
configObject.password = await this.retrieveParamValueFromAzureConfigurationProvider(client, label, 'password');
|
|
130
|
+
|
|
143
131
|
// retrieve wallet_location
|
|
144
|
-
configObject.walletContent = await this.
|
|
132
|
+
configObject.walletContent = await this.retrieveParamValueFromAzureConfigurationProvider(client, label, 'wallet_location');
|
|
133
|
+
|
|
145
134
|
if (configObject.walletContent) {
|
|
146
135
|
//only Pem file supported
|
|
147
136
|
if (!this.isPemFile(configObject.walletContent))
|
|
148
|
-
|
|
137
|
+
throw new Error('Invalid wallet content format. Supported format is PEM');
|
|
149
138
|
}
|
|
150
139
|
return configObject;
|
|
151
140
|
}
|
|
152
|
-
async
|
|
141
|
+
async retrieveParamValueFromAzureConfigurationProvider(client, label, param) {
|
|
153
142
|
let paramJson = null;
|
|
154
143
|
try {
|
|
155
|
-
paramJson = await
|
|
156
|
-
} catch {
|
|
144
|
+
paramJson = (await client.getConfigurationSetting({ key: this.paramMap.get("key") + param, label: label })).value;
|
|
145
|
+
} catch (err) {
|
|
146
|
+
// connect_descriptor must not be null
|
|
147
|
+
if (param == 'connect_descriptor') {
|
|
148
|
+
const errmsg = util.format('Failed to retrieve configuration from Centralized Configuration Provider:\n%s', err.message);
|
|
149
|
+
throw new Error(errmsg);
|
|
150
|
+
}
|
|
157
151
|
return null;
|
|
158
152
|
}
|
|
159
153
|
if (paramJson) {
|
|
160
154
|
let obj;
|
|
161
155
|
try {
|
|
162
|
-
obj = JSON.parse(paramJson
|
|
156
|
+
obj = JSON.parse(paramJson);
|
|
163
157
|
} catch {
|
|
164
|
-
obj = paramJson
|
|
158
|
+
obj = paramJson;
|
|
165
159
|
}
|
|
166
160
|
if (obj.uri) {
|
|
167
161
|
const { SecretClient } = require("@azure/keyvault-secrets");
|
|
@@ -169,10 +163,23 @@ class AzureProvider extends base {
|
|
|
169
163
|
const client1 = new SecretClient(vault_detail[0], this.credential);
|
|
170
164
|
return (await client1.getSecret(vault_detail[1])).value;
|
|
171
165
|
} else {
|
|
172
|
-
return paramJson
|
|
166
|
+
return paramJson;
|
|
173
167
|
}
|
|
174
168
|
}
|
|
175
|
-
|
|
176
169
|
}
|
|
170
|
+
} module.exports = AzureProvider;
|
|
171
|
+
//---------------------------------------------------------------------------
|
|
172
|
+
// hookFn()
|
|
173
|
+
// hookFn will get registered to the driver while loading the plugins
|
|
174
|
+
//---------------------------------------------------------------------------
|
|
175
|
+
async function hookFn(args) {
|
|
176
|
+
const configProvider = new AzureProvider(args.provider_arg, args.urlExtendedPart);
|
|
177
|
+
try {
|
|
178
|
+
configProvider.init();
|
|
179
|
+
} catch (err) {
|
|
180
|
+
const errmsg = util.format('Centralized Config Provider failed to load required libraries. Please install the required libraries.\n %s', err.message);
|
|
181
|
+
throw new Error(errmsg);
|
|
182
|
+
}
|
|
183
|
+
return [await configProvider.returnConfig(), configProvider.credential];
|
|
177
184
|
}
|
|
178
|
-
|
|
185
|
+
oracledb.registerConfigurationProviderHook('azure', hookFn);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Copyright (c) 2025, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// This software is dual-licensed to you under the Universal Permissive License
|
|
6
|
+
// (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
|
|
7
|
+
// 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
|
|
8
|
+
// either license.
|
|
9
|
+
//
|
|
10
|
+
// If you elect to accept the software under the Apache License, Version 2.0,
|
|
11
|
+
// the following applies:
|
|
12
|
+
//
|
|
13
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
14
|
+
// you may not use this file except in compliance with the License.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
+
//
|
|
19
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
20
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
21
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
'use strict';
|
|
27
|
+
|
|
28
|
+
const { base } = require("../base.js");
|
|
29
|
+
const oracledb = require('oracledb');
|
|
30
|
+
const util = require('node:util');
|
|
31
|
+
|
|
32
|
+
let SecretClient;
|
|
33
|
+
class azureVault extends base {
|
|
34
|
+
constructor(provider_arg, urlExtendedPart) {
|
|
35
|
+
super(urlExtendedPart);
|
|
36
|
+
if (provider_arg)
|
|
37
|
+
this._addParam("azuresecreturl", provider_arg);
|
|
38
|
+
}
|
|
39
|
+
init() {
|
|
40
|
+
({SecretClient} = require("@azure/keyvault-secrets"));
|
|
41
|
+
}
|
|
42
|
+
async returnConfig(credential) {
|
|
43
|
+
if (!credential) {
|
|
44
|
+
const azureClass = require('../azure');
|
|
45
|
+
var azureObject = new azureClass();
|
|
46
|
+
azureObject.paramMap = this.paramMap;
|
|
47
|
+
this.credential = await azureObject.returnAzureCredential();
|
|
48
|
+
} else
|
|
49
|
+
this.credential = credential;
|
|
50
|
+
|
|
51
|
+
const vault_detail = await this._parsePwd(this.paramMap.get('azuresecreturl'));
|
|
52
|
+
const client1 = new SecretClient(vault_detail[0], this.credential);
|
|
53
|
+
const resp = (await client1.getSecret(vault_detail[1])).value;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
this.obj = JSON.parse(resp);
|
|
57
|
+
} catch {
|
|
58
|
+
return resp; //when password is of type azurevault
|
|
59
|
+
}
|
|
60
|
+
const userAlias = this.paramMap.get('key'); // alias
|
|
61
|
+
if (userAlias) {
|
|
62
|
+
this.obj = this.obj[userAlias];
|
|
63
|
+
}
|
|
64
|
+
return this.obj;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//---------------------------------------------------------------------------
|
|
68
|
+
// hookFn()
|
|
69
|
+
// hookFn will get registered to the driver while loading the plugins
|
|
70
|
+
//---------------------------------------------------------------------------
|
|
71
|
+
async function hookFn(args) {
|
|
72
|
+
const configProvider = new azureVault(args.provider_arg, args.urlExtendedPart);
|
|
73
|
+
try {
|
|
74
|
+
configProvider.init();
|
|
75
|
+
} catch (err) {
|
|
76
|
+
const errmsg = util.format('Centralized Config Provider failed to load required libraries. Please install the required libraries.\n %s', err.message);
|
|
77
|
+
throw new Error(errmsg);
|
|
78
|
+
}
|
|
79
|
+
if (args.paramMap) {
|
|
80
|
+
configProvider.paramMap = args.paramMap;
|
|
81
|
+
}
|
|
82
|
+
return [await configProvider.returnConfig(args.credential), configProvider.credential];
|
|
83
|
+
}
|
|
84
|
+
oracledb.registerConfigurationProviderHook('azurevault', hookFn);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2024, Oracle and/or its affiliates.
|
|
1
|
+
// // Copyright (c) 2024, 2025, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
//-----------------------------------------------------------------------------
|
|
26
26
|
|
|
27
27
|
'use strict';
|
|
28
|
-
|
|
29
28
|
const pemHeaders = [
|
|
30
29
|
'-----BEGIN CERTIFICATE-----',
|
|
31
30
|
'-----BEGIN PUBLIC KEY-----',
|
|
@@ -72,14 +71,25 @@ class base {
|
|
|
72
71
|
// “uri”:“https://mykeyvault.vault.azure.net/secrets/secretkey”}
|
|
73
72
|
//---------------------------------------------------------------------------
|
|
74
73
|
_parsePwd(str) {
|
|
75
|
-
const vault_uri = new RegExp("(?<vault_url>https://[A-Za-z0-9._-]+)/secrets/(?<secretKey>[A-Za-
|
|
74
|
+
const vault_uri = new RegExp("(?<vault_url>(^(https://))?[A-Za-z0-9._-]+)/secrets/(?<secretKey>[A-Za-z0-9][A-Za-z0-9-/]*)$", 'g');
|
|
76
75
|
const vault_detail = [];
|
|
77
76
|
for (const match of str.matchAll(vault_uri)) {
|
|
78
77
|
vault_detail[0] = match.groups.vault_url;
|
|
79
78
|
vault_detail[1] = match.groups.secretKey;
|
|
80
79
|
}
|
|
80
|
+
if (!vault_detail[0].startsWith('https'))
|
|
81
|
+
vault_detail[0] = 'https://' + vault_detail[0];
|
|
81
82
|
return vault_detail;
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
//---------------------------------------------------------------------------
|
|
86
|
+
// retrieveRegion(objservername)
|
|
87
|
+
//
|
|
88
|
+
// returns region from the given objservername.
|
|
89
|
+
//---------------------------------------------------------------------------
|
|
90
|
+
retrieveRegion(objservername) {
|
|
91
|
+
const arr = objservername.split(".");
|
|
92
|
+
return arr[1].toUpperCase().replaceAll('-', '_');
|
|
93
|
+
}
|
|
84
94
|
}
|
|
85
95
|
module.exports = {base};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2024, Oracle and/or its affiliates.
|
|
1
|
+
// Copyright (c) 2024, 2025, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -25,17 +25,20 @@
|
|
|
25
25
|
//-----------------------------------------------------------------------------
|
|
26
26
|
|
|
27
27
|
'use strict';
|
|
28
|
-
const errors = require("../errors.js");
|
|
29
|
-
const { base } = require("./base.js");
|
|
30
|
-
const fs = require('fs');
|
|
31
28
|
|
|
29
|
+
const { base } = require("../base.js");
|
|
30
|
+
const oracledb = require('oracledb');
|
|
31
|
+
const util = require('node:util');
|
|
32
|
+
const fs = require('fs');
|
|
32
33
|
const cloud_net_naming_pattern_oci = new RegExp("(?<objservername>[A-Za-z0-9._-]+)/n/" + "(?<namespace>[A-Za-z0-9._-]+)/b/" + "(?<bucketname>[A-Za-z0-9._-]+)/o/" + "(?<filename>[A-Za-z0-9._-]+)$");
|
|
33
34
|
// object to store module references that will be populated by init()
|
|
34
35
|
const oci = {};
|
|
35
36
|
class OCIProvider extends base {
|
|
36
37
|
constructor(provider_arg, urlExtendedPart) {
|
|
37
38
|
super(urlExtendedPart);
|
|
38
|
-
|
|
39
|
+
let match;
|
|
40
|
+
if (provider_arg)
|
|
41
|
+
match = provider_arg.match(cloud_net_naming_pattern_oci);
|
|
39
42
|
if (match) {
|
|
40
43
|
this._addParam("objservername", match.groups.objservername);
|
|
41
44
|
this._addParam("namespace", match.groups.namespace);
|
|
@@ -66,14 +69,14 @@ class OCIProvider extends base {
|
|
|
66
69
|
}
|
|
67
70
|
return Buffer.concat(chunks).toString("utf-8");
|
|
68
71
|
}
|
|
69
|
-
|
|
70
72
|
//---------------------------------------------------------------------------
|
|
71
|
-
//
|
|
73
|
+
// returnOCICredential()
|
|
72
74
|
//
|
|
73
|
-
// Returns credential to access OCI Object Store on the basis of
|
|
75
|
+
// Returns credential to access OCI Object Store/OCI Vault on the basis of
|
|
74
76
|
// authentication parameters given by the user.
|
|
77
|
+
// Used in OCI/LOCALJSONFILE/OCIVAULT Config Providers
|
|
75
78
|
//---------------------------------------------------------------------------
|
|
76
|
-
async
|
|
79
|
+
async returnOCICredential() {
|
|
77
80
|
let provider = null;
|
|
78
81
|
let auth = null;
|
|
79
82
|
if (this.paramMap.get('authentication')) {
|
|
@@ -82,11 +85,13 @@ class OCIProvider extends base {
|
|
|
82
85
|
// authentication parameter given and its not OCI_DEFAULT
|
|
83
86
|
if (auth && !(auth == 'OCI_DEFAULT')) {
|
|
84
87
|
if (auth == 'OCI_INSTANCE_PRINCIPAL') {
|
|
85
|
-
provider = await
|
|
88
|
+
provider = await oci.common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
|
|
86
89
|
} else if (auth == 'OCI_RESOURCE_PRINCIPAL') {
|
|
87
90
|
provider = await new oci.common.ResourcePrincipalAuthenticationDetailsProvider.builder();
|
|
88
|
-
} else
|
|
89
|
-
|
|
91
|
+
} else {
|
|
92
|
+
const errmsg = util.format('OCI authentication failed: The authentication parameter value %s may be incorrect', auth);
|
|
93
|
+
throw new Error(errmsg);
|
|
94
|
+
}
|
|
90
95
|
} else {
|
|
91
96
|
// default authentication
|
|
92
97
|
try {
|
|
@@ -102,14 +107,18 @@ class OCIProvider extends base {
|
|
|
102
107
|
}
|
|
103
108
|
// authentication parameters are directly given in the connectString
|
|
104
109
|
const publicKey = fs.readFileSync(this.paramMap.get('oci_key_file'), { encoding: "utf8" });
|
|
105
|
-
|
|
110
|
+
let region;
|
|
111
|
+
if (this.paramMap.get('objectservername'))
|
|
112
|
+
region = this.retrieveRegion(this.paramMap.get('objservername'));
|
|
113
|
+
else
|
|
114
|
+
region = oci.common.Region[(this.paramMap.get("region").replace(/-/g, '_')).toUpperCase()];
|
|
106
115
|
provider = new oci.common.SimpleAuthenticationDetailsProvider(
|
|
107
116
|
this.paramMap.get("oci_tenancy"),
|
|
108
117
|
this.paramMap.get("oci_user"),
|
|
109
118
|
this.paramMap.get("oci_fingerprint"),
|
|
110
119
|
publicKey,
|
|
111
120
|
undefined,
|
|
112
|
-
|
|
121
|
+
region
|
|
113
122
|
);
|
|
114
123
|
}
|
|
115
124
|
}
|
|
@@ -123,8 +132,7 @@ class OCIProvider extends base {
|
|
|
123
132
|
// parses and gets password field stored in OCI/Azure Vault
|
|
124
133
|
//---------------------------------------------------------------------------
|
|
125
134
|
async returnConfig() {
|
|
126
|
-
|
|
127
|
-
this.credential = await this._returnCredential();
|
|
135
|
+
this.credential = await this.returnOCICredential();
|
|
128
136
|
// oci object store
|
|
129
137
|
const client_oci = new (oci.objectstorage).ObjectStorageClient({
|
|
130
138
|
authenticationDetailsProvider: this.credential
|
|
@@ -142,70 +150,27 @@ class OCIProvider extends base {
|
|
|
142
150
|
if (userAlias) {
|
|
143
151
|
this.obj = this.obj[userAlias];
|
|
144
152
|
}
|
|
145
|
-
|
|
146
|
-
const params = this.obj[pmSection];
|
|
147
|
-
for (const key in params) {
|
|
148
|
-
var val = params[key];
|
|
149
|
-
configObject[key] = val;
|
|
150
|
-
}
|
|
151
|
-
configObject.connectString = this.obj.connect_descriptor;
|
|
152
|
-
configObject.user = this.obj.user;
|
|
153
|
-
if (this.obj.password) {
|
|
154
|
-
configObject.password = await this.retrieveParamValueFromVault('password');
|
|
155
|
-
}
|
|
156
|
-
if (this.obj.wallet_location) {
|
|
157
|
-
// retrieve wallet_location
|
|
158
|
-
configObject.walletContent = await this.retrieveParamValueFromVault('wallet_location');
|
|
159
|
-
//only Pem file supported
|
|
160
|
-
if (!this.isPemFile(configObject.walletContent))
|
|
161
|
-
errors.throwErr(errors.ERR_WALLET_TYPE_NOT_SUPPORTED);
|
|
162
|
-
}
|
|
163
|
-
return configObject;
|
|
153
|
+
return this.obj;
|
|
164
154
|
}
|
|
155
|
+
}module.exports = OCIProvider;
|
|
165
156
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
157
|
+
//---------------------------------------------------------------------------
|
|
158
|
+
// hookFn()
|
|
159
|
+
// hookFn will get registered to the driver while loading the plugins
|
|
160
|
+
//---------------------------------------------------------------------------
|
|
161
|
+
async function hookFn(args) {
|
|
162
|
+
const configProvider = new OCIProvider(args.provider_arg, args.urlExtendedPart);
|
|
163
|
+
try {
|
|
164
|
+
configProvider.init();
|
|
165
|
+
} catch (err) {
|
|
166
|
+
const errmsg = util.format('Centralized Config Provider failed to load required libraries. Please install the required libraries.\n %s', err.message);
|
|
167
|
+
throw new Error(errmsg);
|
|
174
168
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const {ClientSecretCredential, ClientCertificateCredential} = require("@azure/identity");
|
|
181
|
-
if (this.obj[param].authentication.azure_client_secret)
|
|
182
|
-
this.credential = new ClientSecretCredential(this.obj[param].authentication.azure_tenant_id, this.obj[param].authentication.azure_client_id, this.obj[param].authentication.azure_client_secret);
|
|
183
|
-
else if (this.obj[param].authentication.azure_client_certificate_path)
|
|
184
|
-
this.credential = new ClientCertificateCredential(this.obj[param].authentication.azure_tenant_id, this.obj[param].authentication.azure_client_id, this.obj[param].authentication.azure_client_certificate_path);
|
|
185
|
-
else
|
|
186
|
-
errors.throwErr(errors.ERR_AZURE_VAULT_AUTH_FAILED);
|
|
187
|
-
const vault_detail = await this._parsePwd(this.obj[param].value);
|
|
188
|
-
const client1 = new SecretClient(vault_detail[0], this.credential);
|
|
189
|
-
return (await client1.getSecret(vault_detail[1])).value;
|
|
190
|
-
} else {
|
|
191
|
-
errors.throwErr(errors.ERR_AZURE_VAULT_AUTH_FAILED);
|
|
192
|
-
}
|
|
193
|
-
} else if (this.obj[param].type == "ocivault") {
|
|
194
|
-
const secrets = require('oci-secrets');
|
|
195
|
-
const secretClientOci = new secrets.SecretsClient({
|
|
196
|
-
authenticationDetailsProvider: this.credential
|
|
197
|
-
});
|
|
198
|
-
const getSecretBundleRequest = {
|
|
199
|
-
secretId: this.obj[param].value
|
|
200
|
-
};
|
|
201
|
-
const getSecretBundleResponse = await secretClientOci.getSecretBundle(getSecretBundleRequest);
|
|
202
|
-
const base64content = getSecretBundleResponse.secretBundle.secretBundleContent.content;
|
|
203
|
-
// decode base64 content
|
|
204
|
-
const returnVal = Buffer.from(base64content, "base64").toString("utf-8");
|
|
205
|
-
return returnVal;
|
|
206
|
-
} else {
|
|
207
|
-
return this.obj[param];
|
|
208
|
-
}
|
|
169
|
+
try {
|
|
170
|
+
return [await configProvider.returnConfig(), configProvider.credential];
|
|
171
|
+
} catch (err) {
|
|
172
|
+
const errmsg = util.format('Failed to retrieve configuration from Centralized Configuration Provider:\n %s', err.message);
|
|
173
|
+
throw new Error(errmsg);
|
|
209
174
|
}
|
|
210
175
|
}
|
|
211
|
-
|
|
176
|
+
oracledb.registerConfigurationProviderHook('ociobject', hookFn);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Copyright (c) 2025, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// This software is dual-licensed to you under the Universal Permissive License
|
|
6
|
+
// (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
|
|
7
|
+
// 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
|
|
8
|
+
// either license.
|
|
9
|
+
//
|
|
10
|
+
// If you elect to accept the software under the Apache License, Version 2.0,
|
|
11
|
+
// the following applies:
|
|
12
|
+
//
|
|
13
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
14
|
+
// you may not use this file except in compliance with the License.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
+
//
|
|
19
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
20
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
21
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
'use strict';
|
|
27
|
+
|
|
28
|
+
const { base } = require("../base.js");
|
|
29
|
+
const oracledb = require('oracledb');
|
|
30
|
+
const util = require('node:util');
|
|
31
|
+
const oci = {};
|
|
32
|
+
class ociVault extends base {
|
|
33
|
+
constructor(provider_arg, urlExtendedPart) {
|
|
34
|
+
super(urlExtendedPart);
|
|
35
|
+
if (provider_arg)
|
|
36
|
+
this._addParam("ocidvault", provider_arg);
|
|
37
|
+
}
|
|
38
|
+
init() {
|
|
39
|
+
oci.secrets = require('oci-secrets');
|
|
40
|
+
oci.common = require('oci-common');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//---------------------------------------------------------------------------
|
|
44
|
+
// returnConfig()
|
|
45
|
+
//
|
|
46
|
+
// Returns config stored in the OCI Vault
|
|
47
|
+
// parses it and gets password field stored in OCI/Azure Vault
|
|
48
|
+
//---------------------------------------------------------------------------
|
|
49
|
+
async returnConfig(credential) {
|
|
50
|
+
if (!credential) {
|
|
51
|
+
const ociObjectClass = require('../ociobject');
|
|
52
|
+
const ociObject = new ociObjectClass();
|
|
53
|
+
ociObject.paramMap = this.paramMap;
|
|
54
|
+
ociObject.paramMap.set('authentication', '');
|
|
55
|
+
ociObject.init();
|
|
56
|
+
this.credential = await ociObject.returnOCICredential();
|
|
57
|
+
} else
|
|
58
|
+
this.credential = credential;
|
|
59
|
+
|
|
60
|
+
const secretClientOci = new oci.secrets.SecretsClient({
|
|
61
|
+
authenticationDetailsProvider: this.credential
|
|
62
|
+
});
|
|
63
|
+
const getSecretBundleRequest = {
|
|
64
|
+
secretId: this.paramMap.get("ocidvault")
|
|
65
|
+
};
|
|
66
|
+
const getSecretBundleResponse = await secretClientOci.getSecretBundle(getSecretBundleRequest);
|
|
67
|
+
const base64content = getSecretBundleResponse.secretBundle.secretBundleContent.content;
|
|
68
|
+
// decode base64 content
|
|
69
|
+
const resp = Buffer.from(base64content, "base64").toString("ascii");
|
|
70
|
+
// Entire object we get from OCI Vault
|
|
71
|
+
try {
|
|
72
|
+
this.obj = JSON.parse(resp);
|
|
73
|
+
} catch {
|
|
74
|
+
return resp; // when password is of type ocivault
|
|
75
|
+
}
|
|
76
|
+
const userAlias = this.paramMap.get('key'); // alias
|
|
77
|
+
if (userAlias) {
|
|
78
|
+
this.obj = this.obj[userAlias];
|
|
79
|
+
}
|
|
80
|
+
return this.obj;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//---------------------------------------------------------------------------
|
|
84
|
+
// hookFn()
|
|
85
|
+
// hookFn will get registered to the driver while loading the plugins
|
|
86
|
+
//---------------------------------------------------------------------------
|
|
87
|
+
async function hookFn(args) {
|
|
88
|
+
const configProvider = new ociVault(args.provider_arg, args.urlExtendedPart);
|
|
89
|
+
try {
|
|
90
|
+
configProvider.init();
|
|
91
|
+
} catch (err) {
|
|
92
|
+
const errmsg = util.format('Centralized Config Provider failed to load required libraries. Please install the required libraries.\n %s', err.message);
|
|
93
|
+
throw new Error(errmsg);
|
|
94
|
+
}
|
|
95
|
+
if (args.paramMap) {
|
|
96
|
+
configProvider.paramMap = args.paramMap;
|
|
97
|
+
}
|
|
98
|
+
return [await configProvider.returnConfig(args.credential), configProvider.credential];
|
|
99
|
+
}
|
|
100
|
+
oracledb.registerConfigurationProviderHook('ocivault', hookFn);
|