@rockcarver/frodo-lib 0.11.0 → 0.11.1-2

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.
@@ -47,11 +47,20 @@ jobs:
47
47
  #
48
48
  # Run tests.
49
49
  #
50
- - name: Test Suites
50
+ - name: Direct Tests
51
51
  env:
52
- FIDC_TENANT_URL: ${{ secrets.FIDC_TENANT_URL }}
53
- FIDC_TENANT_ADMIN_USERNAME: ${{ secrets.FIDC_TENANT_ADMIN_USERNAME }}
54
- FIDC_TENANT_ADMIN_PASSWORD: ${{ secrets.FIDC_TENANT_ADMIN_PASSWORD }}
52
+ FRODO_HOST: ${{ secrets.FIDC_TENANT_URL }}
53
+ FRODO_USER: ${{ secrets.FIDC_TENANT_ADMIN_USERNAME }}
54
+ FRODO_PASSWORD: ${{ secrets.FIDC_TENANT_ADMIN_PASSWORD }}
55
+ run: |
56
+ npm test
57
+
58
+ - name: Proxy Tests
59
+ env:
60
+ HTTPS_PROXY: 'http://127.0.0.1:3128'
61
+ FRODO_HOST: ${{ secrets.FIDC_TENANT_URL }}
62
+ FRODO_USER: ${{ secrets.FIDC_TENANT_ADMIN_USERNAME }}
63
+ FRODO_PASSWORD: ${{ secrets.FIDC_TENANT_ADMIN_PASSWORD }}
55
64
  run: |
56
65
  npm test
57
66
 
@@ -59,25 +68,6 @@ jobs:
59
68
  run: |
60
69
  npm audit
61
70
 
62
- # - name: Direct Tests
63
- # env:
64
- # FIDC_TENANT_URL: ${{ secrets.FIDC_TENANT_URL }}
65
- # FIDC_TENANT_ADMIN_USERNAME: ${{ secrets.FIDC_TENANT_ADMIN_USERNAME }}
66
- # FIDC_TENANT_ADMIN_PASSWORD: ${{ secrets.FIDC_TENANT_ADMIN_PASSWORD }}
67
- # run: |
68
- # frodo conn add "$FIDC_TENANT_URL" "$FIDC_TENANT_ADMIN_USERNAME" "$FIDC_TENANT_ADMIN_PASSWORD"
69
- # frodo info "$FIDC_TENANT_URL"
70
-
71
- # - name: Proxy Tests
72
- # env:
73
- # HTTPS_PROXY: "http://127.0.0.1:3128"
74
- # FIDC_TENANT_URL: ${{ secrets.FIDC_TENANT_URL }}
75
- # FIDC_TENANT_ADMIN_USERNAME: ${{ secrets.FIDC_TENANT_ADMIN_USERNAME }}
76
- # FIDC_TENANT_ADMIN_PASSWORD: ${{ secrets.FIDC_TENANT_ADMIN_PASSWORD }}
77
- # run: |
78
- # frodo conn add "$FIDC_TENANT_URL" "$FIDC_TENANT_ADMIN_USERNAME" "$FIDC_TENANT_ADMIN_PASSWORD"
79
- # frodo info "$FIDC_TENANT_URL"
80
-
81
71
  update-changelog:
82
72
  needs: smoke-tests
83
73
  name: 'Update Changelog'
package/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.11.1-2] - 2022-08-18
11
+
12
+ ## [0.11.1-1] - 2022-08-18
13
+
14
+ ## [0.11.1-0] - 2022-08-17
15
+
10
16
  ## [0.11.0] - 2022-08-16
11
17
 
12
18
  ### Changed
@@ -411,7 +417,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
411
417
  - Fixed problem with adding connection profiles
412
418
  - Miscellaneous bug fixes
413
419
 
414
- [Unreleased]: https://github.com/rockcarver/frodo/compare/v0.10.4...HEAD
420
+ [Unreleased]: https://github.com/rockcarver/frodo-lib/compare/v0.11.1-2...HEAD
421
+
422
+ [0.11.1-2]: https://github.com/rockcarver/frodo-lib/compare/v0.11.1-1...v0.11.1-2
423
+
424
+ [0.11.1-1]: https://github.com/rockcarver/frodo-lib/compare/v0.11.1-0...v0.11.1-1
425
+
426
+ [0.11.1-0]: https://github.com/rockcarver/frodo-lib/compare/v0.10.4...v0.11.1-0
415
427
 
