HTML+ Portlet using the fetch API to get data from webhook server failure

Hi,

The objective is to get JSON data from the webhook server.

I am getting a failure on the HTML+ portlet when using the fetch API to do a REST POST Request to the webhook server:

Refused to connect to 'flaalmmvb01.mtn.co.za:5000/.../OctaneDetails' because it violates the following Content Security Policy directive: "default-src blob: 'self' 'unsafe-inline' 'unsafe-eval' img.youtube.com app.powerbi.com admhelp.microfocus.com www.youtube.com". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.

sendPostRequest @ VM507:22Understand this error
16:59:44.493 VM507:22 Refused to connect to 'flaalmmvb01.mtn.co.za:5000/.../OctaneDetails' because it violates the document's Content Security Policy.
sendPostRequest @ VM507:22Understand this error
16:59:44.493 VM507:37 Error fetching data: TypeError: Failed to fetch
at HTMLButtonElement.sendPostRequest (eval at eval (PortletUtilitiesJS.jsp:477:25), <anonymous>:22:5)

I looked at the HTML+ Portlet tutorial on GitHub (https://github.com/MicroFocus/ppm-html-plus-portlets), for the REST API as well as ChatGPT guidance on the usage of the fetch API in JavaScript

Not sure what I am doing wrong

Here is my HTML which used for testing the HTML+ Portlet:

<div><button id="submit-button">Submit</button></div>
<div id="response"></div>

My JavaScript code:

// Replacing raw data by property-indexed data
data = DF.HtmlPlusUtils.utils.indexDataByColumnKey(data, metadata.columnsInfo);
// Function to perform a POST request with custom JSON payload
function sendPostRequest() {
    // Define variables for the payload
    const epicUrl = 'http://nlaoctmve103.mtn.co.za:8080/ui/entity-navigation?p=5001/7001&entityType=work_item&id=46003';

    // Construct the JSON payload
    const payload = {
        name: epicUrl
    };

    const url = 'http://FLAALMMVB01.mtn.co.za:5000/webhook/OctaneDetails'; // Replace with your API endpoint
    const headers = new Headers({
        // 'Accept': 'application/json',
        'content-type': 'application/json'
    });

    fetch(url, {
        method: 'POST',
        headers: headers,
        body: JSON.stringify(payload)
    })
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok ' + response.statusText);
            }
            return response.json();
        })
        .then(data => {
            displayResponse(data);
        })
        .catch(error => {
            console.error('Error fetching data:', error);
            displayResponse({ error: error.message });
        });
}

// Function to display the response from the server
function displayResponse(data) {
    const responseDiv = document.getElementById('response');
    responseDiv.textContent = JSON.stringify(data, null, 2);
}

// Add event listener to the button
document.getElementById('submit-button').addEventListener('click', sendPostRequest);

If I test in Postman then I get a JSON response back from the webhook server.

It seems it's my JavaScript because I also get "Fail to Fetch" error in IntelliJ IDEA 2024.1.2 (Ultimate Edition).

Lastly, with PPM 24.3 webhook functionality, I successfully send a request to the webhook server.

Any suggestions on what I am doing wrong?

Thanks.

Regards,

Alfred Puth

iOCO: Senior PPM Consultant

  • 0  

    Hi Alfred,

    I don't see how that's related to WebHooks. You're just trying to make a POST call to a different server from the UI of the PPM server. I suggest you to first get familiar with the concept and limitation of Same-Origin Policy - also, you should try to add the address of the server you're trying to call to the PPM Server parameter "TRUSTED_EXTERNAL_URLS", as it will insert it into the content security policy directive for most interactions with it. If it's not enough, you'll need to manually set the Content-Policy header of PPM Server instead of relying on the default one. 

  • 0 in reply to   

    Hi Etienne,

    I have updated the server parameter CONTENT_SECURITY_POLICY from the default to "default-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data: *;" which solved the issue.

    I noticed in the server.conf file that the CONTENT_SECURITY_POLICY parameter was disabled but I still received the same error message until I applied the change to the parameter.

    Regards,

    Alfred Puth

    iOCO: Senior PPM Consultant

  • 0   in reply to 

    Of course that will solve your problem, because you basically entered a value of content-security-policy that allows loading data and interacting with any web site - that is NOT considered a secure configuration. But, sure, that will work, so, your call :)

    My recommendation is still for you to spend some time understanding the purpose of content-security-policy header (one possible source), and then figure out which TRUSTED_URLS values to set in order to allow making the POST request from HTML+ portlet to the target server - and still prevent calls to other non-trusted servers instead of allowing calls to all servers like you did.

  • 0 in reply to   

    Hi Etienne,

    Thanks for the source and I spend some time on it and added connect-src to the default policy.

    The following configuration is working in our PPM Development environment:

    CONTENT_SECURITY_POLICY=default-src blob: 'self' 'unsafe-inline' 'unsafe-eval' %TRUSTED_EXTERNAL_URLS%;img-src 'self' data: %TRUSTED_EXTERNAL_URLS%;connect-src blob: 'self' 'unsafe-inline' 'unsafe-eval' data: *;font-src 'self' data:

    I also added the PPM server and the Webhook server to the Trusted External URLs paramater:

    TRUSTED_EXTERNAL_URLS=https://app.powerbi.com admhelp.microfocus.com https://img.youtube.com https://www.youtube.com http://nlappmrvd01.mtn.co.za http://FLAALMMVB01.mtn.co.za

    Regards,

    Alfred Puth

    iOCO: Senior PPM Consultant