/
samm-charts.min.js
17 lines (14 loc) · 20.8 KB
/
samm-charts.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
@license
Copyright 2015 Qudosoft GmbH & Co. KG
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
!function(e,t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=t(require("jquery")):e.SAMMCharts=t(e.jQuery)}(this,function(e,t){"use strict";String.prototype.format||(String.prototype.format=function(){var e=arguments;return this.replace(/{(\d+)}/g,function(t,r){return"undefined"!=typeof e[r]?e[r]:t})});var r={categories:[{category:"G",name:"Governance",img:"G.png",href:"https://www.owasp.org/index.php/SAMM_-_Governance",color:"lightblue",color_dark:"#014E6C",practices:[{practice:"SM",name:"Strategy & Metrics",img:"SM.png",href:"https://www.owasp.org/index.php/SAMM_-_Governance#Strategy_.26_Metrics",baseHref:"https://www.owasp.org/index.php/SAMM_-_Strategy_%26_Metrics",activities:[["A. Estimate overall business risk profile","B. Build and maintain assurance program roadmap"],["A. Classify data and applications based on business risk","B. Establish and measure per-classification security goals"],["A. Conduct periodic industry-wide cost comparisons","B. Collect metrics for historic security spend"]]},{practice:"PC",name:"Policy & Compliance",img:"PC.png",href:"https://www.owasp.org/index.php/SAMM_-_Governance#Policy_.26_Compliance",baseHref:"https://www.owasp.org/index.php/SAMM_-_Policy_%26_Compliance",activities:[["A. Identify and monitor external compliance drivers","B. Build and maintain compliance guidelines"],["A. Build policies and standards for security and compliance","B. Establish project audit practice"],["A. Create compliance gates for projects","B. Adopt solution for audit data collection"]]},{practice:"EG",name:"Education & Guidance",img:"EG.png",href:"https://www.owasp.org/index.php/SAMM_-_Governance#Education_.26_Guidance",baseHref:"https://www.owasp.org/index.php/SAMM_-_Education_%26_Guidance",activities:[["A. Conduct technical security awareness training","B. Build and maintain technical guidelines"],["A. Conduct role-specific application security training","B. Utilize security coaches to enhance project teams"],["A. Create formal application security support portal","B. Establish role-based examination/certification"]]}]},{category:"C",name:"Construction",img:"C.png",href:"https://www.owasp.org/index.php/SAMM_-_Construction",color:"peru",color_dark:"#6B3416",practices:[{practice:"TA",name:"Threat Assessment",img:"TA.png",href:"https://www.owasp.org/index.php/SAMM_-_Construction#Threat_Assessment",baseHref:"https://www.owasp.org/index.php/SAMM_-_Threat_Assessment",activities:[["A. Build and maintain application-specific threat models","B. Develop attacker profile from software architecture"],["A. Build and maintain abuse-case models per project","B. Adopt a weighting system for measurement of threats"],["A. Explicitly evaluate risk from third-party components","B. Elaborate threat models with compensating controls"]]},{practice:"SR",name:"Security Requirements",img:"SR.png",href:"https://www.owasp.org/index.php/SAMM_-_Construction#Security_Requirements",baseHref:"https://www.owasp.org/index.php/SAMM_-_Security_Requirements",activities:[["A. Derive security requirements from business functionality","B. Evaluate security and compliance guidance for requirements"],["A. Build an access control matrix for resources and capabilities","B. Specify security requirements based on known risks"],["A. Build security requirements into supplier agreements","B. Expand audit program for security requirements"]]},{practice:"SA",name:"Secure Architecture",img:"SA.png",href:"https://www.owasp.org/index.php/SAMM_-_Construction#Security_Architecture",baseHref:"https://www.owasp.org/index.php/SAMM_-_Secure_Architecture",activities:[["A. Maintain list of recommended software frameworks","B. Explicitly apply security principles to design"],["A. Identify and promote security services and infrastructure","B. Identify security design patterns from architecture"],["A. Establish formal reference architectures and platforms","B. Validate usage of frameworks, patterns, and platforms"]]}]},{category:"V",name:"Verification",img:"V.png",href:"https://www.owasp.org/index.php/SAMM_-_Verification",color:"darkseagreen",color_dark:"#116D37",practices:[{practice:"DR",name:"Design Review",img:"DR.png",href:"https://www.owasp.org/index.php/SAMM_-_Verification#Design_Review",baseHref:"https://www.owasp.org/index.php/SAMM_-_Design_Review",activities:[["A. Identify software attack surface","B. Analyze design against known security requirements"],["A. Inspect for complete provision of security mechanisms","B. Deploy design review service for project teams"],["A. Develop data-flow diagrams for sensitive resources","B. Establish release gates for design review"]]},{practice:"CR",name:"Code Review",img:"CR.png",href:"https://www.owasp.org/index.php/SAMM_-_Verification#Code_Review",baseHref:"https://www.owasp.org/index.php/SAMM_-_Code_Review",activities:[["A. Create review checklists from known security requirements","B. Perform point-review of high-risk code"],["A. Utilize automated code analysis tools","B. Integrate code analysis into development process"],["A. Customize code analysis for application-specific concerns","B. Establish release gates for code review"]]},{practice:"ST",name:"Security Testing",img:"ST.png",href:"https://www.owasp.org/index.php/SAMM_-_Verification#Security_Testing",baseHref:"https://www.owasp.org/index.php/SAMM_-_Security_Testing",activities:[["A. Derive test cases from known security requirements","B. Conduct penetration testing on software releases"],["A. Utilize automated security testing tools","B. Integrate security testing into development process"],["A. Employ application-specific security testing automation","B. Establish release gates for security testing"]]}]},{category:"D",name:"Deployment",img:"D.png",href:"https://www.owasp.org/index.php/SAMM_-_Deployment",color:"indianred",color_dark:"#6C0F14",practices:[{practice:"VM",name:"Vulnerability Management",img:"VM.png",href:"https://www.owasp.org/index.php/SAMM_-_Deployment#Vulnerability_Management",baseHref:"https://www.owasp.org/index.php/SAMM_-_Vulnerability_Management",activities:[["A. Identify point of contact for security issues","B. Create informal security response team(s)"],["A. Establish consistent incident response process","B. Adopt a security issue disclosure process"],["A. Conduct root cause analysis for incidents","B. Collect per-incident metrics"]]},{practice:"EH",name:"Environment Hardening",img:"EH.png",href:"https://www.owasp.org/index.php/SAMM_-_Deployment#Environment_Hardening",baseHref:"https://www.owasp.org/index.php/SAMM_-_Environment_Hardening",activities:[["A. Maintain operational environment specification","B. Identify and install critical security upgrades and patches"],["A. Establish routine patch management process","B. Monitor baseline environment configuration status"],["A. Identify and deploy relevant operations protection tools","B. Expand audit program for environment configuration"]]},{practice:"OE",name:"Operational Enablement",img:"OE.png",href:"https://www.owasp.org/index.php/SAMM_-_Deployment#Operational_Enablement",baseHref:"https://www.owasp.org/index.php/SAMM_-_Operational_Enablement",activities:[["A. Capture critical security information for deployment","B. Document procedures for typical application alerts"],["A. Create per-release change management procedures","B. Maintain formal operational security guides"],["A. Expand audit program for operational information","B. Perform code signing for application components"]]}]}]},i="http://www.opensamm.org/badges/small/",a="",n={imgURLBase:i,imgURLSuffix:a,namespace:function(e){for(var t=e.split("."),r=n,i=1,a=t.length;a>i;i++){var o=t[i];r[o]=r[o]||{},r=r[o]}return r},getImgURL:function(e){if("undefined"==typeof e)throw new Error("Missing image parameter.");return this.imgURLBase+e+this.imgURLSuffix},resetImgURL:function(){this.imgURLBase=i,this.imgURLSuffix=a}};return n.namespace("SAMMCharts.Scorecard"),n.Scorecard=function(t){var i=this,a={header:'<table cellspacing="0" cellpadding="0"><thead><tr align="center"><th>Practices / Levels</th><th style="width: {0}px;">0</th><th style="width: {0}px;">0+</th><th style="width: {0}px;">1</th><th style="width: {0}px;">1+</th><th style="width: {0}px;">2</th><th style="width: {0}px;">2+</th><th style="width: {0}px;">3</th></tr></thead></table>'.format(50),category:'<tr style="background-color: lightgrey;"><td><a href="{0}"><img alt="{1}" src="{2}" width="200px" /></a></td><td colspan="8"></td></tr>',practice:'<tr style="background-color: {0}; height: 30px;"><td align="center"><div><a href="{1}" style="text-decoration: none; color:black;" target="_blank">{2}</a></div> </td>'},o="#EEE";this.initialize=function(e){if(!e.element)throw new Error("SAMMCharts Scorecard needs an element selector");if(!e.scores)throw new Error("SAMMCharts Scorecard needs a score object");this.element=e.element,this.scores=e.scores,this.validateScores(e.scores)},this.render=function(){var t=e(i.element);t.append(a.header);var s=e(i.element+" table");e.each(r.categories,function(t,r){s.append(a.category.format(r.href,r.name,n.getImgURL(r.img)));var c="";e.each(r.practices,function(e,t){c+=a.practice.format(o,t.href,t.name);var n=2*i.scores[r.name.toLowerCase()][e]+1;c+=new Array(n+1).join('<td style="background-color: {0}"></td>'.format(r.color_dark)),c+=new Array(8-n+1).join("<td></td>"),c+="</tr>"}),s.append(c)})},this.validateScores=function(e){if(!(e instanceof Object))throw new Error("scores is not an object: {0}".format(e));var t=["governance","construction","verification","deployment"];t.forEach(function(t,r){var i=e[t];if(!i)throw new Error("scores is missing {0}: {1}".format(t,JSON.stringify(e)));if(!Array.isArray(i))throw new Error("'{0}' scores is not an array: {1}".format(t,JSON.stringify(i)));if(3!=i.length)throw new Error("'{0}' scores must have exactly 3 entries. Actual count: {1}".format(t,i.length));i.forEach(function(e,r){if("number"!=typeof e||0>e||e>3)throw new Error("{0} scores contains invalid score value(s). Allowed values are numbers between 0 and 3. Actual values: {1}".format(t,JSON.stringify(i)));if(e%.5!=0)throw new Error("{0} scores contains invalid score value(s). Allowed values are integers or .5 doubles. Actual values: {1}".format(t,JSON.stringify(i)))})})},this.initialize(t)},n.namespace("SAMMCharts.Roadmap"),n.Roadmap=function(i){var a=this;this.initialize=function(e){if(!e.element)throw new Error("SAMMCharts Roadmap needs an element selector");if("undefined"==typeof e.phaseCount)throw new Error("SAMMCharts Roadmap needs a phaseCount");if(!e.roadmap)throw new Error("SAMMCharts Roadmap needs a roadmap object");this.element=e.element,this.phasesSummaryElement=e.phasesSummaryElement||t,this.phaseCount=e.phaseCount,this.roadmap=e.roadmap,o(),s(),this.alpha="undefined"==typeof e.alpha?.7:e.alpha,this.displayEfforts="undefined"==typeof e.displayEfforts?!0:e.displayEfforts,e.currentPhase=e.currentPhase||{},this.currentPhase=e.currentPhase.phase,this.currentLevels=e.currentPhase.levels||{},"undefined"!=typeof this.currentPhase&&(c(),p()),this.practiceWidth=129,this.practicePadding=10,this.phaseWidth=30,this.levelHeight=15,this.phaseHeaderHeight=12,this.phaseHeaderPadding=5,this.effortsPaddingTop=5,this.practiceLabelWidth=this.practiceWidth+this.practicePadding,this.rulerLeftWidth=Math.floor(2*this.phaseWidth/3),this.rulerRightWidth=Math.floor(this.phaseWidth/2),e.fonts=e.fonts||{},e.fonts.phases=e.fonts.phases||{},e.fonts.practices=e.fonts.practices||{},e.fonts.efforts=e.fonts.efforts||{},this.fonts={phases:{size:e.fonts.phases.size||"10",font:e.fonts.phases.font||"Arial",style:e.fonts.phases.style||"italic"},practices:{size:e.fonts.practices.size||"10",font:e.fonts.practices.font||"Arial",style:e.fonts.practices.style||"bold"},efforts:{size:e.fonts.efforts.size||"11",font:e.fonts.efforts.font||"Arial",style:e.fonts.efforts.style||"bold"}},e.colors=e.colors||{},this.colors={header:e.colors.header||"#000",arrow:e.colors.arrow||"#AAA",ruler:e.colors.ruler||"#ADADAD",barLight:e.colors.barLight||"#F3F3F3",barRegular:e.colors.barRegular||"#EEE",barDark:e.colors.barDark||"#DDD"}};var o=function(){if(a.phaseCount<1||a.phaseCount%1!=0)throw new Error("Phase count has to be an Integer greater 0")},s=function(){if(!(a.roadmap instanceof Object))throw new Error("Roadmap is not an object: {0}".format(a.roadmap));r.categories.forEach(function(e,t){e.practices.forEach(function(e,t){var r=a.roadmap[e.practice];if(!r)throw new Error("Missing roadmap entry for practice '{0}' ({1}). Roadmap is: {2}".format(e.practice,e.name,JSON.stringify(a.roadmap)));if(!Array.isArray(r))throw new Error("Roadmap for '{0}' ({1}) is not an array: {2}".format(e.practice,e.name,JSON.stringify(r)));if(r.length<a.phaseCount)throw new Error("Wrong number of phases for '{0}' ({1}) roadmap. Expected phase count is {2}. Actual roadmap: {3}".format(e.practice,e.name,a.phaseCount,JSON.stringify(r)));var i=0;r.forEach(function(t,a){if(Number(t)!==t||t%1!==0||0>t||t>3)throw new Error("Level value of phase {1} for practice '{2}' must be an Integer between 1 and 3. Found: {0}".format(JSON.stringify(t),a+1,e.practice));if(i>t)throw new Error("Level of phase {0} for practice '{1}' must be greater or equal than level of previous phase. Found: {2}".format(a+1,e.practice,JSON.stringify(r)));i=t})})})},c=function(){if(a.currentPhase<1||a.currentPhase>a.phaseCount)throw new Error("Current phase must be between 1 and {1}: Found: {0}".format(a.currentPhase,a.phaseCount))},p=function(){if(!(a.currentLevels instanceof Object))throw new Error("current levels is not an object: {0}".format(a.currentLevels));r.categories.forEach(function(e,t){e.practices.forEach(function(e,t){var r=a.currentLevels[e.practice];if("undefined"==typeof r)throw new Error("Missing level entry for practice '{0}' ({1}). Levels are: {2}".format(e.practice,e.name,JSON.stringify(a.currentLevels)));if(Number(r)!==r||r%1!==0||0>r||r>3)throw new Error("Level value of phase {1} for practice '{2}' must be an Integer between 1 and 3. Found: {0}".format(JSON.stringify(r),k+1,e.practice))})})};this.render=function(){if(this.canvas=l(),!this.canvas[0].getContext)throw new Error("Error setting up 2D context for canvas: "+this.canvas);this.ctx=this.canvas[0].getContext("2d"),this.ctx.translate(.5,.5),d(),w(),y(),a.currentPhase&&v(),a.displayEfforts&&S()},this.renderPhaseSummaries=function(){if(!this.phasesSummaryElement)throw new Error("Missing configuration parameter 'phaseElement'");for(var t=0;t<this.phaseCount;t++){var r="<h3>Phase {0} Details</h3><div>{1}</div>".format(t+1,h(t+1));e(this.phasesSummaryElement).append(r)}},this.renderPhaseSummary=function(t,r){e(r).append(h(t))};var h=function(t){if(t>a.phaseCount||0>t)throw new Error("Phase number has to be > 0 and < "+a.phaseCount);var i=[];return e.each(r.categories,function(r,o){e.each(o.practices,function(e,r){var o=t-1,s=a.roadmap[r.practice][o];if(1>s)return!0;if(t>1){var c=a.roadmap[r.practice][o-1];if(s===c)return!0}var p=n.getImgURL(r.practice+s+".png"),h=r.baseHref+"_-_"+s;i=i.concat('<div style="overflow: hidden; margin:2px;"><div style="float: left;height: 40px;"><span style="display: inline-block;height: 100%; vertical-align: middle;"></span><a href="'+h+'" target="_blank" style="vertical-align: middle;"><img src="'+p+'" alt="'+r.name+'" width="75" style="vertical-align: middle;"/></a></div><div style="float: left; padding-left: 10px"><small>'+r.activities[s-1].join("<br/>")+"</small></div></div>")})}),i.join("")},l=function(){var t=2*a.phaseCount*a.phaseWidth,r=a.practiceLabelWidth+a.rulerLeftWidth+t+a.rulerRightWidth,i=f(),n=e('<canvas class="roadmapCanvas" width="{0}" height="{1}" style="image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: optimize-contrast; -ms-interpolation-mode: nearest-neighbor;"/>'.format(r,i));return e(a.element).append(n),n},f=function(){return a.phasesHeaderTotalHeight=a.phaseCount*(a.phaseHeaderHeight+a.phaseHeaderPadding),a.activitiesHeight=4*a.levelHeight*12,a.effortHeight=4*a.levelHeight/3,a.phasesHeaderTotalHeight+a.activitiesHeight+a.effortHeight},d=function(){for(var e=0;e<a.phaseCount;e++)u(e)},u=function(e){var t=a.ctx;g(t,e);var r=a.practiceLabelWidth,i=e*(a.phaseHeaderHeight+a.phaseHeaderPadding),n=e*a.phaseWidth*2+a.rulerLeftWidth,o=a.phaseHeaderHeight;t.beginPath(),t.rect(r,i,n,o),t.lineWidth=0,t.fillStyle=a.colors.barLight,t.fill(),t.closePath(),t.beginPath(),t.rect(r+n,i,a.phaseWidth,o),t.lineWidth=0,t.fillStyle=a.colors.barDark,t.fill(),t.closePath(),m(t,e),t.beginPath(),t.fillStyle=a.colors.barRegular,t.lineWidth=0;for(var s=0;e+1>s;s++)t.rect(r+a.rulerLeftWidth+2*s*a.phaseWidth,i+o,a.phaseWidth,a.phaseHeaderPadding);t.fill(),t.closePath()},g=function(e,t){e.font="{0} {1}px {2}".format(a.fonts.phases.style,a.fonts.phases.size,a.fonts.phases.font),e.fillStyle=a.colors.header,e.textAlign="right",e.textBaseline="top",e.fillText("Phase {0}".format(t+1),a.practiceWidth,t*(a.phaseHeaderHeight+a.phaseHeaderPadding)+(a.phaseHeaderHeight-a.fonts.phases.size)/2)},m=function(e,t){var r=a.practiceLabelWidth+a.rulerLeftWidth+t*a.phaseWidth*2+a.phaseWidth/2,i=t*(a.phaseHeaderHeight+a.phaseHeaderPadding);e.beginPath(),e.moveTo(r-5,i+3),e.lineTo(r+5,i+3),e.lineTo(r+5,i+5),e.lineTo(r+8,i+5),e.lineTo(r,i+10),e.lineTo(r-8,i+5),e.lineTo(r-5,i+5),e.fillStyle=a.colors.arrow,e.closePath(),e.fill()},w=function(){var e=a.ctx,t=a.practiceLabelWidth;e.beginPath();for(var r=0;r<a.phaseCount;r++)e.rect(t+a.rulerLeftWidth+2*r*a.phaseWidth,a.phasesHeaderTotalHeight,a.phaseWidth,a.activitiesHeight);e.fillStyle=a.colors.barRegular,e.closePath(),e.fill()},v=function(){var e=a.ctx;e.setLineDash||(e.setLineDash=function(){}),e.beginPath(),e.setLineDash([5,5]);var t=a.practiceLabelWidth+a.rulerLeftWidth+2*a.currentPhase*a.phaseWidth-a.phaseWidth;e.moveTo(t,0),e.lineTo(t,a.phasesHeaderTotalHeight+a.activitiesHeight),e.stroke(),e.closePath(),e.setLineDash([])},y=function(){var e=a.ctx;r.categories.forEach(function(t,r){t.practices.forEach(function(i,n){e.font="{0} {1}px {2}".format(a.fonts.practices.style,a.fonts.practices.size,a.fonts.practices.font),e.fillStyle=a.colors.header,e.textAlign="right",e.textBaseline="top",e.fillText(i.name,a.practiceWidth,a.phasesHeaderTotalHeight+4*r*3*a.levelHeight+4*(n+1)*a.levelHeight-2*a.levelHeight),_(a.phasesHeaderTotalHeight+4*(3*r+n)*a.levelHeight);var o="undefined"!=typeof a.currentPhase,s=o?t.color:t.color_dark;if(b(a.roadmap[i.practice],s,a.phasesHeaderTotalHeight+4*(3*r+n)*a.levelHeight+3*a.levelHeight),o){var c=A(a.currentLevels[i.practice],a.currentPhase,a.roadmap[i.practice]);b(c,t.color_dark,a.phasesHeaderTotalHeight+4*(3*r+n)*a.levelHeight+3*a.levelHeight)}})})},A=function(e,t,r){var i=[];return r.forEach(function(r,a){t>a+1?e>r?i.push(r):i.push(e):t==a+1?i.push(e):i.push(0)}),i},b=function(e,t,r){var i=a.practiceLabelWidth+a.rulerLeftWidth,n=r,o=i,s=n,c=a.ctx;c.beginPath(),c.globalAlpha=a.alpha,c.fillStyle=t,e.forEach(function(e,t){t>=a.phaseCount||(0==e?o>i?(c.lineTo(o-a.phaseWidth,s),c.lineTo(o-a.phaseWidth,n),o+=2*a.phaseWidth,c.lineTo(o,n),s=n):(i+=2*a.phaseWidth,o=i,s=n,c.moveTo(o,s)):(o+=a.phaseWidth,s=n-e*a.levelHeight,c.lineTo(o,s),o+=a.phaseWidth,c.lineTo(o,s)))}),c.lineTo(o,n),c.lineTo(i,n),c.closePath(),c.fill(),c.globalAlpha=1},_=function(e){e=e;var t=a.ctx,r=a.practiceLabelWidth;t.beginPath(),t.lineWidth=1,t.strokeStyle=a.colors.ruler,t.moveTo(r+a.rulerLeftWidth/2,e),t.lineTo(r,e),t.lineTo(r,e+a.levelHeight),t.lineTo(r+a.rulerLeftWidth/2,e+a.levelHeight),t.moveTo(r,e+a.levelHeight),t.lineTo(r,e+2*a.levelHeight),t.lineTo(r+a.rulerLeftWidth/2,e+2*a.levelHeight),t.moveTo(r,e+2*a.levelHeight),t.lineTo(r,e+3*a.levelHeight),t.lineTo(r+a.rulerLeftWidth+2*a.phaseCount*a.phaseWidth+a.rulerRightWidth,e+3*a.levelHeight),t.stroke(),t.closePath()},S=function(){var e=Array.apply(null,new Array(a.phaseCount)).map(Number.prototype.valueOf,0);for(var t in a.roadmap)if(a.roadmap.hasOwnProperty(t))for(var r=0;r<a.phaseCount;r++)e[r]+=r>0?a.roadmap[t][r]-a.roadmap[t][r-1]:a.roadmap[t][r];var i=a.ctx;i.font="{0} {1}px {2}".format(a.fonts.efforts.style,a.fonts.efforts.size,a.fonts.efforts.font),i.fillStyle=a.colors.header,i.textAlign="right",i.textBaseline="top",i.fillText("Efforts",a.practiceWidth,a.phasesHeaderTotalHeight+a.activitiesHeight+a.effortsPaddingTop),i.textAlign="center",e.forEach(function(e,t){var r=a.practiceLabelWidth+a.rulerLeftWidth+2*t*a.phaseWidth+a.phaseWidth/2;i.fillText(e,r,a.phasesHeaderTotalHeight+a.activitiesHeight+a.effortsPaddingTop)})};this.initialize(i)},n});