Inline JavaScript with CSP enabled

I am currently fighting with some modules and making them “Enable strict content security policy” compatible.

since script tags are not allowed and the CSP header also has no nonce for that. I did a little workaround providing the javascript by using a controller action:

    public function kickstartAction()
    {
        $script = <<<EOD
            var interval = setInterval(function () {
                if (typeof icinga == 'undefined') return;
                clearInterval(interval);

                var modulname = "mapDatatype";
                if (icinga.isLoadedModule(modulname)) {
                    icinga.modules.mapDatatype.initialize();
                } else {
                    icinga.loadModule(modulname)
                }

            }, 10);
EOD;

                ob_get_clean();
                header("Content-type: application/javascript");
                header('Pragma: public');
                ob_clean();
                flush();
                echo $script;
                exit;

    }

}

location.phtml:

<?php
    $jsUrl = \ipl\Web\Url::fromPath('mapDatatype/js/kickstart');
?>
        <script src=<?php echo $jsUrl; ?> ></script>

This only works on initial load but not on any ajax refresh if loaded in a second column.

Is there any hope of allowing script tags in icingaweb2 using a nonce?

Or is there any other workaround?

Best Regards
Nicolas

There is, but I’d rather want to know whether what you showed is only a weird example or really a case you want to support.

Because, what you’re doing there is … I don’t even have a word for it. :rofl:

What’s the problem you want to solve with this?

Sorry for derailing the question.

I forgot to write that this example is from mapDatatype, which makes it more complicated since it’s loaded as a Director Datatype:

I don’t know how the director implements data type hooks, but your form elements should be in a container with data-icinga-module set to mapDatatype.

Though, it’s currently set to map and the container resides somewhere where it shouldn’t, probably? Why is #col1 inside a dd tag? Looks like a nested column with a duplicate id to me.

<div class="container icinga-module module-mapDatatype module-map map-container" data-icinga-module="mapDatatype">

with that change and the removal of the col1 the js code is no longer necessary, which is great, but the module.js → initialize is still not loaded again on ajax refresh.

Is there any javascript reattaching magic for icingaweb2?

I left the module-map in order to still use the css from the map module

No magic needed. Module initialization is only done once, on purpose.

It’s expected to only do basic stuff there, plus maybe event handler registration.

And that’s what you want, a listener for the rendered event. This fires potentially right after your module has been initialized for the first time.

is that the part where the rerendering can take place:

That’s a rather outdated example. But yeah.

You already have a reference to the module instance: this.module

There you can use .on("rendered"[, selector], handler)

like this? → cause it works

    MapDatatype.prototype = {
        initialize: function () {
            this.module.on('rendered', this.rendered);


        },
        rendered: function(event) {
            // Fetch map config
            var that = this;

            $.getJSON(icinga.config.baseUrl + '/map/config/fetch?type=director', this._newMap).fail(function (jqxhr, textStatus, error) {
                that._newMap({
                    "default_zoom": "4",
                    "default_long": '13.377485',
                    "default_lat": '52.515855',
                    "min_zoom": "2",
                    "max_zoom": "19",
                    "max_native_zoom": "19",
                    "tile_url": "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                });
            });
        },

Congrats :slight_smile: :slight_smile: :slight_smile: :slight_smile: (long enough?)

1 Like

Thanks a lot! :heart: :heart: and now I understand the “(long enough?)” :laughing: