diff --git a/.changeset/brave-coins-boil.md b/.changeset/brave-coins-boil.md new file mode 100644 index 00000000000..2861d42923e --- /dev/null +++ b/.changeset/brave-coins-boil.md @@ -0,0 +1,5 @@ +--- +'@sap-ux/btp-utils': patch +--- + +Update S4HC to validate hostname diff --git a/packages/abap-deploy-config-sub-generator/test/unit/utils/helpers.test.ts b/packages/abap-deploy-config-sub-generator/test/unit/utils/helpers.test.ts index cffc2a937db..e4db0e0f8d5 100644 --- a/packages/abap-deploy-config-sub-generator/test/unit/utils/helpers.test.ts +++ b/packages/abap-deploy-config-sub-generator/test/unit/utils/helpers.test.ts @@ -37,7 +37,7 @@ const mockDestinations = { Type: 'HTTP', Authentication: 'SAMLAssertion', Description: 'Mock destination 2', - Host: 'https://mock.url.dest2.com', + Host: 'https://mock.s4hana.url.dest2.com', ProxyType: 'Internet', WebIDEUsage: 'odata_abap' } diff --git a/packages/btp-utils/src/destination.ts b/packages/btp-utils/src/destination.ts index 9110c588cb6..750eacdeebe 100644 --- a/packages/btp-utils/src/destination.ts +++ b/packages/btp-utils/src/destination.ts @@ -1,3 +1,8 @@ +/** + * Validates whether the provided destination string contains 's4hana.' or 's4hanacloud.'. + */ +const s4hanaHostRegex = /s4hana\.|s4hanacloud\./i; + /** * Support different Token Service URL Types */ @@ -238,16 +243,17 @@ export function getDisplayName(destination: Destination, displayUsername?: strin } /** - * Checks whether the provided destination is configured to point to an S/4 HANA system. + * Checks whether the provided destination is configured to point to an S/4 HANA Public Cloud system. * * @param destination destination info - * @returns boolean if the destination is configured for an SAP S/4HANA system + * @returns boolean if the destination is configured for an SAP S/4HANA public cloud system */ export function isS4HC(destination: Destination): boolean { return Boolean( destination.WebIDEUsage?.includes(WebIDEUsage.ODATA_ABAP) && destination.Authentication === Authentication.SAML_ASSERTION && - destination.ProxyType === ProxyType.INTERNET + destination.ProxyType === ProxyType.INTERNET && + s4hanaHostRegex.test(destination.Host.toLowerCase()) ); } diff --git a/packages/btp-utils/test/app-studio.test.ts b/packages/btp-utils/test/app-studio.test.ts index 1694fcd6aa5..f3de0bb53a0 100644 --- a/packages/btp-utils/test/app-studio.test.ts +++ b/packages/btp-utils/test/app-studio.test.ts @@ -186,7 +186,7 @@ describe('App Studio', () => { expect(!!actualDestinations[destination.Name]).toBe(destination.WebIDEEnabled === 'true'); }); // test host remains unchanged when no opts passed to api - expect(actualDestinations['S4HC'].Host).toBe('https://s4hc-example-api.sap.example'); + expect(actualDestinations['S4HC'].Host).toBe('https://my41111-api.s4hana.ondemand.com'); }); test('nothing returned', async () => { @@ -200,7 +200,7 @@ describe('App Studio', () => { .get('/api/listDestinations') .replyWithFile(200, join(__dirname, 'mockResponses/destinations.json')); const destinationsWithOpts = await listDestinations({ stripS4HCApiHosts: true }); - expect(destinationsWithOpts['S4HC'].Host).toBe('https://s4hc-example.sap.example'); + expect(destinationsWithOpts['S4HC'].Host).toBe('https://my41111.s4hana.ondemand.com'); }); }); diff --git a/packages/btp-utils/test/destination.test.ts b/packages/btp-utils/test/destination.test.ts index 658085d3336..347ba6fa48a 100644 --- a/packages/btp-utils/test/destination.test.ts +++ b/packages/btp-utils/test/destination.test.ts @@ -21,6 +21,9 @@ import destinations from './mockResponses/destinations.json'; const destination: Destination = destinations.find((destination) => destination.Name === 'NO_ADDITIONAL_PROPERTIES')!; const S4HCDestination: Destination = destinations.find((destination) => destination.Name === 'S4HC')!; const btpDestination: Destination = destinations.find((destination) => destination.Name === 'ABAP_ON_BTP')!; +const abapCloud: Destination = destinations.find( + (destination) => destination.Name === 'abap-cloud-my-abap-env-testorg-testspace' +)!; describe('destination', () => { describe('isAbapSystem', () => { @@ -188,6 +191,9 @@ describe('destination', () => { }) ).toBe(true); }); + it('Authentication set to SamlAssertion, internet facing and contains the required hostname', () => { + expect(isS4HC({ ...S4HCDestination, Host: 'https://my41111-api.saps4hanacloud.cn' })).toBe(true); + }); it('Authentication set to SamlAssertion and is OnPremise', () => { expect( isS4HC({ @@ -196,6 +202,11 @@ describe('destination', () => { }) ).toBe(false); }); + it('Authentication set to SamlAssertion and is Internet and using ABAP Cloud host', () => { + expect( + isS4HC(abapCloud) + ).toBe(false); + }); }); describe('Test if destination is odata abap, cloud or on prem', () => { diff --git a/packages/btp-utils/test/mockResponses/destinations.json b/packages/btp-utils/test/mockResponses/destinations.json index cc7b449e4b3..2ef0a5c84af 100644 --- a/packages/btp-utils/test/mockResponses/destinations.json +++ b/packages/btp-utils/test/mockResponses/destinations.json @@ -66,9 +66,9 @@ "Description": "S4HC for ABAP Cloud Deployment", "WebIDEEnabled": "true", "WebIDEUsage": "odata_abap,dev_abap", - "Host": "https://s4hc-example-api.sap.example", + "Host": "https://my41111-api.s4hana.ondemand.com", "HTML5.DynamicDestination": "true", - "audience": "https://s4hc-example.sap.example", + "audience": "https://s4hana-example.sap.example", "authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession" }, { diff --git a/packages/deploy-config-sub-generator/test/headless/__snapshots__/abap-headless.test.ts.snap b/packages/deploy-config-sub-generator/test/headless/__snapshots__/abap-headless.test.ts.snap index 79884fee4b1..90d750cd96c 100644 --- a/packages/deploy-config-sub-generator/test/headless/__snapshots__/abap-headless.test.ts.snap +++ b/packages/deploy-config-sub-generator/test/headless/__snapshots__/abap-headless.test.ts.snap @@ -117,7 +117,7 @@ builder: configuration: target: destination: Dest2 - url: https://mock.url.dest2.com + url: https://mock.s4hana.url.dest2.com authenticationType: reentranceTicket # SAML support for vscode app: name: MY_UI5_ABAP_REPO diff --git a/packages/deploy-config-sub-generator/test/headless/fixtures/constants/destinations.ts b/packages/deploy-config-sub-generator/test/headless/fixtures/constants/destinations.ts index 4ad53e8c48f..3fe5b26ca29 100644 --- a/packages/deploy-config-sub-generator/test/headless/fixtures/constants/destinations.ts +++ b/packages/deploy-config-sub-generator/test/headless/fixtures/constants/destinations.ts @@ -13,7 +13,7 @@ export const mockDestinations = { Type: 'HTTP', Authentication: 'SAMLAssertion', Description: 'Mock destination 2', - Host: 'https://mock.url.dest2.com', + Host: 'https://mock.s4hana.url.dest2.com', ProxyType: 'Internet', WebIDEUsage: 'odata_abap' }