416
428
  [0.10.4]: https://github.com/rockcarver/frodo/compare/v0.10.3...v0.10.4
417
429
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rockcarver/frodo-lib",
3
- "version": "0.11.0",
3
+ "version": "0.11.1-2",
4
4
  "type": "module",
5
5
  "description": "ForgeROck DO Library, frodo-lib, a library to manage ForgeRock platform deployments supporting Identity Cloud tenants, ForgeOps deployments, and classic deployments.",
6
6
  "keywords": [
@@ -27,8 +27,8 @@
27
27
  },
28
28
  "main": "src/index.js",
29
29
  "scripts": {
30
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
31
- "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
30
+ "test": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js",
31
+ "test:watch": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
32
32
  "lint": "eslint --ext .js --ignore-path .gitignore ."
33
33
  },
34
34
  "jest": {
package/src/index.js CHANGED
@@ -30,3 +30,4 @@ export * as Variables from './ops/VariablesOps.js';
30
30
  // TODO: reconsider the aproach to pass in state from client
31
31
  // lib should be stateless, an aplication should own its state
32
32
  export * as state from './storage/SessionStorage.js';
33
+ export * as OAuth2OIDCApi from './api/OAuth2OIDCApi.js';
@@ -0,0 +1,14 @@
1
+ import { Authenticate, state } from '../index.js';
2
+
3
+ describe('AuthenticationOps.js', () => {
4
+ test('getTokens() 1: ', async () => {
5
+ state.default.session.setTenant(process.env.FRODO_HOST);
6
+ state.default.session.setRealm('alpha');
7
+ state.default.session.setUsername(process.env.FRODO_USER);
8
+ state.default.session.setPassword(process.env.FRODO_PASSWORD);
9
+ await Authenticate.getTokens();
10
+ expect(state.default.session.getCookieName()).toBeTruthy();
11
+ expect(state.default.session.getCookieValue()).toBeTruthy();
12
+ expect(state.default.session.getBearerToken()).toBeTruthy();
13
+ });
14
+ });
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import os from 'os';
3
+ import path from 'path';
3
4
  import storage from '../storage/SessionStorage.js';
4
5
  import DataProtection from './utils/DataProtection.js';
5
6
  import {
@@ -7,6 +8,7 @@ import {
7
8
  createTable,
8
9
  printMessage,
9
10
  } from './utils/Console.js';
11
+ import { FRODO_CONNECTION_PROFILES_PATH_KEY } from '../storage/StaticStorage.js';
10
12
 
11
13
  const dataProtection = new DataProtection();
12
14
 
@@ -15,14 +17,16 @@ const fileOptions = {
15
17
  indentation: 4,
16
18
  };
17
19
 
18
- const getConnectionProfilesFolder = () => `${os.homedir()}/.frodo`;
19
-
20
20
  /**
21
21
  * Get connection profiles file name
22
22
  * @returns {String} connection profiles file name
23
23
  */
24
- export function getConnectionProfilesFileName() {
25
- return `${os.homedir()}/.frodo/.frodorc`;
24
+ export function getConnectionProfilesPath() {
25
+ return (
26
+ storage.session.getConnectionProfilesPath() ||
27
+ process.env[FRODO_CONNECTION_PROFILES_PATH_KEY] ||
28
+ `${os.homedir()}/.frodo/.frodorc`
29
+ );
26
30
  }
27
31
 
28
32
  /**
@@ -47,7 +51,7 @@ function findConnectionProfile(connectionProfiles, host) {
47
51
  * @param {boolean} long Long list format with details
48
52
  */
49
53
  export function listConnectionProfiles(long = false) {
50
- const filename = getConnectionProfilesFileName();
54
+ const filename = getConnectionProfilesPath();
51
55
  try {
52
56
  const data = fs.readFileSync(filename, 'utf8');
53
57
  const connectionsData = JSON.parse(data);
@@ -80,8 +84,8 @@ export function listConnectionProfiles(long = false) {
80
84
  */
81
85
  export function initConnectionProfiles() {
82
86
  // create connections.json file if it doesn't exist
83
- const folderName = getConnectionProfilesFolder();
84
- const filename = getConnectionProfilesFileName();
87
+ const filename = getConnectionProfilesPath();
88
+ const folderName = path.dirname(filename);
85
89
  if (!fs.existsSync(folderName)) {
86
90
  fs.mkdirSync(folderName, { recursive: true });
87
91
  if (!fs.existsSync(filename)) {
@@ -121,7 +125,7 @@ export function initConnectionProfiles() {
121
125
  */
122
126
  export async function getConnectionProfileByHost(host) {
123
127
  try {
124
- const filename = getConnectionProfilesFileName();
128
+ const filename = getConnectionProfilesPath();
125
129
  const connectionsData = JSON.parse(
126
130
  fs.readFileSync(filename, fileOptions.options)
127
131
  );
@@ -163,7 +167,7 @@ export async function getConnectionProfile() {
163
167
  * Save connection profile
164
168
  */
165
169
  export async function saveConnectionProfile() {
166
- const filename = getConnectionProfilesFileName();
170
+ const filename = getConnectionProfilesPath();
167
171
  printMessage(`Saving creds in ${filename}...`);
168
172
  let connectionsData = {};
169
173
  let existingData = {};
@@ -174,13 +178,13 @@ export async function saveConnectionProfile() {
174
178
  if (connectionsData[storage.session.getTenant()]) {
175
179
  existingData = connectionsData[storage.session.getTenant()];
176
180
  printMessage(
177
- `Updating existing connection profile ${storage.session.getTenant()}`
181
+ `Updating connection profile ${storage.session.getTenant()}`
178
182
  );
179
183
  } else
180
184
  printMessage(`Adding connection profile ${storage.session.getTenant()}`);
181
185
  } catch (e) {
182
186
  printMessage(
183
- `Creating connection profile file ${filename} with ${storage.session.getTenant()}`
187
+ `Creating connection profiles file ${filename} with ${storage.session.getTenant()}`
184
188
  );
185
189
  }
186
190
  if (storage.session.getUsername())
@@ -203,7 +207,7 @@ export async function saveConnectionProfile() {
203
207
  * @param {String} host host tenant host url or unique substring
204
208
  */
205
209
  export function deleteConnectionProfile(host) {
206
- const filename = getConnectionProfilesFileName();
210
+ const filename = getConnectionProfilesPath();
207
211
  let connectionsData = {};
208
212
  fs.stat(filename, (err) => {
209
213
  if (err == null) {
@@ -0,0 +1,90 @@
1
+ import fs from 'fs';
2
+ import { homedir } from 'os';
3
+ import { ConnectionProfile, state } from '../index.js';
4
+ import {
5
+ FRODO_CONNECTION_PROFILES_PATH_KEY,
6
+ FRODO_MASTER_KEY_PATH_KEY,
7
+ FRODO_MASTER_KEY_KEY,
8
+ } from '../storage/StaticStorage.js';
9
+
10
+ describe('ConnectionProfileOps.js', () => {
11
+ test('saveConnectionProfile() 1: Create connection profiles in location from state field', async () => {
12
+ const host = 'https://openam-tenant-name.forgeblocks.com/am';
13
+ const user = 'frodo.baggins@shire.me';
14
+ const password = 'G@nd@lfTheW153';
15
+ const connectionProfilePath = `${homedir()}/connections1.json`;
16
+
17
+ state.default.session.setTenant(host);
18
+ state.default.session.setUsername(user);
19
+ state.default.session.setPassword(password);
20
+ state.default.session.setConnectionProfilesPath(connectionProfilePath);
21
+ await ConnectionProfile.saveConnectionProfile();
22
+ expect(fs.existsSync(connectionProfilePath)).toBeTruthy();
23
+ const connections = JSON.parse(
24
+ fs.readFileSync(connectionProfilePath, {
25
+ options: 'utf8',
26
+ indentation: 4,
27
+ })
28
+ );
29
+ expect(connections).toBeTruthy();
30
+ expect(connections[host]).toBeTruthy();
31
+ expect(connections[host].username).toEqual(user);
32
+ expect(connections[host].encodedPassword).toBeTruthy();
33
+ });
34
+
35
+ test(`saveConnectionProfile() 2: Create connection profiles in location from env ${FRODO_MASTER_KEY_PATH_KEY}`, async () => {
36
+ const host = 'https://openam-tenant-name.forgeblocks.com/am';
37
+ const user = 'frodo.baggins@shire.me';
38
+ const password = 'G@nd@lfTheW153';
39
+ const connectionProfilePath = `${homedir()}/connections2.json`;
40
+ // set the hard-coded master key
41
+ process.env[FRODO_CONNECTION_PROFILES_PATH_KEY] = connectionProfilePath;
42
+
43
+ state.default.session.setTenant(host);
44
+ state.default.session.setUsername(user);
45
+ state.default.session.setPassword(password);
46
+ state.default.session.setConnectionProfilesPath(null);
47
+ await ConnectionProfile.saveConnectionProfile();
48
+ expect(ConnectionProfile.getConnectionProfilesPath()).toEqual(
49
+ connectionProfilePath
50
+ );
51
+ expect(fs.existsSync(connectionProfilePath)).toBeTruthy();
52
+ const connections = JSON.parse(
53
+ fs.readFileSync(connectionProfilePath, {
54
+ options: 'utf8',
55
+ indentation: 4,
56
+ })
57
+ );
58
+ expect(connections).toBeTruthy();
59
+ expect(connections[host]).toBeTruthy();
60
+ expect(connections[host].username).toEqual(user);
61
+ expect(connections[host].encodedPassword).toBeTruthy();
62
+ });
63
+
64
+ test(`saveConnectionProfile() 3: Use Master Key from env ${FRODO_MASTER_KEY_KEY}`, async () => {
65
+ const host = 'https://openam-tenant-name.forgeblocks.com/am';
66
+ const user = 'frodo.baggins@shire.me';
67
+ const password = 'G@nd@lfTheW153';
68
+ const connectionProfilePath = `${homedir()}/connections3.json`;
69
+ const masterKey = 'bxnQlhcU5VfyDs+BBPhRhK09yHaNtdIIk85HUMKBnqg=';
70
+ // set the hard-coded master key
71
+ process.env[FRODO_MASTER_KEY_KEY] = masterKey;
72
+
73
+ state.default.session.setTenant(host);
74
+ state.default.session.setUsername(user);
75
+ state.default.session.setPassword(password);
76
+ state.default.session.setConnectionProfilesPath(connectionProfilePath);
77
+ await ConnectionProfile.saveConnectionProfile();
78
+ expect(fs.existsSync(connectionProfilePath)).toBeTruthy();
79
+ const connections = JSON.parse(
80
+ fs.readFileSync(connectionProfilePath, {
81
+ options: 'utf8',
82
+ indentation: 4,
83
+ })
84
+ );
85
+ expect(connections).toBeTruthy();
86
+ expect(connections[host]).toBeTruthy();
87
+ expect(connections[host].username).toEqual(user);
88
+ expect(connections[host].encodedPassword).toBeTruthy();
89
+ });
90
+ });
@@ -14,6 +14,11 @@ import crypto from 'crypto';
14
14
  import { homedir } from 'os';
15
15
  import { promisify } from 'util';
16
16
  import { printMessage } from './Console.js';
17
+ import storage from '../../storage/SessionStorage.js';
18
+ import {
19
+ FRODO_MASTER_KEY_PATH_KEY,
20
+ FRODO_MASTER_KEY_KEY,
21
+ } from '../../storage/StaticStorage.js';
17
22
 
18
23
  const scrypt = promisify(crypto.scrypt);
19
24
  // using WeakMaps for added security since it gets garbage collected
@@ -25,10 +30,15 @@ const _encrypt = new WeakMap();
25
30
 
26
31
  class DataProtection {
27
32
  constructor() {
28
- const masterKeyPath = () => `${homedir()}/.frodo/masterkey.key`;
33
+ const masterKeyPath = () =>
34
+ storage.session.getMasterKeyPath() ||
35
+ process.env[FRODO_MASTER_KEY_PATH_KEY] ||
36
+ `${homedir()}/.frodo/masterkey.key`;
29
37
  // Generates a master key in base64 format. This master key will be used to derive the key for encryption. this key should be protected by an HSM or KMS
30
38
  _masterKey.set(this, async () => {
31
39
  try {
40
+ if (process.env[FRODO_MASTER_KEY_KEY])
41
+ return process.env[FRODO_MASTER_KEY_KEY];
32
42
  if (!fs.existsSync(masterKeyPath())) {
33
43
  const masterKey = crypto.randomBytes(32).toString('base64');
34
44
  await fsp.writeFile(masterKeyPath(), masterKey);
@@ -41,5 +41,10 @@ export default {
41
41
  _sessionStorage.frodoVersion || `v${pkg.version} [${process.version}]`,
42
42
  setAllowInsecureConnection: (value) => (_sessionStorage.insecure = value),
43
43
  getAllowInsecureConnection: () => _sessionStorage.insecure,
44
+ setConnectionProfilesPath: (value) =>
45
+ (_sessionStorage.connectionProfilesPath = value),
46
+ getConnectionProfilesPath: () => _sessionStorage.connectionProfilesPath,
47
+ setMasterKeyPath: (value) => (_sessionStorage.masterKeyPath = value),
48
+ getMasterKeyPath: () => _sessionStorage.masterKeyPath,
44
49
  },
45
50
  };
@@ -13,3 +13,7 @@ export const DEPLOYMENT_TYPE_REALM_MAP = {
13
13
  [FORGEOPS_DEPLOYMENT_TYPE_KEY]: '/',
14
14
  };
15
15
  export const FRODO_METADATA_ID = 'frodo';
16
+ export const FRODO_CONNECTION_PROFILES_PATH_KEY =
17
+ 'FRODO_CONNECTION_PROFILES_PATH';
18
+ export const FRODO_MASTER_KEY_PATH_KEY = 'FRODO_MASTER_KEY_PATH';
19
+ export const FRODO_MASTER_KEY_KEY = 'FRODO_MASTER_KEY';
package/test/e2e/setup.js CHANGED
@@ -1,5 +1,4 @@
1
- import fs from 'fs';
2
- import { Authenticate, state } from '../../src/index.js';
1
+ import { ConnectionProfile, Authenticate, state } from '../../src/index.js';
3
2
 
4
3
  export default async function setup(globalConfig) {
5
4
  let run = globalConfig.nonFlagArgs.length === 0;
@@ -12,19 +11,17 @@ export default async function setup(globalConfig) {
12
11
  // make sure we have connectivity
13
12
  try {
14
13
  state.default.session.setTenant(
15
- process.env.FIDC_TENANT_URL ||
16
- 'https://openam-frodo-dev.forgeblocks.com/am'
14
+ process.env.FRODO_HOST || 'https://openam-frodo-dev.forgeblocks.com/am'
17
15
  );
18
- state.default.session.setRealm('alpha');
16
+ state.default.session.setRealm(process.env.FRODO_REALM || 'alpha');
19
17
  state.default.session.setUsername(
20
- process.env.FIDC_TENANT_ADMIN_USERNAME ||
21
- 'volker.scheuber@forgerock.com'
18
+ process.env.FRODO_USER || 'volker.scheuber@forgerock.com'
22
19
  );
23
20
  state.default.session.setPassword(
24
- process.env.FIDC_TENANT_ADMIN_PASSWORD ||
25
- fs.readFileSync(new URL('./FIDC_TENANT_PWD', import.meta.url))
21
+ process.env.FRODO_PASSWORD || '99Luftballons!'
26
22
  );
27
23
 
24
+ await ConnectionProfile.saveConnectionProfile();
28
25
  await Authenticate.getTokens();
29
26
  if (
30
27
  state.default.session.getCookieName() &&
@@ -1,7 +1,7 @@
1
- import e2e from '../e2e/setup.js';
1
+ // import e2e from '../e2e/setup.js';
2
2
 
3
3
  export default async function setup(globalConfig) {
4
- e2e(globalConfig);
4
+ // e2e(globalConfig);
5
5
  }
6
6
 
7
7
  /*