Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/aio-cli-plugin-api-mesh",
"version": "5.3.2-beta.1",
"version": "5.3.2-beta.2",
"description": "Adobe I/O CLI plugin to develop and manage API mesh sources",
"keywords": [
"oclif-plugin"
Expand Down
47 changes: 44 additions & 3 deletions src/commands/api-mesh/__tests__/set-log-forwarding.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ governing permissions and limitations under the License.
*/

const SetLogForwardingCommand = require('../config/set/log-forwarding');
const crypto = require('crypto');
const {
initSdk,
promptConfirm,
promptSelect,
promptInput,
promptInputSecret,
} = require('../../../helpers');
const { getMeshId, setLogForwarding } = require('../../../lib/smsClient');
const { getMeshId, setLogForwarding, getPublicEncryptionKey } = require('../../../lib/smsClient');

jest.mock('../../../helpers', () => ({
initSdk: jest.fn().mockResolvedValue({}),
Expand All @@ -31,6 +32,21 @@ jest.mock('../../../helpers', () => ({
jest.mock('../../../lib/smsClient');
jest.mock('../../../classes/logger');

jest.mock('crypto');
// Mock randomBytes for aesKey and iv
const mockAesKey = Buffer.from('mockAesKey');
const mockIv = Buffer.from('mockIv');
const mockEncryptedAesKey = Buffer.from('mockEncryptedAesKey');
const mockCipher = {
update: jest.fn().mockReturnValueOnce('mockEncryptedData'),
final: jest.fn().mockReturnValueOnce(''),
};
const mockEncryptedLicenseKey = {
iv: 'bW9ja0l2',
key: 'bW9ja0VuY3J5cHRlZEFlc0tleQ==',
data: 'mockEncryptedData',
};

describe('SetLogForwardingCommand', () => {
let parseSpy;
let logSpy;
Expand Down Expand Up @@ -60,8 +76,13 @@ describe('SetLogForwardingCommand', () => {
workspaceName: 'workspaceName',
});
getMeshId.mockResolvedValue('meshId');
getPublicEncryptionKey.mockResolvedValue('dummy_public_key');
setLogForwarding.mockResolvedValue({ success: true, result: true });
global.requestId = 'dummy_request_id';

// Reset mockCipher methods
mockCipher.update.mockReset().mockReturnValueOnce('mockEncryptedData');
mockCipher.final.mockReset().mockReturnValueOnce('');
});

afterEach(() => {
Expand All @@ -71,6 +92,10 @@ describe('SetLogForwardingCommand', () => {
describe('Test New Relic destination', () => {
/** Success Scenario */
test('sets log forwarding with valid parameters', async () => {
crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);

const command = new SetLogForwardingCommand([], {});
await command.run();

Expand All @@ -88,7 +113,7 @@ describe('SetLogForwardingCommand', () => {
destination: 'newrelic',
config: {
baseUri: 'https://log-api.newrelic.com/log/v1',
licenseKey: 'abcdef0123456789abcdef0123456789abcdef01',
licenseKey: JSON.stringify(mockEncryptedLicenseKey), // Expect the encrypted value
},
},
);
Expand Down Expand Up @@ -126,6 +151,10 @@ describe('SetLogForwardingCommand', () => {
args: [],
});

crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);

const command = new SetLogForwardingCommand([], {});
await command.run();

Expand Down Expand Up @@ -186,6 +215,10 @@ describe('SetLogForwardingCommand', () => {
args: [],
});

crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);

const command = new SetLogForwardingCommand([], {});
await command.run();

Expand All @@ -194,6 +227,10 @@ describe('SetLogForwardingCommand', () => {
});

test('sets log forwarding with auto-confirmation', async () => {
crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);

parseSpy.mockResolvedValueOnce({
flags: {
ignoreCache: false,
Expand All @@ -216,7 +253,7 @@ describe('SetLogForwardingCommand', () => {
destination: 'newrelic',
config: {
baseUri: 'https://log-api.newrelic.com/log/v1',
licenseKey: 'abcdef0123456789abcdef0123456789abcdef01',
licenseKey: JSON.stringify(mockEncryptedLicenseKey), // Expect the encrypted value
},
},
);
Expand All @@ -227,6 +264,10 @@ describe('SetLogForwardingCommand', () => {
const errorMessage = 'Unable to set log forwarding details';
setLogForwarding.mockRejectedValueOnce(new Error(errorMessage));

crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);

const command = new SetLogForwardingCommand([], {});
await expect(command.run()).rejects.toThrow(
'Failed to set log forwarding details. Try again. RequestId: dummy_request_id',
Expand Down
32 changes: 31 additions & 1 deletion src/commands/api-mesh/config/set/log-forwarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ const {
autoConfirmActionFlag,
jsonFlag,
destinations,
LogForwardingKeys,
encryptSecrets,
} = require('../../../../utils');
const { setLogForwarding, getMeshId } = require('../../../../lib/smsClient');
const {
setLogForwarding,
getMeshId,
getPublicEncryptionKey,
} = require('../../../../lib/smsClient');

class SetLogForwardingCommand extends Command {
static flags = {
Expand Down Expand Up @@ -85,6 +91,30 @@ class SetLogForwardingCommand extends Command {

if (shouldContinue) {
try {
// Get publicKey for encryption
const publicKey = await getPublicEncryptionKey(imsOrgCode);
if (!publicKey) {
this.error(
`Unable to set log forwarding details. Unable to get public key. Try again. RequestId: ${global.requestId}`,
);
}
// Get the key to encrypt from config
const getEncryptableKey = config => {
if (LogForwardingKeys.LICENSE_KEY in config) return LogForwardingKeys.LICENSE_KEY;
if (LogForwardingKeys.HEC_TOKEN in config) return LogForwardingKeys.HEC_TOKEN;
return null;
};
const keyToEncrypt = getEncryptableKey(destinationConfig.config);
if (!keyToEncrypt) {
this.error(
`Unable to set log forwarding details. No valid key to encrypt found in the configuration. Try again. RequestId: ${global.requestId}`,
);
}
// Encrypt the key
destinationConfig.config[keyToEncrypt] = await encryptSecrets(
publicKey,
destinationConfig.config[keyToEncrypt],
);
const response = await setLogForwarding(
imsOrgCode,
projectId,
Expand Down
6 changes: 6 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ const logFilenameFlag = Flags.string({
required: true,
});

const LogForwardingKeys = {
LICENSE_KEY: 'licenseKey',
HEC_TOKEN: 'hecToken',
};

// The `destinations` object to hold the configuration for log forwarding destinations.
// It prompts for the required inputs for the destination.
// Each destination can have different key/value pairs of configuration credentials.
Expand Down Expand Up @@ -819,4 +824,5 @@ module.exports = {
localToUTCTime,
cachePurgeAllActionFlag,
destinations,
LogForwardingKeys,
};
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8208,7 +8208,7 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==

ms@^2.1.1, ms@^2.1.3:
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
Expand Down
Loading