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.
Files changed (67) hide show
  1. package/README.md +39 -3
  2. package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
  3. package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
  5. package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.9.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/lib/aqMessage.js +10 -1
  14. package/lib/configProviders/file.js +72 -0
  15. package/lib/connection.js +87 -2
  16. package/lib/dbObject.js +9 -0
  17. package/lib/errors.js +56 -31
  18. package/lib/impl/connection.js +9 -0
  19. package/lib/impl/pool.js +10 -1
  20. package/lib/impl/resultset.js +5 -4
  21. package/lib/lob.js +9 -1
  22. package/lib/oracledb.js +129 -16
  23. package/lib/pool.js +12 -1
  24. package/lib/poolStatistics.js +3 -1
  25. package/lib/thin/connection.js +117 -10
  26. package/lib/thin/dbObject.js +8 -6
  27. package/lib/thin/lob.js +2 -3
  28. package/lib/thin/pool.js +105 -28
  29. package/lib/thin/protocol/capabilities.js +7 -3
  30. package/lib/thin/protocol/constants.js +29 -1
  31. package/lib/thin/protocol/messages/auth.js +13 -0
  32. package/lib/thin/protocol/messages/base.js +98 -9
  33. package/lib/thin/protocol/messages/dataType.js +2 -1
  34. package/lib/thin/protocol/messages/execute.js +46 -4
  35. package/lib/thin/protocol/messages/lobOp.js +5 -22
  36. package/lib/thin/protocol/messages/logOff.js +0 -1
  37. package/lib/thin/protocol/messages/sessionRelease.js +0 -1
  38. package/lib/thin/protocol/messages/transactionSwitch.js +12 -4
  39. package/lib/thin/protocol/protocol.js +2 -1
  40. package/lib/thin/sqlnet/connStrategy.js +2 -1
  41. package/lib/thin/sqlnet/navNodes.js +1 -1
  42. package/lib/thin/sqlnet/networkSession.js +9 -3
  43. package/lib/thin/sqlnet/packet.js +2 -1
  44. package/lib/thin/sqlnet/sessionAtts.js +2 -3
  45. package/lib/types.js +0 -5
  46. package/lib/util.js +76 -2
  47. package/lib/version.js +1 -1
  48. package/package/install.js +3 -3
  49. package/package/prunebinaries.js +6 -12
  50. package/package.json +2 -2
  51. package/{lib/configProviders/azure.js → plugins/configProviders/azure/index.js} +70 -63
  52. package/plugins/configProviders/azurevault/index.js +84 -0
  53. package/{lib → plugins}/configProviders/base.js +13 -3
  54. package/{lib/configProviders/ociobject.js → plugins/configProviders/ociobject/index.js} +43 -78
  55. package/plugins/configProviders/ocivault/index.js +100 -0
  56. package/plugins/token/extensionOci/index.js +71 -35
  57. package/build/Release/oracledb-6.8.0-darwin-arm64.node +0 -0
  58. package/build/Release/oracledb-6.8.0-darwin-arm64.node-buildinfo.txt +0 -1
  59. package/build/Release/oracledb-6.8.0-darwin-x64.node +0 -0
  60. package/build/Release/oracledb-6.8.0-darwin-x64.node-buildinfo.txt +0 -1
  61. package/build/Release/oracledb-6.8.0-js-buildinfo.txt +0 -1
  62. package/build/Release/oracledb-6.8.0-linux-arm64.node +0 -0
  63. package/build/Release/oracledb-6.8.0-linux-arm64.node-buildinfo.txt +0 -1
  64. package/build/Release/oracledb-6.8.0-linux-x64.node +0 -0
  65. package/build/Release/oracledb-6.8.0-linux-x64.node-buildinfo.txt +0 -1
  66. package/build/Release/oracledb-6.8.0-win32-x64.node +0 -0
  67. 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 errors = require("../errors.js");
32
- const { base } = require("./base.js");
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
- // _returnCredential()
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
- _returnCredential() {
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
- errors.throwErr(errors.ERR_AZURE_SERVICE_PRINCIPAL_AUTH_FAILED);
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
- errors.throwErr(errors.ERR_AZURE_CONFIG_PROVIDER_AUTH_FAILED, auth);
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
- // _getConfigurationSetting()
80
+ // _withChainedTokenCredential()
103
81
  //
104
- // Get configuration setting from the config provider given a key
105
- //and an optional label
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
- async _getConfigurationSetting(client, key, label) {
108
- return await client.getConfigurationSetting({ key: key, label: label });
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
- this.credential = this._returnCredential();
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._getConfigurationSetting(client, this.paramMap.get("key") + 'connect_descriptor', label)).value;
123
-
113
+ configObject.connectString = (await this.retrieveParamValueFromAzureConfigurationProvider(client, label, 'connect_descriptor'));
124
114
  // retrieve node-oracledb parameters
125
- try {
126
- const params = (await this._getConfigurationSetting(client, this.paramMap.get("key") + 'node-oracledb', label)).value;
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
- } catch {
133
- configObject['node-oracledb'] = null;
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.retrieveParamValueFromVault(client, label, 'password');
129
+ configObject.password = await this.retrieveParamValueFromAzureConfigurationProvider(client, label, 'password');
130
+
143
131
  // retrieve wallet_location
144
- configObject.walletContent = await this.retrieveParamValueFromVault(client, label, 'wallet_location');
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
- errors.throwErr(errors.ERR_WALLET_TYPE_NOT_SUPPORTED);
137
+ throw new Error('Invalid wallet content format. Supported format is PEM');
149
138
  }
150
139
  return configObject;
151
140
  }
152
- async retrieveParamValueFromVault(client, label, param) {
141
+ async retrieveParamValueFromAzureConfigurationProvider(client, label, param) {
153
142
  let paramJson = null;
154
143
  try {
155
- paramJson = await this._getConfigurationSetting(client, this.paramMap.get("key") + param, label);
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.value);
156
+ obj = JSON.parse(paramJson);
163
157
  } catch {
164
- obj = paramJson.value;
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.value;
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
- module.exports = AzureProvider;
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-z][A-Za-z0-9-]*)$", 'g');
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
- const match = provider_arg.match(cloud_net_naming_pattern_oci);
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
- // _returnCredential()
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 _returnCredential() {
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 new oci.common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
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
- errors.throwErr(errors.ERR_OCIOBJECT_CONFIG_PROVIDER_AUTH_FAILED, auth);
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
- const region = this.retrieveRegion(this.paramMap.get('objservername'));
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
- oci.common.Region[region]
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
- const configObject = {};
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
- const pmSection = 'node-oracledb';
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
- // retrieveRegion(objservername)
168
- //
169
- // returns region from the given objservername.
170
- //---------------------------------------------------------------------------
171
- retrieveRegion(objservername) {
172
- const arr = objservername.split(".");
173
- return arr[1].toUpperCase().replaceAll('-', '_');
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
- async retrieveParamValueFromVault(param) {
177
- if (this.obj[param].type == "azurevault") {
178
- if (this.obj[param].authentication) {
179
- const { SecretClient } = require("@azure/keyvault-secrets");
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
- module.exports = OCIProvider;
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);