wemanity-belgium / hyperclair

DEPRECATED [mv to https://github.com/jgsqware/clairctl] -> A CLI for using Clair with Registry
https://github.com/jgsqware/clairctl
MIT License
58 stars 13 forks source link

Generated HTML report doesn't contain vulnarabilities #83

Open jaiwo99 opened 8 years ago

jaiwo99 commented 8 years ago
<div class="features">
   <ul>                           
   </ul>
</div>

The whole feature section is empty. The json report is correct

jgsqware commented 8 years ago

Could you provide your json, or the docker image if it's publc?

jaiwo99 commented 8 years ago

Hi, sure!

I have tried with this image: bfops/ubuntu12

You can find the reports in both HTML and Json format from attachment!

reports.zip

jaiwo99 commented 8 years ago

Hi there,

it is so far not possible to generate html with content, i wrote a template parse the JSON report, if someone also needed, here is the code:

<html>
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
    <script   src="https://code.jquery.com/jquery-2.2.4.min.js"   integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>

<div id="container"></div>

<script id="report-template" type="text/x-handlebars-template">
    <div class="container">
        <ul class="nav nav-tabs" role="tablist">
            {{#Layers}}
            <li role="presentation" class="{{firstElementActive @index}}"><a href="#{{@index}}" aria-controls="{{Layer.Name}}" role="tab" data-toggle="tab"><strong>Layer</strong> - {{@index}} ({{countLayerVulnerabilities Layer}})</a></li>
            {{/Layers}}
        </ul>

        <!-- Tab panes -->
        <div class="tab-content">
            {{#Layers}}
            <div role="tabpanel" class="fade tab-pane {{firstElementActive @index}}" id="{{@index}}">
                <div class="panel panel-default">
                    <!-- Default panel contents -->
                    <div class="panel-heading"><strong>Layer:</strong> {{Layer.Name}}</div>
                    <div class="panel-body">
                        <ul class="list-group">
                            <li class="list-group-item"><strong>Name:</strong> {{Layer.Name}}</li>
                            <li class="list-group-item"><strong>Namespace:</strong> {{Layer.Namespace}}</li>
                            <li class="list-group-item"><strong>ParentName:</strong> {{Layer.ParentName}}</li>
                        </ul>
                    </div>

                    {{#if Layer.Features}}
                    <table class="table table-condensed table-hover">
                        <thead>
                        <tr>
                            <th>Name</th>
                            <th>Namespace</th>
                            <th>Version</th>
                            <th>Vulnerabilities</th>
                        </tr>
                        </thead>
                        <tbody>
                        {{#Layer.Features}}
                        <tr class="feature-detail" data-name="{{Name}}">
                            <td>{{Name}}</td>
                            <td>{{Namespace}}</td>
                            <td>{{Version}}</td>
                            <td>{{countFeatureVulnerabilities Vulnerabilities}}</td>
                        </tr>
                        {{#if Vulnerabilities}}
                        {{#Vulnerabilities}}
                        <tr class="hide vulnerability-detail {{../Name}}">
                            <td colspan="3"><a href="{{Link}}" target="_blank">{{Name}}</a></td>
                            <td>{{Severity}}</td>
                        </tr>
                        {{/Vulnerabilities}}
                        {{/if}}
                        {{/Layer.Features}}
                        </tbody>
                    </table>
                    {{/if}}
                </div>
            </div>
            {{/Layers}}
        </div>

    </div>
</script>
<script>
    $(function () {
        $.getJSON("data.json", function(json) {
            var data = json;
            var source = $('#report-template').html();

            var template = Handlebars.compile(source);

            Handlebars.registerHelper('countLayerVulnerabilities', countLayerVulnerabilities);
            Handlebars.registerHelper('countFeatureVulnerabilities', countFeatureVulnerabilities);
            Handlebars.registerHelper('firstElementActive', firstElementActive);

            $('#container').append(template(data));

            $(".feature-detail").click(function () {
                if ($(this).children('td').last().text() !== '0') {
                    var name = $(this).data('name');
                    console.debug("name:" + name);
                    $(this).nextAll('tr.'+name).toggleClass('hide');
                }
            });

        });
    });

    function countLayerVulnerabilities(layer) {
        var sum = 0;

        if (layer.Features) {
            layer.Features.forEach(function (feature) {
                if (feature.Vulnerabilities) {
                    sum += feature.Vulnerabilities.length;
                }
            })
        }

        return sum;
    }

    function countFeatureVulnerabilities(vulnerabilities) {
        if (vulnerabilities) {
            return vulnerabilities.length
        } else {
            return 0;
        }
    }

    function firstElementActive(index) {
        if (index == 0) {
            return 'active in';
        } else {
            return '';
        }
    }
</script>
</body>
</html>
jgsqware commented 8 years ago

The report should work, I will investigate your image, why it's not working.

jaiwo99 commented 8 years ago

Hi @jgsqware , thanks.. checkout the sample link from hyperclair homepage in report section, it doesn't work either i think.. it is not really related to my image..

kuekuune commented 8 years ago

I second to @jaiwo99: HTML report does not work and contains only bottommost layer. I dug around a bit and found following piece of code: https://github.com/wemanity-belgium/hyperclair/blob/fd7248d1d00f5b72ac8269913f4aaaad9f85c9c9/clair/clair.go#L295 // for _, l := range imageAnalysis.Layers { For cycle is commented out that iterates over layers for some reason, so only bottommost layer is parsed into template. Actually there are lines 102 and 243 commented out as well which require uncommenting

jharshman commented 8 years ago

+1 for fixing. The json report is correct but not reader friendly Html report needs fixing

jharshman commented 8 years ago

using pre-release 0.4.0 works just fine & doesn't have the html reporting issue which was introduced in fd7248d1d00f5b72ac8269913f4aaaad9f85c9c9

joberget commented 8 years ago

Has this issue been fixed?

jharshman commented 8 years ago

Unfortunately not. Like I mentioned, 0.4.0 release works fine. Feel free to check out my fork which has the fix here

mingfang commented 8 years ago

I'm having the same problem; json report works fine but html report is blank.

jharshman commented 8 years ago

As mentioned before, the HTML report only contains the information for the bottom-most layer. This is due to an issue introduced in fd7248d. Version 0.4.0 works fine but the report isn't as "pretty".