Skip to content

Commit a7ccaf5

Browse files
authored
feat: expose oauth s2s env (#899)
* feat: expose oauth s2s env * chore: add tests * chore: rename typo
1 parent 30bf9f1 commit a7ccaf5

5 files changed

Lines changed: 121 additions & 3 deletions

File tree

src/lib/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module.exports = {
2222
defaultImageCacheDuration: '604800',
2323
AIO_CONFIG_IMS_ORG_ID: 'project.org.ims_org_id',
2424
SERVICE_API_KEY_ENV: 'SERVICE_API_KEY',
25+
IMS_OAUTH_S2S_ENV: 'IMS_OAUTH_S2S',
2526
ENTP_INT_CERTS_FOLDER: 'entp-int-certs',
2627
CONSOLE_API_KEYS: {
2728
prod: 'aio-cli-console-auth',

src/lib/import-helper.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,31 @@ const getProjectCredentialType = (projectConfig, flags) => {
734734
return LibConsoleCLI.OAUTH_SERVER_TO_SERVER_CREDENTIAL
735735
}
736736

737+
/**
738+
* Get the OAuth server_to_server credential in IMS API format, from the console config.
739+
*
740+
* @param {object} config Console config object
741+
* @returns {{ client_id, client_secret, org_id, scopes } | undefined} OAuthS2S credential or undefined
742+
*/
743+
const getOAuthS2SCredential = (config) => {
744+
const credential = config?.project?.workspace?.details?.credentials
745+
?.find(c => c.integration_type === 'oauth_server_to_server')
746+
?.oauth_server_to_server
747+
const imsOrgId = config?.project?.org?.ims_org_id
748+
749+
if (credential) {
750+
return {
751+
client_id: credential.client_id,
752+
client_secret: credential.client_secrets[0], // take the first secret
753+
org_id: imsOrgId,
754+
scopes: credential.scopes
755+
}
756+
}
757+
}
758+
737759
module.exports = {
738760
getServiceApiKey,
761+
getOAuthS2SCredential,
739762
writeFile,
740763
loadConfigFile,
741764
loadAndValidateConfigFile,

src/lib/import.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const { loadAndValidateConfigFile, importConfigJson, loadConfigFile, getServiceApiKey } = require('./import-helper')
2-
const { SERVICE_API_KEY_ENV } = require('./defaults')
1+
const { loadAndValidateConfigFile, importConfigJson, loadConfigFile, getServiceApiKey, getOAuthS2SCredential } = require('./import-helper')
2+
const { SERVICE_API_KEY_ENV, IMS_OAUTH_S2S_ENV } = require('./defaults')
33

44
/**
55
* Imports the project's console config to the local environment.
@@ -23,7 +23,14 @@ async function importConsoleConfig (consoleConfigFileOrBuffer, flags) {
2323
const config = loadFunc(consoleConfigFileOrBuffer).values
2424

2525
const serviceClientId = getServiceApiKey(config, useJwt)
26-
const extraEnvVars = { [SERVICE_API_KEY_ENV]: serviceClientId }
26+
const oauthS2SCredential = getOAuthS2SCredential(config)
27+
28+
let extraEnvVars
29+
if (typeof oauthS2SCredential === 'object') {
30+
extraEnvVars = { [SERVICE_API_KEY_ENV]: serviceClientId, [IMS_OAUTH_S2S_ENV]: JSON.stringify(oauthS2SCredential) }
31+
} else {
32+
extraEnvVars = { [SERVICE_API_KEY_ENV]: serviceClientId }
33+
}
2734

2835
await importConfigJson(consoleConfigFileOrBuffer, process.cwd(), { interactive, overwrite, merge, useJwt }, extraEnvVars)
2936
return config

test/commands/lib/import-helper.test.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ inquirer.createPromptModule.mockReturnValue(mockPrompt)
2020

2121
const {
2222
getServiceApiKey,
23+
getOAuthS2SCredential,
2324
loadAndValidateConfigFile,
2425
importConfigJson,
2526
writeAio,
@@ -41,6 +42,9 @@ test('exports', () => {
4142
expect(getServiceApiKey).toBeDefined()
4243
expect(getServiceApiKey).toBeInstanceOf(Function)
4344

45+
expect(getOAuthS2SCredential).toBeDefined()
46+
expect(getOAuthS2SCredential).toBeInstanceOf(Function)
47+
4448
expect(loadAndValidateConfigFile).toBeDefined()
4549
expect(loadAndValidateConfigFile).toBeInstanceOf(Function)
4650

@@ -446,3 +450,40 @@ describe('getServiceApiKey', () => {
446450
expect(getServiceApiKey(config, true)).toEqual('XUXUXUXUXUXUXUX')
447451
})
448452
})
453+
454+
describe('getOAuthS2SCredential', () => {
455+
test('bad config (undefined)', () => {
456+
expect(getOAuthS2SCredential(undefined)).toBeUndefined()
457+
})
458+
459+
test('bad config (empty object)', () => {
460+
expect(getOAuthS2SCredential({})).toBeUndefined()
461+
})
462+
463+
test('config file only has jwt (no OAuth S2S)', () => {
464+
const config = fixtureHjson('valid.config.json')
465+
expect(getOAuthS2SCredential(config)).toBeUndefined()
466+
})
467+
468+
test('config file has no OAuth S2S credentials', () => {
469+
const config = fixtureHjson('oauths2s/valid.config.no.creds.json')
470+
expect(getOAuthS2SCredential(config)).toBeUndefined()
471+
})
472+
473+
test('config file has OAuth S2S', () => {
474+
const config = fixtureHjson('oauths2s/valid.config.json')
475+
expect(getOAuthS2SCredential(config)).toEqual({
476+
client_id: 'CXCXCXCXCXCXCXCXC',
477+
client_secret: 'SFSFSFSFSFSFSFSFSFSFSFSFSFS',
478+
org_id: 'XOXOXOXOXOXOX@AdobeOrg',
479+
scopes: ['openid', 'AdobeID']
480+
})
481+
})
482+
483+
test('config file has OAuth S2S (migration, contains jwt)', () => {
484+
// Note: migration configs have integration_type 'oauth_server_to_server_migrate', not 'oauth_server_to_server'
485+
// so getOAuthS2SCredential should return undefined for migration configs
486+
const config = fixtureHjson('oauths2s/valid.config.migrate.json')
487+
expect(getOAuthS2SCredential(config)).toBeUndefined()
488+
})
489+
})

test/commands/lib/import.test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ OF ANY KIND, either express or implied. See the License for the specific languag
1010
governing permissions and limitations under the License.
1111
*/
1212
const inquirer = require('inquirer')
13+
const fs = require('fs-extra')
1314

1415
// mock prompt before import
1516
const mockPrompt = jest.fn()
1617
inquirer.createPromptModule.mockReturnValue(mockPrompt)
1718

1819
const { importConsoleConfig, downloadConsoleConfigToBuffer } = require('../../../src/lib/import')
20+
const { SERVICE_API_KEY_ENV, IMS_OAUTH_S2S_ENV } = require('../../../src/lib/defaults')
21+
22+
jest.mock('fs-extra')
1923

2024
beforeEach(() => {
2125
jest.clearAllMocks()
@@ -29,4 +33,46 @@ test('exports', () => {
2933
expect(downloadConsoleConfigToBuffer).toBeInstanceOf(Function)
3034
})
3135

36+
describe('importConsoleConfig', () => {
37+
test('with oauth_server_to_server credentials, adds IMS_OAUTH_S2S to env vars', async () => {
38+
const configContent = fixtureFile('oauths2s/valid.config.json')
39+
// The file is read twice: once by importConsoleConfig (loadFunc) and once by importConfigJson
40+
fs.readFileSync.mockReturnValue(configContent)
41+
42+
const config = await importConsoleConfig('/some/config/path', { overwrite: true })
43+
44+
expect(config).toBeDefined()
45+
expect(config.project.name).toEqual('TestProject123')
46+
47+
// Check that writeFile was called with the IMS_OAUTH_S2S_ENV variable
48+
const envWriteCall = fs.writeFile.mock.calls.find(call => call[0].endsWith('.env'))
49+
expect(envWriteCall).toBeDefined()
50+
expect(envWriteCall[1]).toContain(SERVICE_API_KEY_ENV)
51+
expect(envWriteCall[1]).toContain(IMS_OAUTH_S2S_ENV)
52+
53+
// Verify the IMS_OAUTH_S2S value contains expected credential data
54+
const envContent = envWriteCall[1]
55+
expect(envContent).toContain('"client_id":"CXCXCXCXCXCXCXCXC"')
56+
expect(envContent).toContain('"client_secret":"SFSFSFSFSFSFSFSFSFSFSFSFSFS"')
57+
expect(envContent).toContain('"org_id":"XOXOXOXOXOXOX@AdobeOrg"')
58+
})
59+
60+
test('with jwt credentials only, does not add IMS_OAUTH_S2S to env vars', async () => {
61+
const configContent = fixtureFile('valid.config.json')
62+
// The file is read twice: once by importConsoleConfig (loadFunc) and once by importConfigJson
63+
fs.readFileSync.mockReturnValue(configContent)
64+
65+
const config = await importConsoleConfig('/some/config/path', { overwrite: true })
66+
67+
expect(config).toBeDefined()
68+
expect(config.project.name).toEqual('TestProject123')
69+
70+
// Check that writeFile was called without the IMS_OAUTH_S2S_ENV variable
71+
const envWriteCall = fs.writeFile.mock.calls.find(call => call[0].endsWith('.env'))
72+
expect(envWriteCall).toBeDefined()
73+
expect(envWriteCall[1]).toContain(SERVICE_API_KEY_ENV)
74+
expect(envWriteCall[1]).not.toContain(IMS_OAUTH_S2S_ENV)
75+
})
76+
})
77+
3278
// The functions in this module are largely tested by use.test.js

0 commit comments

Comments
 (0)