oracledb 6.5.1 → 6.7.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 +2 -2
- package/build/Release/oracledb-6.7.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.7.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.7.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.7.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.7.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.7.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/README.md +4 -0
- package/lib/configProviders/azure.js +178 -0
- package/lib/configProviders/base.js +85 -0
- package/lib/configProviders/ociobject.js +211 -0
- package/lib/connection.js +97 -14
- package/lib/constants.js +1 -0
- package/lib/errors.js +68 -6
- package/lib/impl/aqQueue.js +2 -1
- package/lib/impl/base.js +45 -0
- package/lib/impl/connection.js +53 -0
- package/lib/impl/datahandlers/constants.js +3 -1
- package/lib/impl/datahandlers/vector.js +24 -9
- package/lib/impl/lob.js +29 -1
- package/lib/impl/pool.js +15 -0
- package/lib/impl/resultset.js +28 -2
- package/lib/impl/sodaCollection.js +2 -1
- package/lib/impl/sodaDatabase.js +2 -1
- package/lib/impl/sodaDocCursor.js +2 -1
- package/lib/impl/sodaOperation.js +2 -1
- package/lib/lob.js +55 -3
- package/lib/oracledb.js +246 -7
- package/lib/pool.js +14 -5
- package/lib/settings.js +1 -0
- package/lib/thin/connection.js +304 -29
- package/lib/thin/dbObject.js +4 -0
- package/lib/thin/lob.js +193 -1
- package/lib/thin/pool.js +18 -0
- package/lib/thin/protocol/capabilities.js +2 -0
- package/lib/thin/protocol/constants.js +29 -1
- package/lib/thin/protocol/messages/auth.js +12 -6
- package/lib/thin/protocol/messages/base.js +3 -0
- package/lib/thin/protocol/messages/index.js +5 -1
- package/lib/thin/protocol/messages/lobOp.js +17 -5
- package/lib/thin/protocol/messages/sessionRelease.js +1 -0
- package/lib/thin/protocol/messages/transactionChangeState.js +99 -0
- package/lib/thin/protocol/messages/transactionSwitch.js +139 -0
- package/lib/thin/protocol/messages/withData.js +21 -6
- package/lib/thin/protocol/protocol.js +23 -0
- package/lib/thin/sqlnet/connStrategy.js +9 -1
- package/lib/thin/sqlnet/constants.js +2 -0
- package/lib/thin/sqlnet/navNodes.js +14 -2
- package/lib/thin/sqlnet/networkSession.js +11 -10
- package/lib/thin/sqlnet/ntTcp.js +1 -1
- package/lib/thin/sqlnet/paramParser.js +87 -50
- package/lib/thin/sqlnet/sessionAtts.js +14 -2
- package/lib/thin/util.js +4 -3
- package/lib/traceHandler.js +133 -0
- package/lib/transformer.js +1 -2
- package/lib/types.js +1 -1
- package/lib/util.js +213 -35
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.5.1-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-win32-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-win32-x64.node-buildinfo.txt +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# node-oracledb version 6.
|
|
1
|
+
# node-oracledb version 6.7.0
|
|
2
2
|
|
|
3
3
|
The node-oracledb add-on for Node.js powers high performance Oracle Database
|
|
4
4
|
applications. Applications can be written in TypeScript, or directly in
|
|
5
5
|
JavaScript.
|
|
6
6
|
|
|
7
|
-
Use node-oracledb 6.
|
|
7
|
+
Use node-oracledb 6.7.0 to connect Node.js 14.6, or later, to Oracle
|
|
8
8
|
Database. Older versions of node-oracledb may work with older versions of
|
|
9
9
|
Node.js.
|
|
10
10
|
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.7.0-darwin-arm64.node v22.2.0 29e0b9cfc2f22f3df1e6b746323fb5f1f95ba492 3f4e00888d20e313374cfe0fb148de2180eaf93f Thu, 07 Nov 2024 06:28:34 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.7.0-darwin-x64.node v20.11.1 29e0b9cfc2f22f3df1e6b746323fb5f1f95ba492 3f4e00888d20e313374cfe0fb148de2180eaf93f Thu, 07 Nov 2024 06:21:29 GMT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
29e0b9cfc2f22f3df1e6b746323fb5f1f95ba492
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.7.0-linux-arm64.node v18.20.4 29e0b9cfc2f22f3df1e6b746323fb5f1f95ba492 3f4e00888d20e313374cfe0fb148de2180eaf93f Thu, 07 Nov 2024 16:48:12 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.7.0-linux-x64.node v16.20.2 29e0b9cfc2f22f3df1e6b746323fb5f1f95ba492 3f4e00888d20e313374cfe0fb148de2180eaf93f Thu, 07 Nov 2024 16:47:47 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.7.0-win32-x64.node v18.16.0 29e0b9cfc2f22f3df1e6b746323fb5f1f95ba492 3f4e00888d20e313374cfe0fb148de2180eaf93f Thu, 07 Nov 2024 16:23:47 GMT
|
package/examples/README.md
CHANGED
|
@@ -65,6 +65,7 @@ File Name | Description
|
|
|
65
65
|
[`aqraw.js`](aqraw.js) | Basic Oracle Advanced Queuing (AQ) example passing text messages
|
|
66
66
|
[`aqutil.js`](aqutil.js) | Common file to setup the user credentials for all the Advanced Queuing (AQ) examples.
|
|
67
67
|
[`blobhttp.js`](blobhttp.js) | Simple web app that streams an image
|
|
68
|
+
[`azureConfigProvider.js`](azureConfigProvider.js) | Show how to connect to an Oracle Database using Azure Configuration Providers
|
|
68
69
|
[`calltimeout.js`](calltimeout.js) | Shows how to cancel a SQL statement if it doesn't complete in a specified time
|
|
69
70
|
[`connect.js`](connect.js) | Basic example for creating a standalone (non-pooled) connection
|
|
70
71
|
[`connectionpool.js`](connectionpool.js) | Basic example creating a pool of connections
|
|
@@ -101,11 +102,13 @@ File Name | Description
|
|
|
101
102
|
[`lobstream2.js`](lobstream2.js) | Shows using Stream data events to fetch a CLOB
|
|
102
103
|
[`lowercasecolumns.js`](lowercasecolumns.js) | Shows how a type handler can convert column names to lower case
|
|
103
104
|
[`metadata.js`](metadata.js) | Shows the metadata available after executing SELECT statements
|
|
105
|
+
[`ociConfigProvider.js`](ociConfigProvider.js) | Show how to connect to an Oracle Database using OCI Configuration Providers
|
|
104
106
|
[`plsqlarray.js`](plsqlarray.js) | Examples of binding PL/SQL "INDEX BY" tables
|
|
105
107
|
[`plsqlfunc.js`](plsqlfunc.js) | How to call a PL/SQL function
|
|
106
108
|
[`plsqlproc.js`](plsqlproc.js) | How to call a PL/SQL procedure
|
|
107
109
|
[`plsqlrecord.js`](plsqlrecord.js) | Shows binding of PL/SQL RECORDS
|
|
108
110
|
[`plsqlvarrayrecord.js`](plsqlvarrayrecord.js) | Shows binding a VARRAY of RECORD in PL/SQL
|
|
111
|
+
[`plsqlrowtype.js`](plsqlrowtype.js) | Shows binding of PL/SQL %ROWTYPE object
|
|
109
112
|
[`raw.js`](raw.js) | Shows using a Buffer to insert and select a RAW
|
|
110
113
|
[`refcursor.js`](refcursor.js) | Shows using a ResultSet to fetch rows from a REF CURSOR
|
|
111
114
|
[`refcursortoquerystream.js`](refcursortoquerystream.js) | Converts a REF CURSOR returned from `execute()` to a query stream.
|
|
@@ -134,3 +137,4 @@ File Name | Description
|
|
|
134
137
|
[`vectortype2.js`](vectortype2.js) | Insert data into VECTOR columns and verify vector operations.
|
|
135
138
|
[`version.js`](version.js) | Shows the node-oracledb version attributes
|
|
136
139
|
[`webapp.js`](webapp.js) | A simple web application using a connection pool
|
|
140
|
+
[`xmltypeInDbObject.js`](xmltypeInDbObject.js) | Work with XMLType data in DbObject (Thin mode only)
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// Copyright (c) 2024, 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
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
let AppConfigurationClient;
|
|
30
|
+
let ClientSecretCredential, ClientCertificateCredential, ChainedTokenCredential, ManagedIdentityCredential, EnvironmentCredential;
|
|
31
|
+
const errors = require("../errors.js");
|
|
32
|
+
const { base } = require("./base.js");
|
|
33
|
+
|
|
34
|
+
class AzureProvider extends base {
|
|
35
|
+
constructor(provider_arg, urlExtendedPart) {
|
|
36
|
+
super(urlExtendedPart);
|
|
37
|
+
this._addParam("appconfigname", provider_arg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//---------------------------------------------------------------------------
|
|
41
|
+
// init()
|
|
42
|
+
//
|
|
43
|
+
// Require/import modules from Azure SDK
|
|
44
|
+
//---------------------------------------------------------------------------
|
|
45
|
+
init() {
|
|
46
|
+
({ 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
|
+
}
|
|
69
|
+
|
|
70
|
+
//---------------------------------------------------------------------------
|
|
71
|
+
// _returnCredential()
|
|
72
|
+
//
|
|
73
|
+
// Returns credential to access Azure Config Store on the basis of
|
|
74
|
+
// authentication parameters given by the user.
|
|
75
|
+
//---------------------------------------------------------------------------
|
|
76
|
+
_returnCredential() {
|
|
77
|
+
let auth = null;
|
|
78
|
+
if (this.paramMap.get('authentication')) {
|
|
79
|
+
auth = this.paramMap.get('authentication').toUpperCase();
|
|
80
|
+
}
|
|
81
|
+
if (auth && !(auth == 'AZURE_DEFAULT')) {
|
|
82
|
+
// do the given authentication
|
|
83
|
+
if (auth == 'AZURE_SERVICE_PRINCIPAL') {
|
|
84
|
+
if (this.paramMap.get("azure_client_certificate_path"))
|
|
85
|
+
return new ClientCertificateCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_certificate_path"));
|
|
86
|
+
else if (this.paramMap.get("azure_client_secret"))
|
|
87
|
+
return new ClientSecretCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_secret"));
|
|
88
|
+
else
|
|
89
|
+
errors.throwErr(errors.ERR_AZURE_SERVICE_PRINCIPAL_AUTH_FAILED);
|
|
90
|
+
} else if (auth == 'AZURE_MANAGED_IDENTITY') {
|
|
91
|
+
return new ManagedIdentityCredential(this.paramMap.get('azure_managed_identity_client_id'));
|
|
92
|
+
} else {
|
|
93
|
+
errors.throwErr(errors.ERR_AZURE_CONFIG_PROVIDER_AUTH_FAILED, auth);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
//return default token credential
|
|
97
|
+
return this._withChainedTokenCredential();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//---------------------------------------------------------------------------
|
|
102
|
+
// _getConfigurationSetting()
|
|
103
|
+
//
|
|
104
|
+
// Get configuration setting from the config provider given a key
|
|
105
|
+
//and an optional label
|
|
106
|
+
//---------------------------------------------------------------------------
|
|
107
|
+
async _getConfigurationSetting(client, key, label) {
|
|
108
|
+
return await client.getConfigurationSetting({ key: key, label: label });
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async returnConfig() {
|
|
113
|
+
const configObject = {};
|
|
114
|
+
const label = this.paramMap.get("label");
|
|
115
|
+
this.credential = this._returnCredential();
|
|
116
|
+
// azure config store
|
|
117
|
+
const client = new AppConfigurationClient(
|
|
118
|
+
"https://" + this.paramMap.get("appconfigname"), // ex: <https://<your appconfig resource>.azconfig.io>
|
|
119
|
+
this.credential
|
|
120
|
+
);
|
|
121
|
+
// retrieve connect_description
|
|
122
|
+
configObject.connectString = (await this._getConfigurationSetting(client, this.paramMap.get("key") + 'connect_descriptor', label)).value;
|
|
123
|
+
|
|
124
|
+
// retrieve node-oracledb parameters
|
|
125
|
+
try {
|
|
126
|
+
const params = (await this._getConfigurationSetting(client, this.paramMap.get("key") + 'node-oracledb', label)).value;
|
|
127
|
+
const obj = JSON.parse(params);
|
|
128
|
+
for (const key in obj) {
|
|
129
|
+
var val = obj[key];
|
|
130
|
+
configObject[key] = val;
|
|
131
|
+
}
|
|
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;
|
|
140
|
+
}
|
|
141
|
+
//retrieve password
|
|
142
|
+
configObject.password = await this.retrieveParamValueFromVault(client, label, 'password');
|
|
143
|
+
// retrieve wallet_location
|
|
144
|
+
configObject.walletContent = await this.retrieveParamValueFromVault(client, label, 'wallet_location');
|
|
145
|
+
if (configObject.walletContent) {
|
|
146
|
+
//only Pem file supported
|
|
147
|
+
if (!this.isPemFile(configObject.walletContent))
|
|
148
|
+
errors.throwErr(errors.ERR_WALLET_TYPE_NOT_SUPPORTED);
|
|
149
|
+
}
|
|
150
|
+
return configObject;
|
|
151
|
+
}
|
|
152
|
+
async retrieveParamValueFromVault(client, label, param) {
|
|
153
|
+
let paramJson = null;
|
|
154
|
+
try {
|
|
155
|
+
paramJson = await this._getConfigurationSetting(client, this.paramMap.get("key") + param, label);
|
|
156
|
+
} catch {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (paramJson) {
|
|
160
|
+
let obj;
|
|
161
|
+
try {
|
|
162
|
+
obj = JSON.parse(paramJson.value);
|
|
163
|
+
} catch {
|
|
164
|
+
obj = paramJson.value;
|
|
165
|
+
}
|
|
166
|
+
if (obj.uri) {
|
|
167
|
+
const { SecretClient } = require("@azure/keyvault-secrets");
|
|
168
|
+
const vault_detail = await this._parsePwd(obj.uri);
|
|
169
|
+
const client1 = new SecretClient(vault_detail[0], this.credential);
|
|
170
|
+
return (await client1.getSecret(vault_detail[1])).value;
|
|
171
|
+
} else {
|
|
172
|
+
return paramJson.value;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
module.exports = AzureProvider;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Copyright (c) 2024, 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
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const pemHeaders = [
|
|
30
|
+
'-----BEGIN CERTIFICATE-----',
|
|
31
|
+
'-----BEGIN PUBLIC KEY-----',
|
|
32
|
+
'-----BEGIN PRIVATE KEY-----',
|
|
33
|
+
'-----BEGIN RSA PRIVATE KEY-----',
|
|
34
|
+
'-----BEGIN DSA PRIVATE KEY-----',
|
|
35
|
+
'-----BEGIN EC PRIVATE KEY-----',
|
|
36
|
+
'-----BEGIN ENCRYPTED PRIVATE KEY-----'
|
|
37
|
+
];
|
|
38
|
+
const pemFooters = [
|
|
39
|
+
'-----END CERTIFICATE-----',
|
|
40
|
+
'-----END PUBLIC KEY-----',
|
|
41
|
+
'-----END PRIVATE KEY-----',
|
|
42
|
+
'-----END RSA PRIVATE KEY-----',
|
|
43
|
+
'-----END DSA PRIVATE KEY-----',
|
|
44
|
+
'-----END EC PRIVATE KEY-----',
|
|
45
|
+
'-----END ENCRYPTED PRIVATE KEY-----'
|
|
46
|
+
];
|
|
47
|
+
class base {
|
|
48
|
+
constructor(url) {
|
|
49
|
+
const params = new URLSearchParams(url);
|
|
50
|
+
this.paramMap = new URLSearchParams([...params].map(([key, value]) => [key.toLowerCase(), value])); //parse the extended part and store parameters in Map
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
isPemFile(content) {
|
|
54
|
+
//remove any line breaks at the end of the content
|
|
55
|
+
content = content.trim();
|
|
56
|
+
return pemHeaders.some(header => content.includes(header)) &&
|
|
57
|
+
pemFooters.some(footer => content.endsWith(footer));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//---------------------------------------------------------------------------
|
|
61
|
+
// _addParam()
|
|
62
|
+
// Adds key,value pairs to the Map
|
|
63
|
+
//---------------------------------------------------------------------------
|
|
64
|
+
_addParam(key, value) {
|
|
65
|
+
const aliasKeyName = key.toLowerCase();
|
|
66
|
+
this.paramMap.set(aliasKeyName, value);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//---------------------------------------------------------------------------
|
|
70
|
+
// _parsePwd()
|
|
71
|
+
// Parse password which is in url format
|
|
72
|
+
// “uri”:“https://mykeyvault.vault.azure.net/secrets/secretkey”}
|
|
73
|
+
//---------------------------------------------------------------------------
|
|
74
|
+
_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');
|
|
76
|
+
const vault_detail = [];
|
|
77
|
+
for (const match of str.matchAll(vault_uri)) {
|
|
78
|
+
vault_detail[0] = match.groups.vault_url;
|
|
79
|
+
vault_detail[1] = match.groups.secretKey;
|
|
80
|
+
}
|
|
81
|
+
return vault_detail;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
module.exports = {base};
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// Copyright (c) 2024, 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
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
const errors = require("../errors.js");
|
|
29
|
+
const { base } = require("./base.js");
|
|
30
|
+
const fs = require('fs');
|
|
31
|
+
|
|
32
|
+
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
|
+
// object to store module references that will be populated by init()
|
|
34
|
+
const oci = {};
|
|
35
|
+
class OCIProvider extends base {
|
|
36
|
+
constructor(provider_arg, urlExtendedPart) {
|
|
37
|
+
super(urlExtendedPart);
|
|
38
|
+
const match = provider_arg.match(cloud_net_naming_pattern_oci);
|
|
39
|
+
if (match) {
|
|
40
|
+
this._addParam("objservername", match.groups.objservername);
|
|
41
|
+
this._addParam("namespace", match.groups.namespace);
|
|
42
|
+
this._addParam("bucketname", match.groups.bucketname);
|
|
43
|
+
this._addParam("filename", match.groups.filename);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//---------------------------------------------------------------------------
|
|
48
|
+
// init()
|
|
49
|
+
//
|
|
50
|
+
// Require/import modules from ociobject
|
|
51
|
+
//---------------------------------------------------------------------------
|
|
52
|
+
init() {
|
|
53
|
+
oci.common = require('oci-common');
|
|
54
|
+
oci.objectstorage = require('oci-objectstorage');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//---------------------------------------------------------------------------
|
|
58
|
+
// _streamToString()
|
|
59
|
+
//
|
|
60
|
+
// Converts data stored in a Readable stream to string
|
|
61
|
+
//---------------------------------------------------------------------------
|
|
62
|
+
async _streamToString(stream) {
|
|
63
|
+
const chunks = [];
|
|
64
|
+
for await (const chunk of stream) {
|
|
65
|
+
chunks.push(Buffer.from(chunk));
|
|
66
|
+
}
|
|
67
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//---------------------------------------------------------------------------
|
|
71
|
+
// _returnCredential()
|
|
72
|
+
//
|
|
73
|
+
// Returns credential to access OCI Object Store on the basis of
|
|
74
|
+
// authentication parameters given by the user.
|
|
75
|
+
//---------------------------------------------------------------------------
|
|
76
|
+
async _returnCredential() {
|
|
77
|
+
let provider = null;
|
|
78
|
+
let auth = null;
|
|
79
|
+
if (this.paramMap.get('authentication')) {
|
|
80
|
+
auth = this.paramMap.get('authentication').toUpperCase();
|
|
81
|
+
}
|
|
82
|
+
// authentication parameter given and its not OCI_DEFAULT
|
|
83
|
+
if (auth && !(auth == 'OCI_DEFAULT')) {
|
|
84
|
+
if (auth == 'OCI_INSTANCE_PRINCIPAL') {
|
|
85
|
+
provider = await new oci.common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
|
|
86
|
+
} else if (auth == 'OCI_RESOURCE_PRINCIPAL') {
|
|
87
|
+
provider = await new oci.common.ResourcePrincipalAuthenticationDetailsProvider.builder();
|
|
88
|
+
} else
|
|
89
|
+
errors.throwErr(errors.ERR_OCIOBJECT_CONFIG_PROVIDER_AUTH_FAILED, auth);
|
|
90
|
+
} else {
|
|
91
|
+
// default authentication
|
|
92
|
+
try {
|
|
93
|
+
//authentication parameters exist in the configurationFile
|
|
94
|
+
provider = new oci.common.ConfigFileAuthenticationDetailsProvider(
|
|
95
|
+
this.paramMap.get("oci_profile_path"), //default path ~/.oci/config
|
|
96
|
+
this.paramMap.get("oci_profile")
|
|
97
|
+
);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
//throw error for wrong profile or wrong path
|
|
100
|
+
if (!this.paramMap.get("oci_tenancy") || !this.paramMap.get("oci_user")) {
|
|
101
|
+
throw (err);
|
|
102
|
+
}
|
|
103
|
+
// authentication parameters are directly given in the connectString
|
|
104
|
+
const publicKey = fs.readFileSync(this.paramMap.get('oci_key_file'), { encoding: "utf8" });
|
|
105
|
+
const region = this.retrieveRegion(this.paramMap.get('objservername'));
|
|
106
|
+
provider = new oci.common.SimpleAuthenticationDetailsProvider(
|
|
107
|
+
this.paramMap.get("oci_tenancy"),
|
|
108
|
+
this.paramMap.get("oci_user"),
|
|
109
|
+
this.paramMap.get("oci_fingerprint"),
|
|
110
|
+
publicKey,
|
|
111
|
+
undefined,
|
|
112
|
+
oci.common.Region[region]
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return provider;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//---------------------------------------------------------------------------
|
|
120
|
+
// returnConfig()
|
|
121
|
+
//
|
|
122
|
+
// Returns config stored in the OCI Object Store and
|
|
123
|
+
// parses and gets password field stored in OCI/Azure Vault
|
|
124
|
+
//---------------------------------------------------------------------------
|
|
125
|
+
async returnConfig() {
|
|
126
|
+
const configObject = {};
|
|
127
|
+
this.credential = await this._returnCredential();
|
|
128
|
+
// oci object store
|
|
129
|
+
const client_oci = new (oci.objectstorage).ObjectStorageClient({
|
|
130
|
+
authenticationDetailsProvider: this.credential
|
|
131
|
+
});
|
|
132
|
+
const getObjectRequest = {
|
|
133
|
+
objectName: this.paramMap.get('filename'),
|
|
134
|
+
bucketName: this.paramMap.get('bucketname'),
|
|
135
|
+
namespaceName: this.paramMap.get('namespace')
|
|
136
|
+
};
|
|
137
|
+
const getObjectResponse = await client_oci.getObject(getObjectRequest);
|
|
138
|
+
const resp = await this._streamToString(getObjectResponse.value);
|
|
139
|
+
// Entire object we get from OCI Object Storage
|
|
140
|
+
this.obj = JSON.parse(resp);
|
|
141
|
+
const userAlias = this.paramMap.get('key'); // alias
|
|
142
|
+
if (userAlias) {
|
|
143
|
+
this.obj = this.obj[userAlias];
|
|
144
|
+
}
|
|
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;
|
|
164
|
+
}
|
|
165
|
+
|
|
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('-', '_');
|
|
174
|
+
}
|
|
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
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
module.exports = OCIProvider;
|