diff --git a/src/main/java/com/redhat/exhort/integration/backend/sbom/cyclonedx/CycloneDxParser.java b/src/main/java/com/redhat/exhort/integration/backend/sbom/cyclonedx/CycloneDxParser.java index c685685d..3afe549f 100644 --- a/src/main/java/com/redhat/exhort/integration/backend/sbom/cyclonedx/CycloneDxParser.java +++ b/src/main/java/com/redhat/exhort/integration/backend/sbom/cyclonedx/CycloneDxParser.java @@ -64,7 +64,7 @@ protected DependencyTree buildTree(InputStream input) { if (bom.getComponents() != null) { componentPurls.putAll( bom.getComponents().stream() - .filter(c -> c.getBomRef() != null) + .filter(c -> c.getBomRef() != null && c.getPurl() != null) .collect(Collectors.toMap(Component::getBomRef, c -> new PackageRef(c.getPurl())))); } diff --git a/src/main/java/com/redhat/exhort/integration/report/ReportTemplate.java b/src/main/java/com/redhat/exhort/integration/report/ReportTemplate.java index 76da78c2..dc10006a 100644 --- a/src/main/java/com/redhat/exhort/integration/report/ReportTemplate.java +++ b/src/main/java/com/redhat/exhort/integration/report/ReportTemplate.java @@ -32,10 +32,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.redhat.exhort.integration.Constants; +import com.redhat.exhort.integration.trustedcontent.ubi.UBIRecommendation; import io.quarkus.runtime.annotations.RegisterForReflection; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; @RegisterForReflection @ApplicationScoped @@ -56,6 +58,8 @@ public class ReportTemplate { @ConfigProperty(name = "report.cve.issue.regex") String cveIssuePathRegex; + @Inject UBIRecommendation ubiRecommendation; + public Map setVariables( @Body Object report, @ExchangeProperty(Constants.PROVIDER_PRIVATE_DATA_PROPERTY) List providerPrivateData) @@ -69,6 +73,7 @@ public Map setVariables( params.put("providerPrivateData", providerPrivateData); params.put("snykSignup", snykSignup); params.put("cveIssueTemplate", cveIssuePathRegex); + params.put("imageMapping", getImageMapping()); ObjectWriter objectWriter = new ObjectMapper().writer(); String appData = objectWriter.writeValueAsString(params); @@ -77,6 +82,22 @@ public Map setVariables( return params; } + private String getImageMapping() throws JsonProcessingException { + List> urlMapping = + ubiRecommendation.purl().keySet().stream() + .map( + ubi -> { + Map urls = new HashMap<>(2); + urls.put("purl", ubiRecommendation.purl().get(ubi)); + urls.put("catalogUrl", ubiRecommendation.catalogurl().get(ubi)); + return urls; + }) + .toList(); + + ObjectWriter objectWriter = new ObjectMapper().writer(); + return objectWriter.writeValueAsString(urlMapping); + } + @RegisterForReflection public static record IssueLinkFormatter(String issuePathRegex) { diff --git a/src/main/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandler.java b/src/main/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandler.java index 7c68458c..878220fa 100644 --- a/src/main/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandler.java +++ b/src/main/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandler.java @@ -29,13 +29,13 @@ import org.apache.camel.Body; import org.apache.camel.Exchange; import org.apache.camel.ExchangeProperty; -import org.eclipse.microprofile.config.inject.ConfigProperty; import com.fasterxml.jackson.databind.ObjectMapper; import com.redhat.exhort.api.PackageRef; import com.redhat.exhort.api.v4.ProviderStatus; import com.redhat.exhort.integration.Constants; import com.redhat.exhort.integration.providers.ProviderResponseHandler; +import com.redhat.exhort.integration.trustedcontent.ubi.UBIRecommendation; import com.redhat.exhort.model.DependencyTree; import com.redhat.exhort.model.ProviderResponse; import com.redhat.exhort.model.trustedcontent.IndexedRecommendation; @@ -60,8 +60,7 @@ public class TcResponseHandler extends ProviderResponseHandler { @Inject ObjectMapper mapper; - @ConfigProperty(name = "trustedcontent.recommended.ubi") - String recommendedUBIPurl; + @Inject UBIRecommendation ubiRecommendation; public TrustedContentResponse parseResponse( @Body byte[] tcResponse, @ExchangeProperty(Constants.SBOM_ID_PROPERTY) String sbomId) @@ -116,14 +115,17 @@ private Map getUBIRecommendation(String sbomI return Collections.emptyMap(); } - PackageRef pkgRef = new PackageRef(sbomId); + var pkgRef = new PackageRef(sbomId); if (!Constants.OCI_PURL_TYPE.equals(pkgRef.purl().getType())) { return Collections.emptyMap(); } - IndexedRecommendation recommendation = - new IndexedRecommendation(new PackageRef(recommendedUBIPurl), null); - return Collections.singletonMap(pkgRef, recommendation); + var recommendedUBIPurl = ubiRecommendation.mapping().get(pkgRef.name()); + if (recommendedUBIPurl != null) { + var recommendation = new IndexedRecommendation(new PackageRef(recommendedUBIPurl), null); + return Collections.singletonMap(pkgRef, recommendation); + } + return Collections.emptyMap(); } @Override diff --git a/src/main/java/com/redhat/exhort/integration/trustedcontent/ubi/UBIRecommendation.java b/src/main/java/com/redhat/exhort/integration/trustedcontent/ubi/UBIRecommendation.java new file mode 100644 index 00000000..cb3a98a1 --- /dev/null +++ b/src/main/java/com/redhat/exhort/integration/trustedcontent/ubi/UBIRecommendation.java @@ -0,0 +1,32 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * 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. + */ + +package com.redhat.exhort.integration.trustedcontent.ubi; + +import java.util.Map; + +import io.smallrye.config.ConfigMapping; + +@ConfigMapping(prefix = "trustedcontent.recommendation.ubi") +public interface UBIRecommendation { + Map mapping(); + + Map purl(); + + Map catalogurl(); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 58f88cb6..88c316e6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -35,4 +35,13 @@ quarkus.rest-client.segment-api.url=https://api.segment.io/ quarkus.management.enabled=true quarkus.http.limits.max-body-size=4G -trustedcontent.recommended.ubi=pkg:oci/registry.access.redhat.com/ubi9/ubi@latest +trustedcontent.recommendation.ubi.purl.ubi9=pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64 +trustedcontent.recommendation.ubi.catalogurl.ubi9=https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5f +trustedcontent.recommendation.ubi.purl.ubi9-minimal=pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64 +trustedcontent.recommendation.ubi.catalogurl.ubi9-minimal=https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26 +trustedcontent.recommendation.ubi.mapping.alpine=${trustedcontent.recommendation.ubi.purl.ubi9-minimal} +trustedcontent.recommendation.ubi.mapping.ubuntu=${trustedcontent.recommendation.ubi.purl.ubi9} +trustedcontent.recommendation.ubi.mapping.centos=${trustedcontent.recommendation.ubi.purl.ubi9} +trustedcontent.recommendation.ubi.mapping.debian=${trustedcontent.recommendation.ubi.purl.ubi9} +trustedcontent.recommendation.ubi.mapping.fedora=${trustedcontent.recommendation.ubi.purl.ubi9} +trustedcontent.recommendation.ubi.mapping.amazonlinux=${trustedcontent.recommendation.ubi.purl.ubi9} \ No newline at end of file diff --git a/src/main/resources/freemarker/templates/generated/main.js b/src/main/resources/freemarker/templates/generated/main.js index a6742002..004da92e 100644 --- a/src/main/resources/freemarker/templates/generated/main.js +++ b/src/main/resources/freemarker/templates/generated/main.js @@ -1 +1 @@ -!function(){"use strict";var e={1958:function(e,n,r){var i=r(8963),t=r(3609),a=(r(3218),r(9559)),s=r(9714),c=r(4187),o=r(5671),l=r(3144),d="maven",u="https://pkg.go.dev/",h="https://www.npmjs.com/package/",g="https://pypi.org/project/",v="__ISSUE_ID__",x="pkg:",p=["oss-index"],j="https://maven.repository.redhat.com/ga/",f=function(e){return"oss-index"===e?"https://ossindex.sonatype.org/user/register":""},m=function(e,n){var r=T.fromString(e),i=function(e){var n="";return e.namespace&&(n=e.type===d?"".concat(e.namespace,":"):"".concat(e.namespace,"/")),n+"".concat(e.name)}(r);return n?i+"@".concat(r.version):i},y=function(e){var n=T.fromString(e),r=j;if(n.namespace){var i,t=null===(i=n.namespace)||void 0===i?void 0:i.replace(/\./g,"/");return"".concat(j).concat(t,"/").concat(n.name,"/").concat(n.version)}return r},I=function(e){var n=T.fromString(e);switch(n.type){case d:var r=n.version;if(null!==r&&void 0!==r&&r.includes("redhat")){var i,t=null===(i=n.namespace)||void 0===i?void 0:i.replace(/\./g,"/");return"".concat(j).concat(t,"/").concat(n.name,"/").concat(n.version)}return"".concat("https://central.sonatype.com/artifact/").concat(n.namespace,"/").concat(n.name,"/").concat(n.version);case"golang":var a=n.version;return null!==a&&void 0!==a&&a.match(/v\d\.\d.\d-\d{14}-\w{12}/)?"".concat(u).concat(n.namespace,"/").concat(n.name):"".concat(u).concat(n.namespace,"/").concat(n.name,"@").concat(n.version);case"npm":return n.namespace?"".concat(h).concat(n.namespace,"/").concat(n.name,"/v/").concat(n.version):"".concat(h).concat(n.name,"/v/").concat(n.version);case"pypi":return n.namespace?"".concat(g).concat(n.namespace,"/").concat(n.name,"/").concat(n.version):"".concat(g).concat(n.name,"/").concat(n.version);default:return n.toString()}},b=function(e){var n=T.fromString(e).version;return n||""},C=function(e,n,r){switch(e){case"snyk":return r.snykIssueTemplate.replace(v,n);case"oss-index":return r.ossIssueTemplate.replace(v,n);case"osv-nvd":return r.nvdIssueTemplate.replace(v,n)}},M=function(e){return e.toLowerCase().replace(/./,(function(e){return e.toUpperCase()}))},T=function(){function e(n,r,i,t){(0,o.Z)(this,e),this.type=void 0,this.namespace=void 0,this.name=void 0,this.version=void 0,this.type=n,this.namespace=r,this.name=i,this.version=t}return(0,l.Z)(e,[{key:"toString",value:function(){var e=this.name;return this.version&&(e+="@".concat(this.version)),this.namespace?"".concat(x).concat(this.type,"/").concat(this.namespace,"/").concat(e):"".concat(x).concat(this.type,"/").concat(e)}}],[{key:"fromString",value:function(n){var r=n.replace(x,""),i=r.indexOf("?");-1!==i&&(r=r.substring(0,i));var t,a,s=r.substring(0,r.indexOf("/")),c=r.split("/");c.length>2&&(t=c.slice(1,c.length-1).join("/")),-1!==r.indexOf("@")&&(a=r.substring(r.indexOf("@")+1));var o=c[c.length-1];return a&&(o=o.substring(0,o.indexOf("@"))),new e(s,t,o,a)}}]),e}();function A(e){var n=[];return Object.keys(e.providers).forEach((function(r){var i=e.providers[r].sources;void 0!==i&&Object.keys(i).length>0?Object.keys(i).forEach((function(e){n.push({provider:r,source:e,report:i[e]})})):"trusted-content"!==r&&n.push({provider:r,source:r,report:{}})})),n.sort((function(e,n){return 0===Object.keys(e.report).length&&0===Object.keys(n.report).length?""===f(e.provider)?""===f(n.provider)?0:-1:1:Object.keys(n.report).length-Object.keys(e.report).length}))}function S(e){return void 0===e?"unknown":e.provider!==e.source?"$item.provider/$item.source":e.provider}function D(e){var n;return!(!e.remediation||!(e.remediation.fixedIn||null!==(n=e.remediation)&&void 0!==n&&n.trustedContent))}function w(e){var n=[];return e.map((function(e){return{dependencyRef:e.ref,vulnerabilities:e.issues||[]}})).forEach((function(e){var r;null===(r=e.vulnerabilities)||void 0===r||r.forEach((function(r){r.cves&&r.cves.length>0?r.cves.forEach((function(i){n.push({id:i,dependencyRef:e.dependencyRef,vulnerability:r})})):n.push({id:r.id,dependencyRef:e.dependencyRef,vulnerability:r})}))})),n.sort((function(e,n){return n.vulnerability.cvssScore-e.vulnerability.cvssScore}))}var N=r(3442),P=r(3324),k=r(6363),O=r(8437),Z=r(6798),L=r(2996),z=r(3020),E=r(4223),B=r(1858),F=r(493),R=r(7065),G=r(7941),H=r(2355),U=r(8485),Y=r(9090),V=r(2570),J=r(7806),_=r(5859),W=["#800000","#FF0000","#FFA500","#5BA352"],Q=function(e){var n,r,i,t,a,s=e.summary,c=null!==(n=null===s||void 0===s?void 0:s.critical)&&void 0!==n?n:0,o=null!==(r=null===s||void 0===s?void 0:s.high)&&void 0!==r?r:0,l=null!==(i=null===s||void 0===s?void 0:s.medium)&&void 0!==i?i:0,d=null!==(t=null===s||void 0===s?void 0:s.low)&&void 0!==t?t:0,u=null!==(a=null===s||void 0===s?void 0:s.total)&&void 0!==a?a:0,h=c+o+l+d>0,g=h?W:["#D5F5E3"],v=[{name:"Critical: ".concat(c),symbol:{type:"square",fill:W[0]}},{name:"High: ".concat(o),symbol:{type:"square",fill:W[1]}},{name:"Medium: ".concat(l),symbol:{type:"square",fill:W[2]}},{name:"Low: ".concat(d),symbol:{type:"square",fill:W[3]}}];return(0,_.jsx)("div",{children:(0,_.jsx)(E.e,{style:{paddingBottom:"inherit",padding:"0"},children:(0,_.jsx)(V.b,{children:(0,_.jsx)("div",{style:{height:"230px",width:"350px"},children:(0,_.jsx)(J.H,{constrainToVisibleArea:!0,data:h?[{x:"Critical",y:c},{x:"High",y:o},{x:"Medium",y:l},{x:"Low",y:d}]:[{x:"Empty",y:1e-10}],labels:function(e){var n=e.datum;return"".concat(n.x,": ").concat(n.y)},legendData:v,legendOrientation:"vertical",legendPosition:"right",padding:{left:20,right:140},subTitle:"Unique vulnerabilities",title:"".concat(u),width:350,colorScale:g})})})})})},K=r(6155),q="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTJweCIgaGVpZ2h0PSIxM3B4IiB2aWV3Qm94PSIwIDAgMTIgMTMiIGlkPSJTZWN1cml0eUNoZWNrSWNvbiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZyBpZD0iTXVsdGktdmVuZG9yIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iT3ZlcnZpZXctQ29weSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEyMDcsIC05OTMpIiBmaWxsPSIjM0U4NjM1Ij4KICAgICAgICAgICAgPGcgaWQ9IkRldGFpbHMtb2YtZGVwZW5kZW5jeS1jb20uZ2l0aHViIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0MjcsIDgxOSkiPgogICAgICAgICAgICAgICAgPGcgaWQ9IkRlcGVuZGVuY3ktMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMTQ0KSI+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc4MC4xNzI4LCAyNCkiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMy4yKSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iSWNvbnMvMi4tU2l6ZS1zbS9BY3Rpb25zL2NoZWNrIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAyLjgpIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTAuNTU2NTc4OSwwIEMxMC43OTA2MjQ5LDAgMTAuOTc5MzMyMiwwLjE4MTU0Mjk2OSAxMC45NzkzMzIyLDAuNDA2MjUgTDEwLjk3OTMzMjIsNS43NDA4MjAzMSBDMTAuOTc5MzMyMiw5Ljc1IDYuMjQwODE5MDcsMTMgNS40OTU3OTI5NiwxMyBDNC43NTA3NjY4NCwxMyAwLDkuNzUgMCw1LjczOTU1MDc4IEwwLDAuNDA2MjUgQzAsMC4xODE1NDI5NjkgMC4xODg3MDcyNzIsMCAwLjQyMjc1MzMwNCwwIFogTTguNTQyNzc4ODMsMy4xMTc4MjY2NyBMNC43OTEyOTYxLDYuODkwODczNTMgTDMuMDM5ODEzMzgsNS4xMjkzMjQ0IEMyLjg4MzYwOSw0Ljk3MjIwNjgzIDIuNjMwMzI4MTIsNC45NzIyMDY4MyAyLjQ3NDEyMzc1LDUuMTI5MzI0NCBMMS45MDg0NDkzOCw1LjY5ODI2NTU2IEMxLjc1MjI0NTAxLDUuODU1MzgzMTIgMS43NTIyNDUwMSw2LjExMDEwNDQ5IDEuOTA4NDQ5MzgsNi4yNjcyMDY3MSBMNC41MDg0NTc5Nyw4Ljg4MjE1OTkxIEM0LjY2NDY0NzA4LDkuMDM5Mjc3NDcgNC45MTc5MTI3LDkuMDM5Mjc3NDcgNS4wNzQxMzIzMyw4Ljg4MjE3NTI1IEw5LjY3NDE0MjgyLDQuMjU1NzA4OTggQzkuODMwMzQ3Miw0LjA5ODU5MTQxIDkuODMwMzQ3MiwzLjg0Mzg3MDA0IDkuNjc0MTQyODIsMy42ODY3Njc4MiBMOS4xMDg0Njg0NiwzLjExNzgyNjY3IEM4Ljk1MjI2NDA4LDIuOTYwNzI0NDQgOC42OTg5ODMyLDIuOTYwNzI0NDQgOC41NDI3Nzg4MywzLjExNzgyNjY3IFoiIGlkPSJDb21iaW5lZC1TaGFwZSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=",X=function(e){var n=e.report;return(0,_.jsxs)(s.r,{hasGutter:!0,children:[(0,_.jsxs)(N.D,{headingLevel:"h3",size:N.H["2xl"],style:{paddingLeft:"15px"},children:[(0,_.jsx)(P.J,{isInline:!0,status:"info",children:(0,_.jsx)(Y.ZP,{style:{fill:"#f0ab00"}})}),"\xa0Red Hat Overview of security Issues"]}),(0,_.jsx)(k.i,{}),(0,_.jsx)(c.P,{children:(0,_.jsxs)(O.Z,{isFlat:!0,isFullHeight:!0,children:[(0,_.jsx)(Z.O,{children:(0,_.jsx)(L.l,{children:(0,_.jsx)(z.M,{style:{fontSize:"large"},children:"Vendor Issues"})})}),(0,_.jsxs)(E.e,{children:[(0,_.jsx)(B.g,{children:(0,_.jsx)(F.b,{children:(0,_.jsx)(z.M,{children:"Below is a list of dependencies affected with CVE."})})}),(0,_.jsx)(R.o,{isAutoFit:!0,style:{paddingTop:"10px"},children:A(n).map((function(e,n){return(0,_.jsxs)(B.g,{style:{display:"flex",flexDirection:"column",alignItems:"center"},children:[(0,_.jsx)(_.Fragment,{children:(0,_.jsx)(z.M,{style:{fontSize:"large"},children:S(e)})}),(0,_.jsx)(F.b,{children:(0,_.jsx)(Q,{summary:e.report.summary})})]},n)}))})]}),(0,_.jsx)(k.i,{})]})}),(0,_.jsxs)(c.P,{md:6,children:[(0,_.jsx)(O.Z,{isFlat:!0,children:(0,_.jsxs)(B.g,{children:[(0,_.jsx)(L.l,{component:"h4",children:(0,_.jsxs)(z.M,{style:{fontSize:"large"},children:[(0,_.jsx)(P.J,{isInline:!0,status:"info",children:(0,_.jsx)(K.ZP,{style:{fill:"#cc0000"}})}),"\xa0 Red Hat Remediations"]})}),(0,_.jsx)(E.e,{children:(0,_.jsx)(F.b,{children:(0,_.jsx)(G.aV,{isPlain:!0,children:A(n).map((function(e,n){return Object.keys(e.report).length>0?(0,_.jsxs)(H.H,{children:[(0,_.jsx)(P.J,{isInline:!0,status:"success",children:(0,_.jsx)("img",{src:q,alt:"Security Check Icon"})}),"\xa0",e.report.summary.remediations," remediations are available from Red Hat for ",e.provider]}):(0,_.jsxs)(H.H,{children:[(0,_.jsx)(P.J,{isInline:!0,status:"success",children:(0,_.jsx)("img",{src:q,alt:"Security Check Icon"})}),"\xa0 There are no available Red Hat remediations for your SBOM at this time for ",e.provider]})}))})})})]})}),"\xa0"]}),(0,_.jsxs)(c.P,{md:6,children:[(0,_.jsx)(O.Z,{isFlat:!0,children:(0,_.jsxs)(B.g,{children:[(0,_.jsx)(L.l,{component:"h4",children:(0,_.jsx)(z.M,{style:{fontSize:"large"},children:"Join to explore Red Hat TPA"})}),(0,_.jsx)(E.e,{children:(0,_.jsx)(F.b,{children:(0,_.jsxs)(G.aV,{isPlain:!0,children:[(0,_.jsx)(H.H,{children:"Check out our new Trusted Profile Analyzer to get visibility and insight into your software risk profile, for instance by exploring vulnerabilites or analyzing SBOMs."}),(0,_.jsx)(H.H,{children:(0,_.jsx)("a",{href:"https://console.redhat.com/application-services/trusted-content",target:"_blank",rel:"noopener noreferrer",children:(0,_.jsx)(U.zx,{variant:"primary",size:"sm",children:"Take me there"})})})]})})})]})}),"\xa0"]})]})},$=r(2933),ee=function(e){var n=e.report,r=Object.keys(n.providers).map((function(e){return n.providers[e].status})).filter((function(e){return!e.ok&&!(!(n=e).ok&&401===n.code&&"Unauthenticated"===n.message&&p.includes(n.name));var n}));return(0,_.jsx)(_.Fragment,{children:r.map((function(e,n){return(0,_.jsx)($.b,{variant:e.code>=500?$.U.danger:e.code>=400?$.U.warning:void 0,title:"".concat(M(e.name),": ").concat(e.message)},n)}))})},ne=r(885),re=r(6081),ie=r(4817),te=r(6467),ae=r(1413),se=r(9809),ce=r(382),oe=r(8521),le=r(2e3),de=r(6989),ue=r(2401),he=r(6496),ge=r(8987),ve=r(9623),xe=r(9626),pe=r(205),je=r(3610),fe=r(7990),me=r(5091),ye=r(6056),Ie=r(1915),be=r(1178),Ce=r(7102),Me=r(2982),Te=r(1917),Ae=function(e){return e[e.SET_PAGE=0]="SET_PAGE",e[e.SET_SORT_BY=1]="SET_SORT_BY",e}(Ae||{}),Se={changed:!1,currentPage:{page:1,perPage:10},sortBy:void 0},De=function(e,n){switch(n.type){case Ae.SET_PAGE:var r=n.payload;return(0,ae.Z)((0,ae.Z)({},e),{},{changed:!0,currentPage:{page:r.page,perPage:r.perPage}});case Ae.SET_SORT_BY:var i=n.payload;return(0,ae.Z)((0,ae.Z)({},e),{},{changed:!0,sortBy:{index:i.index,direction:i.direction}});default:return e}},we=r(9960),Ne=r(500),Pe=function(e){var n,r=e.count,i=e.params,t=e.isTop,a=(e.isCompact,e.perPageOptions),s=e.onChange,c=function(){return i.perPage||10};return(0,_.jsx)(we.t,{itemCount:r,page:i.page||1,perPage:c(),onPageInput:function(e,n){s({page:n,perPage:c()})},onSetPage:function(e,n){s({page:n,perPage:c()})},onPerPageSelect:function(e,n){s({page:1,perPage:n})},widgetId:"pagination-options-menu",variant:t?we.a.top:we.a.bottom,perPageOptions:(n=a||[10,20,50,100],n.map((function(e){return{title:String(e),value:e}}))),toggleTemplate:function(e){return(0,_.jsx)(Ne.v,(0,ae.Z)({},e))}})},ke=function(e){var n=e.name,r=e.showVersion,i=void 0!==r&&r;return(0,_.jsx)(_.Fragment,{children:(0,_.jsx)("a",{href:I(n),target:"_blank",rel:"noreferrer",children:m(n,i)})})},Oe=r(164),Ze=r(5020),Le=r(8649),ze=r(7514),Ee=function(e){var n=e.numRenderedColumns,r=e.isLoading,i=void 0!==r&&r,t=e.isError,a=void 0!==t&&t,s=e.isNoData,c=void 0!==s&&s,o=e.errorEmptyState,l=void 0===o?null:o,d=e.noDataEmptyState,u=void 0===d?null:d,h=e.children,g=(0,_.jsxs)(se.u,{variant:se.I.sm,children:[(0,_.jsx)(oe.k,{icon:Le.ZP,color:ze.a.value}),(0,_.jsx)(N.D,{headingLevel:"h2",size:"lg",children:"Unable to connect"}),(0,_.jsx)(le.B,{children:"There was an error retrieving data. Check your connection and try again."})]}),v=(0,_.jsxs)(se.u,{variant:se.I.sm,children:[(0,_.jsx)(oe.k,{icon:Ze.ZP}),(0,_.jsx)(N.D,{headingLevel:"h2",size:"lg",children:"No data available"}),(0,_.jsx)(le.B,{children:"No data available to be shown here."})]});return(0,_.jsx)(_.Fragment,{children:i?(0,_.jsx)(ye.p,{children:(0,_.jsx)(fe.Tr,{children:(0,_.jsx)(Ie.Td,{colSpan:n,children:(0,_.jsx)(V.b,{children:(0,_.jsx)(Oe.$,{size:"xl"})})})})}):a?(0,_.jsx)(ye.p,{"aria-label":"Table error",children:(0,_.jsx)(fe.Tr,{children:(0,_.jsx)(Ie.Td,{colSpan:n,children:(0,_.jsx)(V.b,{children:l||g})})})}):c?(0,_.jsx)(ye.p,{"aria-label":"Table no data",children:(0,_.jsx)(fe.Tr,{children:(0,_.jsx)(Ie.Td,{colSpan:n,children:(0,_.jsx)(V.b,{children:u||v})})})}):h})},Be=function(e){var n=e.packageName;e.cves;return(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(P.J,{isInline:!0,status:"success",children:(0,_.jsx)("img",{src:q,alt:"Security Check Icon"})}),"\xa0",(0,_.jsx)("a",{href:y(n),target:"_blank",rel:"noreferrer",children:b(n)})]})},Fe=function(){var e=dn().providerPrivateData;return{hideIssue:function(n,r){return!(!e||-1===e.indexOf(n))&&r}}},Re=function(e){var n,r,i,t=e.sourceName,a=e.vulnerability,s=Fe(),c=dn();return(0,_.jsx)(_.Fragment,{children:s.hideIssue(t,a.unique)?(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)("a",{href:c.snykSignup,target:"_blank",rel:"noreferrer",children:"Sign up for a Snyk account"})," ","to learn about the vulnerabilities found"]}):"snyk"!==t||null!==(null===(n=a.remediation)||void 0===n?void 0:n.fixedIn)&&0!==(null===(r=a.remediation)||void 0===r||null===(i=r.fixedIn)||void 0===i?void 0:i.length)?(0,_.jsx)("a",{href:C(t,a.id,c),target:"_blank",rel:"noreferrer",children:a.id}):(0,_.jsx)("p",{})})},Ge=r(736),He=r(5351),Ue=r(975),Ye=r(6647),Ve=function(e){var n,r=e.vulnerability;switch(r.severity){case"CRITICAL":case"HIGH":n=Ge.n9.danger;break;default:n=Ge.n9.warning}return(0,_.jsx)(_.Fragment,{children:(0,_.jsx)(He.P,{hasGutter:!0,children:(0,_.jsx)(Ue.J,{isFilled:!0,children:(0,_.jsx)(Ye.E,{title:"".concat(r.cvssScore,"/10"),"aria-label":"cvss-score",value:r.cvssScore,min:0,max:10,size:Ye.L.sm,variant:n,measureLocation:Ge.nK.none})})})})},Je=r(313),_e=function(e){var n,r=e.vulnerability;switch(r.severity){case"CRITICAL":n="#800000";break;case"HIGH":n="#FF0000";break;case"MEDIUM":n="#FFA500";break;case"LOW":n="#5BA352";break;default:n="grey"}return(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(P.J,{isInline:!0,children:(0,_.jsx)(Je.ZP,{style:{fill:n,height:"13px"}})}),"\xa0",M(r.severity)]})},We=function(e){var n,r,i=e.id,t=dn();return(0,_.jsx)("a",{href:(n=i,r=t,r.cveIssueTemplate.replace(v,n)),target:"_blank",rel:"noreferrer",children:i})},Qe=r(4150),Ke=function(e){var n=e.title,r=i.useState(!1),t=(0,ne.Z)(r,2),a=t[0],s=t[1];return(0,_.jsx)(Qe.L,{variant:Qe.S.truncate,toggleText:a?"Show less":"Show more",onToggle:function(e,n){s(n)},isExpanded:a,children:n})},qe=function(e){var n,r,i,t,a,s=e.item,c=e.providerName,o=e.rowIndex;a=s.vulnerability.cves&&s.vulnerability.cves.length>0?s.vulnerability.cves:[s.vulnerability.id];var l=Fe().hideIssue(c,s.vulnerability.unique),d=dn();return(0,_.jsxs)(fe.Tr,{children:[l?(0,_.jsx)(_.Fragment,{children:(0,_.jsx)(Ie.Td,{colSpan:3,children:(0,_.jsx)("a",{href:d.snykSignup,target:"_blank",rel:"noreferrer",children:"Sign up for a Snyk account to learn about the vulnerabilities found"})})}):(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(Ie.Td,{children:a.map((function(e,n){return(0,_.jsx)("p",{children:(0,_.jsx)(We,{id:e})},n)}))}),(0,_.jsx)(Ie.Td,{children:(0,_.jsx)(Ke,{title:s.vulnerability.title})}),(0,_.jsx)(Ie.Td,{noPadding:!0,children:(0,_.jsx)(_e,{vulnerability:s.vulnerability})})]}),(0,_.jsx)(Ie.Td,{children:(0,_.jsx)(Ve,{vulnerability:s.vulnerability})}),(0,_.jsx)(Ie.Td,{children:(0,_.jsx)(ke,{name:s.dependencyRef,showVersion:!0})}),(0,_.jsx)(Ie.Td,{children:null!==(n=s.vulnerability.remediation)&&void 0!==n&&n.trustedContent?(0,_.jsx)(Be,{cves:s.vulnerability.cves||[],packageName:null===(r=s.vulnerability.remediation)||void 0===r||null===(i=r.trustedContent)||void 0===i?void 0:i.ref},o):null!==(t=s.vulnerability.remediation)&&void 0!==t&&t.fixedIn?(0,_.jsx)(Re,{sourceName:c,vulnerability:s.vulnerability}):D(s.vulnerability)?null:(0,_.jsx)("span",{})})]},o)},Xe=function(e){var n=e.providerName,r=e.transitiveDependencies;return(0,_.jsx)(O.Z,{style:{backgroundColor:"var(--pf-v5-global--BackgroundColor--100)"},children:(0,_.jsxs)(xe.i,{variant:pe.B.compact,children:[(0,_.jsx)(je.h,{children:(0,_.jsxs)(fe.Tr,{children:[(0,_.jsx)(me.Th,{width:15,children:"Vulnerability ID"}),(0,_.jsx)(me.Th,{width:20,children:"Description"}),(0,_.jsx)(me.Th,{width:10,children:"Severity"}),(0,_.jsx)(me.Th,{width:15,children:"CVSS Score"}),(0,_.jsx)(me.Th,{width:20,children:"Transitive Dependency"}),(0,_.jsx)(me.Th,{width:20,children:"Remediation"})]})}),(0,_.jsx)(Ee,{isNoData:0===r.length,numRenderedColumns:7,children:w(r).map((function(e,r){return(0,_.jsx)(ye.p,{children:(0,_.jsx)(qe,{item:e,providerName:n,rowIndex:r})},r)}))})]})})},$e=function(e){var n=e.providerName,r=e.dependency,i=e.vulnerabilities;return(0,_.jsx)(O.Z,{style:{backgroundColor:"var(--pf-v5-global--BackgroundColor--100)"},children:(0,_.jsxs)(xe.i,{variant:pe.B.compact,children:[(0,_.jsx)(je.h,{children:(0,_.jsxs)(fe.Tr,{children:[(0,_.jsx)(me.Th,{width:15,children:"Vulnerability ID"}),(0,_.jsx)(me.Th,{width:20,children:"Description"}),(0,_.jsx)(me.Th,{width:10,children:"Severity"}),(0,_.jsx)(me.Th,{width:15,children:"CVSS Score"}),(0,_.jsx)(me.Th,{width:20,children:"Direct Dependency"}),(0,_.jsx)(me.Th,{width:20,children:"Remediation"})]})}),(0,_.jsx)(Ee,{isNoData:0===i.length,numRenderedColumns:6,children:null===i||void 0===i?void 0:i.map((function(e,i){var t=[];return e.cves&&e.cves.length>0?e.cves.forEach((function(e){return t.push(e)})):e.unique&&t.push(e.id),(0,_.jsx)(ye.p,{children:t.map((function(t,a){return(0,_.jsx)(qe,{item:{id:e.id,dependencyRef:r.ref,vulnerability:e},providerName:n,rowIndex:i},"".concat(i,"-").concat(a))}))},i)}))})]})})},en=r(3566),nn=function(e){var n=e.vulnerabilities,r=void 0===n?[]:n,i=e.transitiveDependencies,t=void 0===i?[]:i,a={CRITICAL:0,HIGH:0,MEDIUM:0,LOW:0};return r.length>0?r.forEach((function(e){var n=e.severity;a.hasOwnProperty(n)&&a[n]++})):null===t||void 0===t||t.forEach((function(e){var n;null===(n=e.issues)||void 0===n||n.forEach((function(e){var n=e.severity;a.hasOwnProperty(n)&&a[n]++}))})),(0,_.jsxs)(en.B,{children:[a.CRITICAL>0&&(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(P.J,{isInline:!0,children:(0,_.jsx)(Je.ZP,{style:{fill:"#800000",height:"13px"}})}),"\xa0",a.CRITICAL,"\xa0"]}),a.HIGH>0&&(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(P.J,{isInline:!0,children:(0,_.jsx)(Je.ZP,{style:{fill:"#FF0000",height:"13px"}})}),"\xa0",a.HIGH,"\xa0"]}),a.MEDIUM>0&&(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(P.J,{isInline:!0,children:(0,_.jsx)(Je.ZP,{style:{fill:"#FFA500",height:"13px"}})}),"\xa0",a.MEDIUM,"\xa0"]}),a.LOW>0&&(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(P.J,{isInline:!0,children:(0,_.jsx)(Je.ZP,{style:{fill:"#5BA352",height:"13px"}})}),"\xa0",a.LOW]})]})},rn=r(6934),tn=function(e){var n,r,i=e.dependency,t=null===(n=i.issues)||void 0===n?void 0:n.some((function(e){return D(e)})),a=(null===(r=i.transitive)||void 0===r?void 0:r.some((function(e){var n;return null===(n=e.issues)||void 0===n?void 0:n.some((function(e){return D(e)}))})))||!1;return(0,_.jsx)(_.Fragment,{children:t||a?"Yes":"No"})},an=function(e){var n=e.name,r=e.dependencies,t=(0,i.useState)(""),a=(0,ne.Z)(t,2),s=a[0],c=a[1],o=function(e){var n=(0,i.useReducer)(De,(0,ae.Z)((0,ae.Z)({},Se),{},{currentPage:e&&e.page?(0,ae.Z)({},e.page):(0,ae.Z)({},Se.currentPage),sortBy:e&&e.sortBy?(0,ae.Z)({},e.sortBy):Se.sortBy})),r=(0,ne.Z)(n,2),t=r[0],a=r[1],s=(0,i.useCallback)((function(e){var n;a({type:Ae.SET_PAGE,payload:{page:e.page>=1?e.page:1,perPage:null!==(n=e.perPage)&&void 0!==n?n:Se.currentPage.perPage}})}),[]),c=(0,i.useCallback)((function(e,n,r,i){a({type:Ae.SET_SORT_BY,payload:{index:n,direction:r}})}),[]);return{page:t.currentPage,sortBy:t.sortBy,changePage:s,changeSortBy:c}}(),l=o.page,d=o.sortBy,u=o.changePage,h=o.changeSortBy,g=function(e){var n=e.items,r=e.currentSortBy,t=e.currentPage,a=e.filterItem,s=e.compareToByColumn;return(0,i.useMemo)((function(){var e,i=(0,Me.Z)(n||[]).filter(a),c=!1;return e=(0,Me.Z)(i).sort((function(e,n){var i=s(e,n,null===r||void 0===r?void 0:r.index);return 0!==i&&(c=!0),i})),c&&(null===r||void 0===r?void 0:r.direction)===Te.B.desc&&(e=e.reverse()),{pageItems:e.slice((t.page-1)*t.perPage,t.page*t.perPage),filteredItems:i}}),[n,t,r,s,a])}({items:r,currentPage:l,currentSortBy:d,compareToByColumn:function(e,n,r){return 1===r?e.ref.localeCompare(n.ref):0},filterItem:function(e){var n=!0;return s&&s.trim().length>0&&(n=-1!==e.ref.toLowerCase().indexOf(s.toLowerCase())),n}}),v=g.pageItems,x=g.filteredItems,p={name:"Dependency Name",version:"Current Version",direct:"Direct Vulnerabilities",transitive:"Transitive Vulnerabilities",rhRemediation:"Remediation available"},j=i.useState({"siemur/test-space":"name"}),m=(0,ne.Z)(j,2),y=m[0],I=m[1],C=function(e,n,r,i){return{isExpanded:y[e.ref]===n,onToggle:function(){return function(e,n){var r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],i=(0,ae.Z)({},y);r?i[e.ref]=n:delete i[e.ref],I(i)}(e,n,y[e.ref]!==n)},expandId:"compound-expandable-example",rowIndex:r,columnIndex:i}};return(0,_.jsx)(O.Z,{children:(0,_.jsx)(E.e,{children:(0,_.jsx)("div",{style:{backgroundColor:"var(--pf-v5-global--BackgroundColor--100)"},children:""!==f(n)&&void 0===r?(0,_.jsx)("div",{children:(0,_.jsxs)(se.u,{variant:se.I.sm,children:[(0,_.jsx)(ce.t,{icon:(0,_.jsx)(oe.k,{icon:Ze.ZP}),titleText:"Set up "+n,headingLevel:"h2"}),(0,_.jsxs)(le.B,{children:["You need to provide a valid credentials to see ",n," data. You can use the button below to sing-up for ",n,". If you have already signed up, enter your credentials in your extension settings and then regenerate the Dependency Analytics report."]}),(0,_.jsx)("br",{}),(0,_.jsx)("br",{}),(0,_.jsx)("a",{href:f(n),target:"_blank",rel:"noopener noreferrer",children:(0,_.jsxs)(U.zx,{variant:"primary",size:"sm",children:["Sign up for ",n]})})]})}):(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(de.o,{children:(0,_.jsxs)(ue.c,{children:[(0,_.jsx)(he.R,{toggleIcon:(0,_.jsx)(Ce.ZP,{}),breakpoint:"xl",children:(0,_.jsx)(ge.E,{variant:"search-filter",children:(0,_.jsx)(ve.M,{style:{width:"250px"},placeholder:"Filter by Dependency name",value:s,onChange:function(e,n){return c(n)},onClear:function(){return c("")}})})}),(0,_.jsx)(ge.E,{variant:ge.A.pagination,align:{default:"alignRight"},children:(0,_.jsx)(Pe,{isTop:!0,count:x.length,params:l,onChange:u})})]})}),(0,_.jsxs)(xe.i,{"aria-label":"Compound expandable table",variant:pe.B.compact,children:[(0,_.jsx)(je.h,{children:(0,_.jsxs)(fe.Tr,{children:[(0,_.jsx)(me.Th,{width:25,sort:{columnIndex:1,sortBy:(0,ae.Z)({},d),onSort:h},children:p.name}),(0,_.jsx)(me.Th,{children:p.version}),(0,_.jsx)(me.Th,{children:p.direct}),(0,_.jsx)(me.Th,{children:p.transitive}),(0,_.jsx)(me.Th,{children:p.rhRemediation})]})}),(0,_.jsx)(Ee,{isNoData:0===x.length,numRenderedColumns:8,noDataEmptyState:(0,_.jsxs)(se.u,{variant:se.I.sm,children:[(0,_.jsx)(ce.t,{icon:(0,_.jsx)(oe.k,{icon:rn.ZP}),titleText:"No results found",headingLevel:"h2"}),(0,_.jsx)(le.B,{children:"Clear all filters and try again."})]}),children:null===v||void 0===v?void 0:v.map((function(e,r){var i,t,a,s,c,o=y[e.ref],l=!!o;return null!==(i=e.issues)&&void 0!==i&&i.length||null!==(t=e.transitive)&&void 0!==t&&t.length?(0,_.jsxs)(ye.p,{isExpanded:l,children:[(0,_.jsxs)(fe.Tr,{children:[(0,_.jsx)(Ie.Td,{width:30,dataLabel:p.name,component:"th",children:(0,_.jsx)(ke,{name:e.ref})}),(0,_.jsx)(Ie.Td,{width:15,dataLabel:p.version,children:b(e.ref)}),(0,_.jsx)(Ie.Td,{width:15,dataLabel:p.direct,compoundExpand:C(e,"direct",r,2),children:null!==(a=e.issues)&&void 0!==a&&a.length?(0,_.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:[(0,_.jsx)("div",{style:{width:"25px"},children:null===(s=e.issues)||void 0===s?void 0:s.length}),(0,_.jsx)(k.i,{orientation:{default:"vertical"},style:{paddingRight:"10px"}}),(0,_.jsx)(nn,{vulnerabilities:e.issues})]}):0}),(0,_.jsx)(Ie.Td,{width:15,dataLabel:p.transitive,compoundExpand:C(e,"transitive",r,3),children:null!==(c=e.transitive)&&void 0!==c&&c.length?(0,_.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:[(0,_.jsx)("div",{style:{width:"25px"},children:e.transitive.map((function(e){var n;return null===(n=e.issues)||void 0===n?void 0:n.length})).reduce((function(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:0)+(arguments.length>1&&void 0!==arguments[1]?arguments[1]:0)}))}),(0,_.jsx)(k.i,{orientation:{default:"vertical"},style:{paddingRight:"10px"}}),(0,_.jsx)(nn,{transitiveDependencies:e.transitive})]}):0}),(0,_.jsx)(Ie.Td,{width:15,dataLabel:p.rhRemediation,children:(0,_.jsx)(tn,{dependency:e})})]}),l?(0,_.jsx)(fe.Tr,{isExpanded:l,children:(0,_.jsx)(Ie.Td,{dataLabel:p[o],noPadding:!0,colSpan:6,children:(0,_.jsx)(be.G,{children:(0,_.jsx)("div",{className:"pf-v5-u-m-md",children:"direct"===o&&e.issues&&e.issues.length>0?(0,_.jsx)($e,{providerName:n,dependency:e,vulnerabilities:e.issues}):"transitive"===o&&e.transitive&&e.transitive.length>0?(0,_.jsx)(Xe,{providerName:n,transitiveDependencies:e.transitive}):null})})})}):null]},e.ref):null}))})]}),(0,_.jsx)(Pe,{isTop:!1,count:x.length,params:l,onChange:u}),"osv-nvd"===n&&(0,_.jsx)("div",{children:(0,_.jsx)("p",{children:"Disclaimer:This Product uses data from the NVD API but is not endorsed or certified by the NVD"})})]})})})})},sn=function(e){var n=A(e.report),r=i.useState(S(n[0])),t=(0,ne.Z)(r,2),s=t[0],c=t[1],o=i.useState(!0),l=(0,ne.Z)(o,1)[0],d=n.map((function(e){var n,r=S(e),i=null===(n=e.report.dependencies)||void 0===n?void 0:n.filter((function(e){return e.highestVulnerability}));return(0,_.jsx)(re.O,{eventKey:r,title:(0,_.jsx)(ie.T,{children:r}),"aria-label":"".concat(r," source"),children:(0,_.jsx)(a.NP,{variant:a.Dk.default,children:(0,_.jsx)(an,{name:r,dependencies:i})})})}));return(0,_.jsx)("div",{children:(0,_.jsx)(te.m,{activeKey:s,onSelect:function(e,n){c(n)},"aria-label":"Providers",role:"region",variant:l?"light300":"default",isBox:!0,children:d})})},cn=function(e){var n=e.report,r=i.useState(Object.keys(n)[0]||""),t=(0,ne.Z)(r,2),o=t[0],l=t[1],d=i.useState(!0),u=(0,ne.Z)(d,1)[0],h=Object.entries(n).map((function(e){var n=(0,ne.Z)(e,2),r=n[0],i=n[1];return(0,_.jsxs)(re.O,{eventKey:r,title:(0,_.jsx)(ie.T,{children:m(r,!0)}),"aria-label":"".concat(r," source"),children:[(0,_.jsx)(ee,{report:i}),(0,_.jsx)(a.NP,{variant:a.Dk.light,children:(0,_.jsx)(s.r,{hasGutter:!0,children:(0,_.jsx)(c.P,{children:(0,_.jsx)(X,{report:i})})})}),(0,_.jsx)(a.NP,{variant:a.Dk.default,children:(0,_.jsx)(sn,{report:i})})]})}));return(0,_.jsx)("div",{children:(0,_.jsx)(te.m,{activeKey:o,onSelect:function(e,n){l(n)},"aria-label":"Providers",role:"region",variant:u?"light300":"default",isBox:!0,children:h})})},on=window.appData,ln=(0,i.createContext)(on),dn=function(){return(0,i.useContext)(ln)};var un=function(){return(0,_.jsx)(ln.Provider,{value:on,children:(e=on.report,"object"===typeof e&&null!==e&&Object.keys(e).every((function(n){return"scanned"in e[n]&&"providers"in e[n]&&"object"===typeof e[n].scanned&&"object"===typeof e[n].providers}))?(0,_.jsx)(a.NP,{variant:a.Dk.default,children:(0,_.jsx)(cn,{report:on.report})}):(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(ee,{report:on.report}),(0,_.jsx)(a.NP,{variant:a.Dk.light,children:(0,_.jsx)(s.r,{hasGutter:!0,children:(0,_.jsx)(c.P,{children:(0,_.jsx)(X,{report:on.report})})})}),(0,_.jsx)(a.NP,{variant:a.Dk.default,children:(0,_.jsx)(sn,{report:on.report})})]}))});var e},hn=function(e){e&&e instanceof Function&&r.e(736).then(r.bind(r,599)).then((function(n){var r=n.getCLS,i=n.getFID,t=n.getFCP,a=n.getLCP,s=n.getTTFB;r(e),i(e),t(e),a(e),s(e)}))};t.createRoot(document.getElementById("root")).render((0,_.jsx)(i.StrictMode,{children:(0,_.jsx)(un,{})})),hn()}},n={};function r(i){var t=n[i];if(void 0!==t)return t.exports;var a=n[i]={id:i,loaded:!1,exports:{}};return e[i](a,a.exports,r),a.loaded=!0,a.exports}r.m=e,function(){var e=[];r.O=function(n,i,t,a){if(!i){var s=1/0;for(d=0;d=a)&&Object.keys(r.O).every((function(e){return r.O[e](i[o])}))?i.splice(o--,1):(c=!1,a0&&e[d-1][2]>a;d--)e[d]=e[d-1];e[d]=[i,t,a]}}(),r.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(n,{a:n}),n},r.d=function(e,n){for(var i in n)r.o(n,i)&&!r.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},r.e=function(){return Promise.resolve()},r.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}(),r.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},r.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e},function(){var e={179:0};r.O.j=function(n){return 0===e[n]};var n=function(n,i){var t,a,s=i[0],c=i[1],o=i[2],l=0;if(s.some((function(n){return 0!==e[n]}))){for(t in c)r.o(c,t)&&(r.m[t]=c[t]);if(o)var d=o(r)}for(n&&n(i);l2&&(t=o.slice(1,o.length-1).join("/")),-1!==r.indexOf("@")&&(a=r.substring(r.indexOf("@")+1));var c=o[o.length-1];return a&&(c=c.substring(0,c.indexOf("@"))),new e(s,t,c,a)}}]),e}();function N(e){var n=[];return Object.keys(e.providers).forEach((function(r){var i=e.providers[r].sources;void 0!==i&&Object.keys(i).length>0?Object.keys(i).forEach((function(e){n.push({provider:r,source:e,report:i[e]})})):"trusted-content"!==r&&n.push({provider:r,source:r,report:{}})})),n.sort((function(e,n){return 0===Object.keys(e.report).length&&0===Object.keys(n.report).length?""===f(e.provider)?""===f(n.provider)?0:-1:1:Object.keys(n.report).length-Object.keys(e.report).length}))}function P(e){return void 0===e?"unknown":e.provider!==e.source?"$item.provider/$item.source":e.provider}function k(e){var n;return!(!e.remediation||!(e.remediation.fixedIn||null!==(n=e.remediation)&&void 0!==n&&n.trustedContent))}function O(e){var n=[];return e.map((function(e){return{dependencyRef:e.ref,vulnerabilities:e.issues||[]}})).forEach((function(e){var r;null===(r=e.vulnerabilities)||void 0===r||r.forEach((function(r){r.cves&&r.cves.length>0?r.cves.forEach((function(i){n.push({id:i,dependencyRef:e.dependencyRef,vulnerability:r})})):n.push({id:r.id,dependencyRef:e.dependencyRef,vulnerability:r})}))})),n.sort((function(e,n){return n.vulnerability.cvssScore-e.vulnerability.cvssScore}))}var Z=r(3442),L=r(3324),z=r(6363),E=r(8437),B=r(6798),R=r(2996),F=r(3020),H=r(4223),G=r(1858),U=r(493),_=r(7065),V=r(7941),Y=r(2355),J=r(8485),W=r(9090),Q=r(2570),K=r(7806),q=r(5859),X=["#800000","#FF0000","#FFA500","#5BA352"],$=function(e){var n,r,i,t,a,s=e.summary,o=null!==(n=null===s||void 0===s?void 0:s.critical)&&void 0!==n?n:0,c=null!==(r=null===s||void 0===s?void 0:s.high)&&void 0!==r?r:0,l=null!==(i=null===s||void 0===s?void 0:s.medium)&&void 0!==i?i:0,d=null!==(t=null===s||void 0===s?void 0:s.low)&&void 0!==t?t:0,u=null!==(a=null===s||void 0===s?void 0:s.total)&&void 0!==a?a:0,h=o+c+l+d>0,g=h?X:["#D5F5E3"],v=[{name:"Critical: ".concat(o),symbol:{type:"square",fill:X[0]}},{name:"High: ".concat(c),symbol:{type:"square",fill:X[1]}},{name:"Medium: ".concat(l),symbol:{type:"square",fill:X[2]}},{name:"Low: ".concat(d),symbol:{type:"square",fill:X[3]}}];return(0,q.jsx)("div",{children:(0,q.jsx)(H.e,{style:{paddingBottom:"inherit",padding:"0"},children:(0,q.jsx)(Q.b,{children:(0,q.jsx)("div",{style:{height:"230px",width:"350px"},children:(0,q.jsx)(K.H,{constrainToVisibleArea:!0,data:h?[{x:"Critical",y:o},{x:"High",y:c},{x:"Medium",y:l},{x:"Low",y:d}]:[{x:"Empty",y:1e-10}],labels:function(e){var n=e.datum;return"".concat(n.x,": ").concat(n.y)},legendData:v,legendOrientation:"vertical",legendPosition:"right",padding:{left:20,right:140},subTitle:"Unique vulnerabilities",title:"".concat(u),width:350,colorScale:g})})})})})},ee=r(6155),ne="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTJweCIgaGVpZ2h0PSIxM3B4IiB2aWV3Qm94PSIwIDAgMTIgMTMiIGlkPSJTZWN1cml0eUNoZWNrSWNvbiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZyBpZD0iTXVsdGktdmVuZG9yIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iT3ZlcnZpZXctQ29weSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEyMDcsIC05OTMpIiBmaWxsPSIjM0U4NjM1Ij4KICAgICAgICAgICAgPGcgaWQ9IkRldGFpbHMtb2YtZGVwZW5kZW5jeS1jb20uZ2l0aHViIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0MjcsIDgxOSkiPgogICAgICAgICAgICAgICAgPGcgaWQ9IkRlcGVuZGVuY3ktMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMTQ0KSI+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc4MC4xNzI4LCAyNCkiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMy4yKSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iSWNvbnMvMi4tU2l6ZS1zbS9BY3Rpb25zL2NoZWNrIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAyLjgpIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTAuNTU2NTc4OSwwIEMxMC43OTA2MjQ5LDAgMTAuOTc5MzMyMiwwLjE4MTU0Mjk2OSAxMC45NzkzMzIyLDAuNDA2MjUgTDEwLjk3OTMzMjIsNS43NDA4MjAzMSBDMTAuOTc5MzMyMiw5Ljc1IDYuMjQwODE5MDcsMTMgNS40OTU3OTI5NiwxMyBDNC43NTA3NjY4NCwxMyAwLDkuNzUgMCw1LjczOTU1MDc4IEwwLDAuNDA2MjUgQzAsMC4xODE1NDI5NjkgMC4xODg3MDcyNzIsMCAwLjQyMjc1MzMwNCwwIFogTTguNTQyNzc4ODMsMy4xMTc4MjY2NyBMNC43OTEyOTYxLDYuODkwODczNTMgTDMuMDM5ODEzMzgsNS4xMjkzMjQ0IEMyLjg4MzYwOSw0Ljk3MjIwNjgzIDIuNjMwMzI4MTIsNC45NzIyMDY4MyAyLjQ3NDEyMzc1LDUuMTI5MzI0NCBMMS45MDg0NDkzOCw1LjY5ODI2NTU2IEMxLjc1MjI0NTAxLDUuODU1MzgzMTIgMS43NTIyNDUwMSw2LjExMDEwNDQ5IDEuOTA4NDQ5MzgsNi4yNjcyMDY3MSBMNC41MDg0NTc5Nyw4Ljg4MjE1OTkxIEM0LjY2NDY0NzA4LDkuMDM5Mjc3NDcgNC45MTc5MTI3LDkuMDM5Mjc3NDcgNS4wNzQxMzIzMyw4Ljg4MjE3NTI1IEw5LjY3NDE0MjgyLDQuMjU1NzA4OTggQzkuODMwMzQ3Miw0LjA5ODU5MTQxIDkuODMwMzQ3MiwzLjg0Mzg3MDA0IDkuNjc0MTQyODIsMy42ODY3Njc4MiBMOS4xMDg0Njg0NiwzLjExNzgyNjY3IEM4Ljk1MjI2NDA4LDIuOTYwNzI0NDQgOC42OTg5ODMyLDIuOTYwNzI0NDQgOC41NDI3Nzg4MywzLjExNzgyNjY3IFoiIGlkPSJDb21iaW5lZC1TaGFwZSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=",re=function(e){var n=e.report,r=e.isReportMap,i=e.purl,t=vn();return(0,q.jsxs)(s.r,{hasGutter:!0,children:[(0,q.jsxs)(Z.D,{headingLevel:"h3",size:Z.H["2xl"],style:{paddingLeft:"15px"},children:[(0,q.jsx)(L.J,{isInline:!0,status:"info",children:(0,q.jsx)(W.ZP,{style:{fill:"#f0ab00"}})}),"\xa0Red Hat Overview of security Issues"]}),(0,q.jsx)(z.i,{}),(0,q.jsx)(o.P,{children:(0,q.jsxs)(E.Z,{isFlat:!0,isFullHeight:!0,children:[(0,q.jsx)(B.O,{children:(0,q.jsx)(R.l,{children:(0,q.jsx)(F.M,{style:{fontSize:"large"},children:r?(0,q.jsxs)(q.Fragment,{children:[i?T(i):"No Image name"," - Vendor Issues"]}):(0,q.jsx)(q.Fragment,{children:"Vendor Issues"})})})}),(0,q.jsxs)(H.e,{children:[(0,q.jsx)(G.g,{children:(0,q.jsx)(U.b,{children:(0,q.jsx)(F.M,{children:"Below is a list of dependencies affected with CVE."})})}),(0,q.jsx)(_.o,{isAutoFit:!0,style:{paddingTop:"10px"},children:N(n).map((function(e,n){return(0,q.jsxs)(G.g,{style:{display:"flex",flexDirection:"column",alignItems:"center"},children:[(0,q.jsx)(q.Fragment,{children:(0,q.jsx)(F.M,{style:{fontSize:"large"},children:P(e)})}),(0,q.jsx)(U.b,{children:(0,q.jsx)($,{summary:e.report.summary})})]},n)}))})]}),(0,q.jsx)(z.i,{})]})}),(0,q.jsxs)(o.P,{md:6,children:[(0,q.jsx)(E.Z,{isFlat:!0,children:(0,q.jsxs)(G.g,{children:[(0,q.jsx)(R.l,{component:"h4",children:(0,q.jsxs)(F.M,{style:{fontSize:"large"},children:[(0,q.jsx)(L.J,{isInline:!0,status:"info",children:(0,q.jsx)(ee.ZP,{style:{fill:"#cc0000"}})}),"\xa0 Red Hat Remediations"]})}),(0,q.jsx)(H.e,{children:(0,q.jsx)(U.b,{children:r?(0,q.jsxs)(V.aV,{isPlain:!0,children:[(0,q.jsx)(Y.H,{children:"Switch to UBI 9 for enhanced security and enterprise-grade stability in your containerized applications, backed by Red Hat's support and compatibility assurance."}),(0,q.jsx)(Y.H,{children:(0,q.jsx)("a",{href:i?S(i,n,t.imageMapping):"###",target:"_blank",rel:"noreferrer",children:(0,q.jsx)(J.zx,{variant:"primary",size:"sm",children:"Take me there"})})})]}):(0,q.jsx)(V.aV,{isPlain:!0,children:N(n).map((function(e,n){return Object.keys(e.report).length>0?(0,q.jsxs)(Y.H,{children:[(0,q.jsx)(L.J,{isInline:!0,status:"success",children:(0,q.jsx)("img",{src:ne,alt:"Security Check Icon"})}),"\xa0",e.report.summary.remediations," remediations are available from Red Hat for ",e.provider]}):(0,q.jsxs)(Y.H,{children:[(0,q.jsx)(L.J,{isInline:!0,status:"success",children:(0,q.jsx)("img",{src:ne,alt:"Security Check Icon"})}),"\xa0 There are no available Red Hat remediations for your SBOM at this time for ",e.provider]})}))})})})]})}),"\xa0"]}),(0,q.jsxs)(o.P,{md:6,children:[(0,q.jsx)(E.Z,{isFlat:!0,children:(0,q.jsxs)(G.g,{children:[(0,q.jsx)(R.l,{component:"h4",children:(0,q.jsx)(F.M,{style:{fontSize:"large"},children:"Join to explore Red Hat TPA"})}),(0,q.jsx)(H.e,{children:(0,q.jsx)(U.b,{children:(0,q.jsxs)(V.aV,{isPlain:!0,children:[(0,q.jsx)(Y.H,{children:"Check out our new Trusted Profile Analyzer to get visibility and insight into your software risk profile, for instance by exploring vulnerabilites or analyzing SBOMs."}),(0,q.jsx)(Y.H,{children:(0,q.jsx)("a",{href:"https://console.redhat.com/application-services/trusted-content",target:"_blank",rel:"noopener noreferrer",children:(0,q.jsx)(J.zx,{variant:"primary",size:"sm",children:"Take me there"})})})]})})})]})}),"\xa0"]})]})},ie=r(2933),te=function(e){var n=e.report,r=Object.keys(n.providers).map((function(e){return n.providers[e].status})).filter((function(e){return!e.ok&&!(!(n=e).ok&&401===n.code&&"Unauthenticated"===n.message&&x.includes(n.name));var n}));return(0,q.jsx)(q.Fragment,{children:r.map((function(e,n){return(0,q.jsx)(ie.b,{variant:e.code>=500?ie.U.danger:e.code>=400?ie.U.warning:void 0,title:"".concat(M(e.name),": ").concat(e.message)},n)}))})},ae=r(885),se=r(6081),oe=r(4817),ce=r(6467),le=r(1413),de=r(9809),ue=r(382),he=r(8521),ge=r(2e3),ve=r(6989),pe=r(2401),xe=r(6496),je=r(8987),fe=r(9623),me=r(9626),ye=r(205),Ie=r(3610),be=r(7990),Ce=r(5091),Me=r(6056),Te=r(1915),Ae=r(1178),Se=r(7102),we=r(2982),De=r(1917),Ne=function(e){return e[e.SET_PAGE=0]="SET_PAGE",e[e.SET_SORT_BY=1]="SET_SORT_BY",e}(Ne||{}),Pe={changed:!1,currentPage:{page:1,perPage:10},sortBy:void 0},ke=function(e,n){switch(n.type){case Ne.SET_PAGE:var r=n.payload;return(0,le.Z)((0,le.Z)({},e),{},{changed:!0,currentPage:{page:r.page,perPage:r.perPage}});case Ne.SET_SORT_BY:var i=n.payload;return(0,le.Z)((0,le.Z)({},e),{},{changed:!0,sortBy:{index:i.index,direction:i.direction}});default:return e}},Oe=r(9960),Ze=r(500),Le=function(e){var n,r=e.count,i=e.params,t=e.isTop,a=(e.isCompact,e.perPageOptions),s=e.onChange,o=function(){return i.perPage||10};return(0,q.jsx)(Oe.t,{itemCount:r,page:i.page||1,perPage:o(),onPageInput:function(e,n){s({page:n,perPage:o()})},onSetPage:function(e,n){s({page:n,perPage:o()})},onPerPageSelect:function(e,n){s({page:1,perPage:n})},widgetId:"pagination-options-menu",variant:t?Oe.a.top:Oe.a.bottom,perPageOptions:(n=a||[10,20,50,100],n.map((function(e){return{title:String(e),value:e}}))),toggleTemplate:function(e){return(0,q.jsx)(Ze.v,(0,le.Z)({},e))}})},ze=function(e){var n=e.name,r=e.showVersion,i=void 0!==r&&r;return(0,q.jsx)(q.Fragment,{children:(0,q.jsx)("a",{href:I(n),target:"_blank",rel:"noreferrer",children:m(n,i)})})},Ee=r(164),Be=r(5020),Re=r(8649),Fe=r(7514),He=function(e){var n=e.numRenderedColumns,r=e.isLoading,i=void 0!==r&&r,t=e.isError,a=void 0!==t&&t,s=e.isNoData,o=void 0!==s&&s,c=e.errorEmptyState,l=void 0===c?null:c,d=e.noDataEmptyState,u=void 0===d?null:d,h=e.children,g=(0,q.jsxs)(de.u,{variant:de.I.sm,children:[(0,q.jsx)(he.k,{icon:Re.ZP,color:Fe.a.value}),(0,q.jsx)(Z.D,{headingLevel:"h2",size:"lg",children:"Unable to connect"}),(0,q.jsx)(ge.B,{children:"There was an error retrieving data. Check your connection and try again."})]}),v=(0,q.jsxs)(de.u,{variant:de.I.sm,children:[(0,q.jsx)(he.k,{icon:Be.ZP}),(0,q.jsx)(Z.D,{headingLevel:"h2",size:"lg",children:"No data available"}),(0,q.jsx)(ge.B,{children:"No data available to be shown here."})]});return(0,q.jsx)(q.Fragment,{children:i?(0,q.jsx)(Me.p,{children:(0,q.jsx)(be.Tr,{children:(0,q.jsx)(Te.Td,{colSpan:n,children:(0,q.jsx)(Q.b,{children:(0,q.jsx)(Ee.$,{size:"xl"})})})})}):a?(0,q.jsx)(Me.p,{"aria-label":"Table error",children:(0,q.jsx)(be.Tr,{children:(0,q.jsx)(Te.Td,{colSpan:n,children:(0,q.jsx)(Q.b,{children:l||g})})})}):o?(0,q.jsx)(Me.p,{"aria-label":"Table no data",children:(0,q.jsx)(be.Tr,{children:(0,q.jsx)(Te.Td,{colSpan:n,children:(0,q.jsx)(Q.b,{children:u||v})})})}):h})},Ge=function(e){var n=e.packageName;e.cves;return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(L.J,{isInline:!0,status:"success",children:(0,q.jsx)("img",{src:ne,alt:"Security Check Icon"})}),"\xa0",(0,q.jsx)("a",{href:y(n),target:"_blank",rel:"noreferrer",children:b(n)})]})},Ue=function(){var e=vn().providerPrivateData;return{hideIssue:function(n,r){return!(!e||-1===e.indexOf(n))&&r}}},_e=function(e){var n,r,i,t=e.sourceName,a=e.vulnerability,s=Ue(),o=vn();return(0,q.jsx)(q.Fragment,{children:s.hideIssue(t,a.unique)?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)("a",{href:o.snykSignup,target:"_blank",rel:"noreferrer",children:"Sign up for a Snyk account"})," ","to learn about the vulnerabilities found"]}):"snyk"!==t||null!==(null===(n=a.remediation)||void 0===n?void 0:n.fixedIn)&&0!==(null===(r=a.remediation)||void 0===r||null===(i=r.fixedIn)||void 0===i?void 0:i.length)?(0,q.jsx)("a",{href:C(t,a.id,o),target:"_blank",rel:"noreferrer",children:a.id}):(0,q.jsx)("p",{})})},Ve=r(736),Ye=r(5351),Je=r(975),We=r(6647),Qe=function(e){var n,r=e.vulnerability;switch(r.severity){case"CRITICAL":case"HIGH":n=Ve.n9.danger;break;default:n=Ve.n9.warning}return(0,q.jsx)(q.Fragment,{children:(0,q.jsx)(Ye.P,{hasGutter:!0,children:(0,q.jsx)(Je.J,{isFilled:!0,children:(0,q.jsx)(We.E,{title:"".concat(r.cvssScore,"/10"),"aria-label":"cvss-score",value:r.cvssScore,min:0,max:10,size:We.L.sm,variant:n,measureLocation:Ve.nK.none})})})})},Ke=r(313),qe=function(e){var n,r=e.vulnerability;switch(r.severity){case"CRITICAL":n="#800000";break;case"HIGH":n="#FF0000";break;case"MEDIUM":n="#FFA500";break;case"LOW":n="#5BA352";break;default:n="grey"}return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(L.J,{isInline:!0,children:(0,q.jsx)(Ke.ZP,{style:{fill:n,height:"13px"}})}),"\xa0",M(r.severity)]})},Xe=function(e){var n,r,i=e.id,t=vn();return(0,q.jsx)("a",{href:(n=i,r=t,r.cveIssueTemplate.replace(v,n)),target:"_blank",rel:"noreferrer",children:i})},$e=r(4150),en=function(e){var n=e.title,r=i.useState(!1),t=(0,ae.Z)(r,2),a=t[0],s=t[1];return(0,q.jsx)($e.L,{variant:$e.S.truncate,toggleText:a?"Show less":"Show more",onToggle:function(e,n){s(n)},isExpanded:a,children:n})},nn=function(e){var n,r,i,t,a,s=e.item,o=e.providerName,c=e.rowIndex;a=s.vulnerability.cves&&s.vulnerability.cves.length>0?s.vulnerability.cves:[s.vulnerability.id];var l=Ue().hideIssue(o,s.vulnerability.unique),d=vn();return(0,q.jsxs)(be.Tr,{children:[l?(0,q.jsx)(q.Fragment,{children:(0,q.jsx)(Te.Td,{colSpan:3,children:(0,q.jsx)("a",{href:d.snykSignup,target:"_blank",rel:"noreferrer",children:"Sign up for a Snyk account to learn about the vulnerabilities found"})})}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(Te.Td,{children:a.map((function(e,n){return(0,q.jsx)("p",{children:(0,q.jsx)(Xe,{id:e})},n)}))}),(0,q.jsx)(Te.Td,{children:(0,q.jsx)(en,{title:s.vulnerability.title})}),(0,q.jsx)(Te.Td,{noPadding:!0,children:(0,q.jsx)(qe,{vulnerability:s.vulnerability})})]}),(0,q.jsx)(Te.Td,{children:(0,q.jsx)(Qe,{vulnerability:s.vulnerability})}),(0,q.jsx)(Te.Td,{children:(0,q.jsx)(ze,{name:s.dependencyRef,showVersion:!0})}),(0,q.jsx)(Te.Td,{children:null!==(n=s.vulnerability.remediation)&&void 0!==n&&n.trustedContent?(0,q.jsx)(Ge,{cves:s.vulnerability.cves||[],packageName:null===(r=s.vulnerability.remediation)||void 0===r||null===(i=r.trustedContent)||void 0===i?void 0:i.ref},c):null!==(t=s.vulnerability.remediation)&&void 0!==t&&t.fixedIn?(0,q.jsx)(_e,{sourceName:o,vulnerability:s.vulnerability}):k(s.vulnerability)?null:(0,q.jsx)("span",{})})]},c)},rn=function(e){var n=e.providerName,r=e.transitiveDependencies;return(0,q.jsx)(E.Z,{style:{backgroundColor:"var(--pf-v5-global--BackgroundColor--100)"},children:(0,q.jsxs)(me.i,{variant:ye.B.compact,children:[(0,q.jsx)(Ie.h,{children:(0,q.jsxs)(be.Tr,{children:[(0,q.jsx)(Ce.Th,{width:15,children:"Vulnerability ID"}),(0,q.jsx)(Ce.Th,{width:20,children:"Description"}),(0,q.jsx)(Ce.Th,{width:10,children:"Severity"}),(0,q.jsx)(Ce.Th,{width:15,children:"CVSS Score"}),(0,q.jsx)(Ce.Th,{width:20,children:"Transitive Dependency"}),(0,q.jsx)(Ce.Th,{width:20,children:"Remediation"})]})}),(0,q.jsx)(He,{isNoData:0===r.length,numRenderedColumns:7,children:O(r).map((function(e,r){return(0,q.jsx)(Me.p,{children:(0,q.jsx)(nn,{item:e,providerName:n,rowIndex:r})},r)}))})]})})},tn=function(e){var n=e.providerName,r=e.dependency,i=e.vulnerabilities;return(0,q.jsx)(E.Z,{style:{backgroundColor:"var(--pf-v5-global--BackgroundColor--100)"},children:(0,q.jsxs)(me.i,{variant:ye.B.compact,children:[(0,q.jsx)(Ie.h,{children:(0,q.jsxs)(be.Tr,{children:[(0,q.jsx)(Ce.Th,{width:15,children:"Vulnerability ID"}),(0,q.jsx)(Ce.Th,{width:20,children:"Description"}),(0,q.jsx)(Ce.Th,{width:10,children:"Severity"}),(0,q.jsx)(Ce.Th,{width:15,children:"CVSS Score"}),(0,q.jsx)(Ce.Th,{width:20,children:"Direct Dependency"}),(0,q.jsx)(Ce.Th,{width:20,children:"Remediation"})]})}),(0,q.jsx)(He,{isNoData:0===i.length,numRenderedColumns:6,children:null===i||void 0===i?void 0:i.map((function(e,i){var t=[];return e.cves&&e.cves.length>0?e.cves.forEach((function(e){return t.push(e)})):e.unique&&t.push(e.id),(0,q.jsx)(Me.p,{children:t.map((function(t,a){return(0,q.jsx)(nn,{item:{id:e.id,dependencyRef:r.ref,vulnerability:e},providerName:n,rowIndex:i},"".concat(i,"-").concat(a))}))},i)}))})]})})},an=r(3566),sn=function(e){var n=e.vulnerabilities,r=void 0===n?[]:n,i=e.transitiveDependencies,t=void 0===i?[]:i,a={CRITICAL:0,HIGH:0,MEDIUM:0,LOW:0};return r.length>0?r.forEach((function(e){var n=e.severity;a.hasOwnProperty(n)&&a[n]++})):null===t||void 0===t||t.forEach((function(e){var n;null===(n=e.issues)||void 0===n||n.forEach((function(e){var n=e.severity;a.hasOwnProperty(n)&&a[n]++}))})),(0,q.jsxs)(an.B,{children:[a.CRITICAL>0&&(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(L.J,{isInline:!0,children:(0,q.jsx)(Ke.ZP,{style:{fill:"#800000",height:"13px"}})}),"\xa0",a.CRITICAL,"\xa0"]}),a.HIGH>0&&(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(L.J,{isInline:!0,children:(0,q.jsx)(Ke.ZP,{style:{fill:"#FF0000",height:"13px"}})}),"\xa0",a.HIGH,"\xa0"]}),a.MEDIUM>0&&(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(L.J,{isInline:!0,children:(0,q.jsx)(Ke.ZP,{style:{fill:"#FFA500",height:"13px"}})}),"\xa0",a.MEDIUM,"\xa0"]}),a.LOW>0&&(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(L.J,{isInline:!0,children:(0,q.jsx)(Ke.ZP,{style:{fill:"#5BA352",height:"13px"}})}),"\xa0",a.LOW]})]})},on=r(6934),cn=function(e){var n,r,i=e.dependency,t=null===(n=i.issues)||void 0===n?void 0:n.some((function(e){return k(e)})),a=(null===(r=i.transitive)||void 0===r?void 0:r.some((function(e){var n;return null===(n=e.issues)||void 0===n?void 0:n.some((function(e){return k(e)}))})))||!1;return(0,q.jsx)(q.Fragment,{children:t||a?"Yes":"No"})},ln=function(e){var n=e.name,r=e.dependencies,t=(0,i.useState)(""),a=(0,ae.Z)(t,2),s=a[0],o=a[1],c=function(e){var n=(0,i.useReducer)(ke,(0,le.Z)((0,le.Z)({},Pe),{},{currentPage:e&&e.page?(0,le.Z)({},e.page):(0,le.Z)({},Pe.currentPage),sortBy:e&&e.sortBy?(0,le.Z)({},e.sortBy):Pe.sortBy})),r=(0,ae.Z)(n,2),t=r[0],a=r[1],s=(0,i.useCallback)((function(e){var n;a({type:Ne.SET_PAGE,payload:{page:e.page>=1?e.page:1,perPage:null!==(n=e.perPage)&&void 0!==n?n:Pe.currentPage.perPage}})}),[]),o=(0,i.useCallback)((function(e,n,r,i){a({type:Ne.SET_SORT_BY,payload:{index:n,direction:r}})}),[]);return{page:t.currentPage,sortBy:t.sortBy,changePage:s,changeSortBy:o}}(),l=c.page,d=c.sortBy,u=c.changePage,h=c.changeSortBy,g=function(e){var n=e.items,r=e.currentSortBy,t=e.currentPage,a=e.filterItem,s=e.compareToByColumn;return(0,i.useMemo)((function(){var e,i=(0,we.Z)(n||[]).filter(a),o=!1;return e=(0,we.Z)(i).sort((function(e,n){var i=s(e,n,null===r||void 0===r?void 0:r.index);return 0!==i&&(o=!0),i})),o&&(null===r||void 0===r?void 0:r.direction)===De.B.desc&&(e=e.reverse()),{pageItems:e.slice((t.page-1)*t.perPage,t.page*t.perPage),filteredItems:i}}),[n,t,r,s,a])}({items:r,currentPage:l,currentSortBy:d,compareToByColumn:function(e,n,r){return 1===r?e.ref.localeCompare(n.ref):0},filterItem:function(e){var n=!0;return s&&s.trim().length>0&&(n=-1!==e.ref.toLowerCase().indexOf(s.toLowerCase())),n}}),v=g.pageItems,p=g.filteredItems,x={name:"Dependency Name",version:"Current Version",direct:"Direct Vulnerabilities",transitive:"Transitive Vulnerabilities",rhRemediation:"Remediation available"},j=i.useState({"siemur/test-space":"name"}),m=(0,ae.Z)(j,2),y=m[0],I=m[1],C=function(e,n,r,i){return{isExpanded:y[e.ref]===n,onToggle:function(){return function(e,n){var r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],i=(0,le.Z)({},y);r?i[e.ref]=n:delete i[e.ref],I(i)}(e,n,y[e.ref]!==n)},expandId:"compound-expandable-example",rowIndex:r,columnIndex:i}};return(0,q.jsx)(E.Z,{children:(0,q.jsx)(H.e,{children:(0,q.jsx)("div",{style:{backgroundColor:"var(--pf-v5-global--BackgroundColor--100)"},children:""!==f(n)&&void 0===r?(0,q.jsx)("div",{children:(0,q.jsxs)(de.u,{variant:de.I.sm,children:[(0,q.jsx)(ue.t,{icon:(0,q.jsx)(he.k,{icon:Be.ZP}),titleText:"Set up "+n,headingLevel:"h2"}),(0,q.jsxs)(ge.B,{children:["You need to provide a valid credentials to see ",n," data. You can use the button below to sing-up for ",n,". If you have already signed up, enter your credentials in your extension settings and then regenerate the Dependency Analytics report."]}),(0,q.jsx)("br",{}),(0,q.jsx)("br",{}),(0,q.jsx)("a",{href:f(n),target:"_blank",rel:"noopener noreferrer",children:(0,q.jsxs)(J.zx,{variant:"primary",size:"sm",children:["Sign up for ",n]})})]})}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(ve.o,{children:(0,q.jsxs)(pe.c,{children:[(0,q.jsx)(xe.R,{toggleIcon:(0,q.jsx)(Se.ZP,{}),breakpoint:"xl",children:(0,q.jsx)(je.E,{variant:"search-filter",children:(0,q.jsx)(fe.M,{style:{width:"250px"},placeholder:"Filter by Dependency name",value:s,onChange:function(e,n){return o(n)},onClear:function(){return o("")}})})}),(0,q.jsx)(je.E,{variant:je.A.pagination,align:{default:"alignRight"},children:(0,q.jsx)(Le,{isTop:!0,count:p.length,params:l,onChange:u})})]})}),(0,q.jsxs)(me.i,{"aria-label":"Compound expandable table",variant:ye.B.compact,children:[(0,q.jsx)(Ie.h,{children:(0,q.jsxs)(be.Tr,{children:[(0,q.jsx)(Ce.Th,{width:25,sort:{columnIndex:1,sortBy:(0,le.Z)({},d),onSort:h},children:x.name}),(0,q.jsx)(Ce.Th,{children:x.version}),(0,q.jsx)(Ce.Th,{children:x.direct}),(0,q.jsx)(Ce.Th,{children:x.transitive}),(0,q.jsx)(Ce.Th,{children:x.rhRemediation})]})}),(0,q.jsx)(He,{isNoData:0===p.length,numRenderedColumns:8,noDataEmptyState:(0,q.jsxs)(de.u,{variant:de.I.sm,children:[(0,q.jsx)(ue.t,{icon:(0,q.jsx)(he.k,{icon:on.ZP}),titleText:"No results found",headingLevel:"h2"}),(0,q.jsx)(ge.B,{children:"Clear all filters and try again."})]}),children:null===v||void 0===v?void 0:v.map((function(e,r){var i,t,a,s,o,c=y[e.ref],l=!!c;return null!==(i=e.issues)&&void 0!==i&&i.length||null!==(t=e.transitive)&&void 0!==t&&t.length?(0,q.jsxs)(Me.p,{isExpanded:l,children:[(0,q.jsxs)(be.Tr,{children:[(0,q.jsx)(Te.Td,{width:30,dataLabel:x.name,component:"th",children:(0,q.jsx)(ze,{name:e.ref})}),(0,q.jsx)(Te.Td,{width:15,dataLabel:x.version,children:b(e.ref)}),(0,q.jsx)(Te.Td,{width:15,dataLabel:x.direct,compoundExpand:C(e,"direct",r,2),children:null!==(a=e.issues)&&void 0!==a&&a.length?(0,q.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:[(0,q.jsx)("div",{style:{width:"25px"},children:null===(s=e.issues)||void 0===s?void 0:s.length}),(0,q.jsx)(z.i,{orientation:{default:"vertical"},style:{paddingRight:"10px"}}),(0,q.jsx)(sn,{vulnerabilities:e.issues})]}):0}),(0,q.jsx)(Te.Td,{width:15,dataLabel:x.transitive,compoundExpand:C(e,"transitive",r,3),children:null!==(o=e.transitive)&&void 0!==o&&o.length?(0,q.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:[(0,q.jsx)("div",{style:{width:"25px"},children:e.transitive.map((function(e){var n;return null===(n=e.issues)||void 0===n?void 0:n.length})).reduce((function(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:0)+(arguments.length>1&&void 0!==arguments[1]?arguments[1]:0)}))}),(0,q.jsx)(z.i,{orientation:{default:"vertical"},style:{paddingRight:"10px"}}),(0,q.jsx)(sn,{transitiveDependencies:e.transitive})]}):0}),(0,q.jsx)(Te.Td,{width:15,dataLabel:x.rhRemediation,children:(0,q.jsx)(cn,{dependency:e})})]}),l?(0,q.jsx)(be.Tr,{isExpanded:l,children:(0,q.jsx)(Te.Td,{dataLabel:x[c],noPadding:!0,colSpan:6,children:(0,q.jsx)(Ae.G,{children:(0,q.jsx)("div",{className:"pf-v5-u-m-md",children:"direct"===c&&e.issues&&e.issues.length>0?(0,q.jsx)(tn,{providerName:n,dependency:e,vulnerabilities:e.issues}):"transitive"===c&&e.transitive&&e.transitive.length>0?(0,q.jsx)(rn,{providerName:n,transitiveDependencies:e.transitive}):null})})})}):null]},e.ref):null}))})]}),(0,q.jsx)(Le,{isTop:!1,count:p.length,params:l,onChange:u}),"osv-nvd"===n&&(0,q.jsx)("div",{children:(0,q.jsx)("p",{children:"Disclaimer:This Product uses data from the NVD API but is not endorsed or certified by the NVD"})})]})})})})},dn=function(e){var n=N(e.report),r=i.useState(P(n[0])),t=(0,ae.Z)(r,2),s=t[0],o=t[1],c=i.useState(!0),l=(0,ae.Z)(c,1)[0],d=n.map((function(e){var n,r=P(e),i=null===(n=e.report.dependencies)||void 0===n?void 0:n.filter((function(e){return e.highestVulnerability}));return(0,q.jsx)(se.O,{eventKey:r,title:(0,q.jsx)(oe.T,{children:r}),"aria-label":"".concat(r," source"),children:(0,q.jsx)(a.NP,{variant:a.Dk.default,children:(0,q.jsx)(ln,{name:r,dependencies:i})})})}));return(0,q.jsx)("div",{children:(0,q.jsx)(ce.m,{activeKey:s,onSelect:function(e,n){o(n)},"aria-label":"Providers",role:"region",variant:l?"light300":"default",isBox:!0,children:d})})},un=function(e){var n=e.report,r=i.useState(Object.keys(n)[0]||""),t=(0,ae.Z)(r,2),c=t[0],l=t[1],d=i.useState(!0),u=(0,ae.Z)(d,1)[0],h=Object.entries(n).map((function(e){var n=(0,ae.Z)(e,2),r=n[0],i=n[1];return(0,q.jsxs)(se.O,{eventKey:r,title:(0,q.jsx)(oe.T,{children:T(r)}),"aria-label":"".concat(r," source"),children:[(0,q.jsx)(te,{report:i}),(0,q.jsx)(a.NP,{variant:a.Dk.light,children:(0,q.jsx)(s.r,{hasGutter:!0,children:(0,q.jsx)(o.P,{children:(0,q.jsx)(re,{report:i,isReportMap:!0,purl:r})})})}),(0,q.jsx)(a.NP,{variant:a.Dk.default,children:(0,q.jsx)(dn,{report:i})})]})}));return(0,q.jsx)("div",{children:(0,q.jsx)(ce.m,{activeKey:c,onSelect:function(e,n){l(n)},"aria-label":"Providers",role:"region",variant:u?"light300":"default",isBox:!0,children:h})})},hn=window.appData,gn=(0,i.createContext)(hn),vn=function(){return(0,i.useContext)(gn)};var pn=function(){return(0,q.jsx)(gn.Provider,{value:hn,children:(e=hn.report,"object"===typeof e&&null!==e&&Object.keys(e).every((function(n){return"scanned"in e[n]&&"providers"in e[n]&&"object"===typeof e[n].scanned&&"object"===typeof e[n].providers}))?(0,q.jsx)(a.NP,{variant:a.Dk.default,children:(0,q.jsx)(un,{report:hn.report})}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(te,{report:hn.report}),(0,q.jsx)(a.NP,{variant:a.Dk.light,children:(0,q.jsx)(s.r,{hasGutter:!0,children:(0,q.jsx)(o.P,{children:(0,q.jsx)(re,{report:hn.report})})})}),(0,q.jsx)(a.NP,{variant:a.Dk.default,children:(0,q.jsx)(dn,{report:hn.report})})]}))});var e},xn=function(e){e&&e instanceof Function&&r.e(736).then(r.bind(r,599)).then((function(n){var r=n.getCLS,i=n.getFID,t=n.getFCP,a=n.getLCP,s=n.getTTFB;r(e),i(e),t(e),a(e),s(e)}))};t.createRoot(document.getElementById("root")).render((0,q.jsx)(i.StrictMode,{children:(0,q.jsx)(pn,{})})),xn()}},n={};function r(i){var t=n[i];if(void 0!==t)return t.exports;var a=n[i]={id:i,loaded:!1,exports:{}};return e[i](a,a.exports,r),a.loaded=!0,a.exports}r.m=e,function(){var e=[];r.O=function(n,i,t,a){if(!i){var s=1/0;for(d=0;d=a)&&Object.keys(r.O).every((function(e){return r.O[e](i[c])}))?i.splice(c--,1):(o=!1,a0&&e[d-1][2]>a;d--)e[d]=e[d-1];e[d]=[i,t,a]}}(),r.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(n,{a:n}),n},r.d=function(e,n){for(var i in n)r.o(n,i)&&!r.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},r.e=function(){return Promise.resolve()},r.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}(),r.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},r.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e},function(){var e={179:0};r.O.j=function(n){return 0===e[n]};var n=function(n,i){var t,a,s=i[0],o=i[1],c=i[2],l=0;if(s.some((function(n){return 0!==e[n]}))){for(t in o)r.o(o,t)&&(r.m[t]=o[t]);if(c)var d=c(r)}for(n&&n(i);l sectionElements = rootElement.getByXPath("./section"); + assertEquals(1, sectionElements.size()); + List anchorElements = + page.getByXPath( + "//a[contains(@href, 'https://catalog.redhat.com/software/containers/ubi9/')]"); + assertTrue(!anchorElements.isEmpty(), "At least one href contains the desired substring"); + + verifySnykRequest(OK_TOKEN, 3); + verifyOssRequest(OK_USER, OK_TOKEN, 3); + } + private HtmlTableBody getTableBodyForDependency(String depRef, DomElement table) { List tbodies = table.getByXPath(".//tbody"); return tbodies.stream() diff --git a/src/test/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandlerTest.java b/src/test/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandlerTest.java index 965b68d7..090cde85 100644 --- a/src/test/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandlerTest.java +++ b/src/test/java/com/redhat/exhort/integration/trustedcontent/TcResponseHandlerTest.java @@ -28,11 +28,11 @@ import java.util.Map; import java.util.Set; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.junit.jupiter.api.Test; import com.redhat.exhort.api.PackageRef; import com.redhat.exhort.integration.Constants; +import com.redhat.exhort.integration.trustedcontent.ubi.UBIRecommendation; import com.redhat.exhort.model.trustedcontent.IndexedRecommendation; import io.quarkus.test.junit.QuarkusTest; @@ -47,8 +47,7 @@ class TcResponseHandlerTest { @Inject TcResponseHandler handler; - @ConfigProperty(name = "trustedcontent.recommended.ubi") - String recommendedUBIPurl; + @Inject UBIRecommendation mapping; @Test void testAggregation() throws IOException { @@ -114,14 +113,15 @@ void testEmpty() throws IOException { @Test void testSbomId() throws IOException { - String sbomId = "pkg:oci/quay.io/test-app@0.0.1"; + String sbomId = "pkg:oci/alpine@0.0.1"; + handler.ubiRecommendation = mapping; var response = handler.parseResponse( getClass() .getClassLoader() .getResourceAsStream("__files/trustedcontent/empty_report.json") .readAllBytes(), - "pkg:oci/quay.io/test-app@0.0.1"); + sbomId); assertNotNull(response); assertTrue(response.status().getOk()); assertEquals("OK", response.status().getMessage()); @@ -130,17 +130,19 @@ void testSbomId() throws IOException { PackageRef sbomRef = new PackageRef(sbomId); IndexedRecommendation recommendation = - new IndexedRecommendation(new PackageRef(recommendedUBIPurl), null); + new IndexedRecommendation(new PackageRef(expectedUBIRecommendation), null); assertEquals(1, response.recommendations().size()); assertEquals(recommendation, response.recommendations().get(sbomRef)); } private static final record ExpectedRecommendation(String version, Set cves) {} + private static final String expectedUBIRecommendation = "pkg:oci/ubi@0.0.2"; + public static class SbomIdTestProfile implements QuarkusTestProfile { @Override public Map getConfigOverrides() { - return Map.of("trustedcontent.recommended.ubi", "pkg:oci/quay.io/test-app@0.0.2"); + return Map.of("trustedcontent.recommendation.ubi.mapping.alpine", expectedUBIRecommendation); } } } diff --git a/src/test/resources/__files/reports/batch_report_all_token.json b/src/test/resources/__files/reports/batch_report_all_token.json index 67dc5aaf..419c7bca 100644 --- a/src/test/resources/__files/reports/batch_report_all_token.json +++ b/src/test/resources/__files/reports/batch_report_all_token.json @@ -839,7 +839,71 @@ } } }, - "pkg:oci/quay.io/default-app@0.0.1": { + "pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1": { + "scanned": { + "total": 2, + "direct": 2, + "transitive": 0 + }, + "providers": { + "oss-index": { + "status": { + "ok": false, + "name": "oss-index", + "code": 401, + "message": "Unauthorized: Verify the provided credentials are valid." + } + }, + "trusted-content": { + "status": { + "ok": true, + "name": "trusted-content", + "code": 200, + "message": "OK" + } + }, + "osv-nvd": { + "status": { + "ok": true, + "name": "osv-nvd", + "code": 200, + "message": "OK" + } + }, + "snyk": { + "status": { + "ok": true, + "name": "snyk", + "code": 200, + "message": "OK" + }, + "sources": { + "snyk": { + "summary": { + "direct": 0, + "transitive": 0, + "total": 0, + "dependencies": 0, + "critical": 0, + "high": 0, + "medium": 0, + "low": 0, + "remediations": 0, + "recommendations": 0, + "unscanned": 1 + }, + "unscanned": [ + { + "ref": "pkg:oci/default-app@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io%2Fdefault-app&tag=0.0.1", + "reason": "unsupported-pkg-type" + } + ] + } + } + } + } + }, + "pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1": { "scanned": { "total": 2, "direct": 2, @@ -886,8 +950,8 @@ }, "dependencies": [ { - "ref": "pkg:oci/quay.io/default-app@0.0.1", - "recommendation": "pkg:oci/registry.access.redhat.com/ubi9/ubi@latest" + "ref": "pkg:oci/debian@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1", + "recommendation": "pkg:oci/ubi@sha256%3Af5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?arch=amd64&repository_url=registry.access.redhat.com%2Fubi9%2Fubi&tag=9.3-1552" } ] } @@ -917,13 +981,13 @@ }, "dependencies": [ { - "ref": "pkg:oci/quay.io/default-app@0.0.1", - "recommendation": "pkg:oci/registry.access.redhat.com/ubi9/ubi@latest" + "ref": "pkg:oci/debian@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1", + "recommendation": "pkg:oci/ubi@sha256%3Af5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?arch=amd64&repository_url=registry.access.redhat.com%2Fubi9%2Fubi&tag=9.3-1552" } ], "unscanned": [ { - "ref": "pkg:oci/quay.io/default-app@0.0.1", + "ref": "pkg:oci/debian@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1", "reason": "unsupported-pkg-type" } ] diff --git a/src/test/resources/cyclonedx/batch-sbom.json b/src/test/resources/cyclonedx/batch-sbom.json index bd1796ec..363b2c06 100644 --- a/src/test/resources/cyclonedx/batch-sbom.json +++ b/src/test/resources/cyclonedx/batch-sbom.json @@ -781,40 +781,76 @@ } ] }, - "pkg:oci/quay.io/default-app@0.0.1" : { - "bomFormat": "CycloneDX", - "specVersion": "1.4", - "serialNumber": "urn:uuid:21e8d828-b07f-4fd3-bd14-0458f7188d40", - "version": 1, - "metadata": { - "timestamp": "2023-05-16T14:37:58Z", - "component": { - "group": "com.redhat.exhort", - "name": "default-app", - "version": "0.0.1", - "licenses": [], - "purl": "pkg:oci/quay.io/default-app@0.0.1", - "type": "library", - "bom-ref": "pkg:oci/quay.io/default-app@0.0.1" - } + "pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1": { + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "serialNumber": "urn:uuid:21e8d828-b07f-4fd3-bd14-0458f7188d40", + "version": 1, + "metadata": { + "timestamp": "2023-05-16T14:37:58Z", + "component": { + "group": "com.redhat.exhort", + "name": "default-app", + "version": "0.0.1", + "licenses": [], + "purl": "pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1", + "type": "library", + "bom-ref": "pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1" + } + }, + "components": [ + { + "type": "library", + "name": "common", + "group": "@xml-tools", + "version": "0.1.6", + "bom-ref": "@xml-tools/common@0.1.6", + "purl": "pkg:npm/%40xml-tools/common@0.1.6" + } + ], + "dependencies": [ + { + "ref": "pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1", + "dependsOn": [ + "@xml-tools/common@0.1.6" + ] + } + ] }, - "components": [ - { - "type": "library", - "name": "common", - "group": "@xml-tools", - "version": "0.1.6", - "bom-ref": "@xml-tools/common@0.1.6", - "purl": "pkg:npm/%40xml-tools/common@0.1.6" - } - ], - "dependencies": [ - { - "ref": "pkg:oci/quay.io/default-app@0.0.1", - "dependsOn": [ - "@xml-tools/common@0.1.6" - ] - } - ] -} + "pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1": { + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "serialNumber": "urn:uuid:21e8d828-b07f-4fd3-bd14-0458f7188d40", + "version": 1, + "metadata": { + "timestamp": "2023-05-16T14:37:58Z", + "component": { + "group": "com.redhat.exhort", + "name": "default-app", + "version": "0.0.1", + "licenses": [], + "purl": "pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1", + "type": "library", + "bom-ref": "pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1" + } + }, + "components": [ + { + "type": "library", + "name": "common", + "group": "@xml-tools", + "version": "0.1.6", + "bom-ref": "@xml-tools/common@0.1.6", + "purl": "pkg:npm/%40xml-tools/common@0.1.6" + } + ], + "dependencies": [ + { + "ref": "pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1", + "dependsOn": [ + "@xml-tools/common@0.1.6" + ] + } + ] + } } \ No newline at end of file diff --git a/src/test/resources/spdx/batch-sbom.json b/src/test/resources/spdx/batch-sbom.json index cf0f1c66..3eae8cb7 100644 --- a/src/test/resources/spdx/batch-sbom.json +++ b/src/test/resources/spdx/batch-sbom.json @@ -790,113 +790,242 @@ } ] }, - "pkg:oci/quay.io/default-app@0.0.1" : { - "SPDXID": "SPDXRef-DOCUMENT", - "spdxVersion": "SPDX-2.3", - "creationInfo": { - "comment": "Converted from CycloneDX spec version 1.4", - "created": "2023-06-08T11:54:56Z", - "creators": [ - "Tool: @cyclonedx:cyclonedx-npm-1.12.0", - "Tool: @cyclonedx:cyclonedx-library-2.0.0", - "Tool: CycloneToSpdx-0.1.4" + "pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1": { + "SPDXID": "SPDXRef-DOCUMENT", + "spdxVersion": "SPDX-2.3", + "creationInfo": { + "comment": "Converted from CycloneDX spec version 1.4", + "created": "2023-06-08T11:54:56Z", + "creators": [ + "Tool: @cyclonedx:cyclonedx-npm-1.12.0", + "Tool: @cyclonedx:cyclonedx-library-2.0.0", + "Tool: CycloneToSpdx-0.1.4" + ], + "licenseListVersion": "3.21" + }, + "name": "default-app", + "dataLicense": "CC0-1.0", + "annotations": [ + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:extensions={}" + } + ], + "documentNamespace": "https://cyclonedx/bafb80af-ae60-41c4-aab0-fa23ed480dc9_1", + "packages": [ + { + "SPDXID": "SPDXRef-quay-io-default-app-0.0.1", + "annotations": [ + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:componentType=\"APPLICATION\"" + }, + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:properites=[{\"name\":\"cdx:npm:package:path\",\"value\":\"\"}]" + } + ], + "copyrightText": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "Apache-2.0", + "name": "quay.io/default-app", + "originator": "Person: Pavel Odvody", + "primaryPackagePurpose": "APPLICATION", + "versionInfo": "0.0.1" + }, + { + "SPDXID": "SPDXRef--xml-tools-common-0.1.6", + "annotations": [ + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:properites=[{\"name\":\"cdx:npm:package:path\",\"value\":\"node_modules/@xml-tools/common\"}]" + }, + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:componentType=\"LIBRARY\"" + } + ], + "checksums": [ + { + "algorithm": "SHA512", + "checksumValue": "eda55978461c72cd4a23f02c77a28a9eb0787530165d392344c8c6e34029184529e4da5f408bd62c406f32ff392a88f695b4a96a0700111c03cbda8cb1f58674" + } + ], + "copyrightText": "NOASSERTION", + "description": "XML-Tools Common Utilities", + "downloadLocation": "https://registry.npmjs.org/@xml-tools/common/-/common-0.1.6.tgz", + "externalRefs": [ + { + "comment": "as detected from PackageJson property \"bugs.url\"", + "referenceCategory": "OTHER", + "referenceLocator": "https://github.com/sap/xml-tools/issues", + "referenceType": "http://cyclonedx.org/referenctype/issue-tracker" + }, + { + "comment": "as detected from PackageJson property \"repository.url\"", + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "git+https://github.com/sap/xml-tools.git", + "referenceType": "http://cyclonedx.org/referenctype/other-package-manager" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:npm/%40xml-tools/common@0.1.6", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "homepage": "https://github.com/sap/xml-tools#readme", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "Apache-2.0", + "name": "@xml-tools:common", + "primaryPackagePurpose": "LIBRARY", + "versionInfo": "0.1.6" + } ], - "licenseListVersion": "3.21" + "relationships": [ + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBES", + "relatedSpdxElement": "SPDXRef-quay-io-default-app-0.0.1" + } + ] }, - "name": "default-app", - "dataLicense": "CC0-1.0", - "annotations": [ - { - "annotationDate": "2023-07-27T20:07:25Z", - "annotationType": "OTHER", - "annotator": "Tool: CycloneToSpdx", - "comment": "MISSING_CDX_PROPERTY:extensions={}" - } - ], - "documentNamespace": "https://cyclonedx/bafb80af-ae60-41c4-aab0-fa23ed480dc9_1", - "packages": [ - { - "SPDXID": "SPDXRef-quay-io-default-app-0.0.1", - "annotations": [ - { - "annotationDate": "2023-07-27T20:07:25Z", - "annotationType": "OTHER", - "annotator": "Tool: CycloneToSpdx", - "comment": "MISSING_CDX_PROPERTY:componentType=\"APPLICATION\"" - }, - { - "annotationDate": "2023-07-27T20:07:25Z", - "annotationType": "OTHER", - "annotator": "Tool: CycloneToSpdx", - "comment": "MISSING_CDX_PROPERTY:properites=[{\"name\":\"cdx:npm:package:path\",\"value\":\"\"}]" - } - ], - "copyrightText": "NOASSERTION", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "PACKAGE-MANAGER", - "referenceLocator": "pkg:oci/quay.io/default-app@0.0.1", - "referenceType": "purl" - } + "pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1": { + "SPDXID": "SPDXRef-DOCUMENT", + "spdxVersion": "SPDX-2.3", + "creationInfo": { + "comment": "Converted from CycloneDX spec version 1.4", + "created": "2023-06-08T11:54:56Z", + "creators": [ + "Tool: @cyclonedx:cyclonedx-npm-1.12.0", + "Tool: @cyclonedx:cyclonedx-library-2.0.0", + "Tool: CycloneToSpdx-0.1.4" ], - "filesAnalyzed": false, - "licenseConcluded": "NOASSERTION", - "licenseDeclared": "Apache-2.0", - "name": "quay.io/default-app", - "originator": "Person: Pavel Odvody", - "primaryPackagePurpose": "APPLICATION", - "versionInfo": "0.0.1" - }, { - "SPDXID" : "SPDXRef--xml-tools-common-0.1.6", - "annotations" : [ { - "annotationDate" : "2023-07-27T20:07:25Z", - "annotationType" : "OTHER", - "annotator" : "Tool: CycloneToSpdx", - "comment" : "MISSING_CDX_PROPERTY:properites=[{\"name\":\"cdx:npm:package:path\",\"value\":\"node_modules/@xml-tools/common\"}]" - }, { - "annotationDate" : "2023-07-27T20:07:25Z", - "annotationType" : "OTHER", - "annotator" : "Tool: CycloneToSpdx", - "comment" : "MISSING_CDX_PROPERTY:componentType=\"LIBRARY\"" - } ], - "checksums" : [ { - "algorithm" : "SHA512", - "checksumValue" : "eda55978461c72cd4a23f02c77a28a9eb0787530165d392344c8c6e34029184529e4da5f408bd62c406f32ff392a88f695b4a96a0700111c03cbda8cb1f58674" - } ], - "copyrightText" : "NOASSERTION", - "description" : "XML-Tools Common Utilities", - "downloadLocation" : "https://registry.npmjs.org/@xml-tools/common/-/common-0.1.6.tgz", - "externalRefs" : [ { - "comment" : "as detected from PackageJson property \"bugs.url\"", - "referenceCategory" : "OTHER", - "referenceLocator" : "https://github.com/sap/xml-tools/issues", - "referenceType" : "http://cyclonedx.org/referenctype/issue-tracker" - }, { - "comment" : "as detected from PackageJson property \"repository.url\"", - "referenceCategory" : "PACKAGE-MANAGER", - "referenceLocator" : "git+https://github.com/sap/xml-tools.git", - "referenceType" : "http://cyclonedx.org/referenctype/other-package-manager" - }, { - "referenceCategory" : "PACKAGE-MANAGER", - "referenceLocator" : "pkg:npm/%40xml-tools/common@0.1.6", - "referenceType" : "purl" - } ], - "filesAnalyzed" : false, - "homepage" : "https://github.com/sap/xml-tools#readme", - "licenseConcluded" : "NOASSERTION", - "licenseDeclared" : "Apache-2.0", - "name" : "@xml-tools:common", - "primaryPackagePurpose" : "LIBRARY", - "versionInfo" : "0.1.6" - } - ], - "relationships": [ - { - "spdxElementId": "SPDXRef-DOCUMENT", - "relationshipType": "DESCRIBES", - "relatedSpdxElement": "SPDXRef-quay-io-default-app-0.0.1" - } - ] -} + "licenseListVersion": "3.21" + }, + "name": "default-app", + "dataLicense": "CC0-1.0", + "annotations": [ + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:extensions={}" + } + ], + "documentNamespace": "https://cyclonedx/bafb80af-ae60-41c4-aab0-fa23ed480dc9_1", + "packages": [ + { + "SPDXID": "SPDXRef-quay-io-default-app-0.0.1", + "annotations": [ + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:componentType=\"APPLICATION\"" + }, + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:properites=[{\"name\":\"cdx:npm:package:path\",\"value\":\"\"}]" + } + ], + "copyrightText": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "Apache-2.0", + "name": "quay.io/default-app", + "originator": "Person: Pavel Odvody", + "primaryPackagePurpose": "APPLICATION", + "versionInfo": "0.0.1" + }, + { + "SPDXID": "SPDXRef--xml-tools-common-0.1.6", + "annotations": [ + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:properites=[{\"name\":\"cdx:npm:package:path\",\"value\":\"node_modules/@xml-tools/common\"}]" + }, + { + "annotationDate": "2023-07-27T20:07:25Z", + "annotationType": "OTHER", + "annotator": "Tool: CycloneToSpdx", + "comment": "MISSING_CDX_PROPERTY:componentType=\"LIBRARY\"" + } + ], + "checksums": [ + { + "algorithm": "SHA512", + "checksumValue": "eda55978461c72cd4a23f02c77a28a9eb0787530165d392344c8c6e34029184529e4da5f408bd62c406f32ff392a88f695b4a96a0700111c03cbda8cb1f58674" + } + ], + "copyrightText": "NOASSERTION", + "description": "XML-Tools Common Utilities", + "downloadLocation": "https://registry.npmjs.org/@xml-tools/common/-/common-0.1.6.tgz", + "externalRefs": [ + { + "comment": "as detected from PackageJson property \"bugs.url\"", + "referenceCategory": "OTHER", + "referenceLocator": "https://github.com/sap/xml-tools/issues", + "referenceType": "http://cyclonedx.org/referenctype/issue-tracker" + }, + { + "comment": "as detected from PackageJson property \"repository.url\"", + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "git+https://github.com/sap/xml-tools.git", + "referenceType": "http://cyclonedx.org/referenctype/other-package-manager" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:npm/%40xml-tools/common@0.1.6", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "homepage": "https://github.com/sap/xml-tools#readme", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "Apache-2.0", + "name": "@xml-tools:common", + "primaryPackagePurpose": "LIBRARY", + "versionInfo": "0.1.6" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBES", + "relatedSpdxElement": "SPDXRef-quay-io-default-app-0.0.1" + } + ] + } } \ No newline at end of file diff --git a/ui/src/api/report.ts b/ui/src/api/report.ts index f7fe7afd..4db550a2 100644 --- a/ui/src/api/report.ts +++ b/ui/src/api/report.ts @@ -1,4 +1,4 @@ -import { getSignUpLink } from "../utils/utils"; +import {getSignUpLink} from "../utils/utils"; export interface AppData { providerPrivateData?: string[] | null; @@ -8,6 +8,7 @@ export interface AppData { nvdIssueTemplate: string; cveIssueTemplate: string; snykSignup: string; + imageMapping: string; } export interface ReportMap { @@ -185,6 +186,11 @@ export interface Cvss { cvss: string; } +export interface CatalogEntry { + purl: string; + catalogUrl: string; +} + export function hasRemediations(vulnerability: Vulnerability): boolean { if ( vulnerability.remediation && diff --git a/ui/src/components/DockerTabbedLayout.tsx b/ui/src/components/DockerTabbedLayout.tsx index 4d2c37a3..a55ef6ac 100644 --- a/ui/src/components/DockerTabbedLayout.tsx +++ b/ui/src/components/DockerTabbedLayout.tsx @@ -4,7 +4,7 @@ import {SummaryCard} from '../components/SummaryCard'; import {TabbedLayout} from "../components/TabbedLayout"; import {ReportErrorAlert} from '../components/ReportErrorAlert'; import {ReportMap} from '../api/report'; -import {extractDependencyName} from '../utils/utils'; +import {constructImageName} from '../utils/utils'; export const DockerTabbedLayout = ({report}: { report: ReportMap }) => { @@ -23,14 +23,14 @@ export const DockerTabbedLayout = ({report}: { report: ReportMap }) => { return ( {extractDependencyName(key, true)}} // Use the map key as title + title={{constructImageName(key)}} // Use the map key as title aria-label={`${key} source`} > - + diff --git a/ui/src/components/SummaryCard.tsx b/ui/src/components/SummaryCard.tsx index 20740052..200bee6a 100644 --- a/ui/src/components/SummaryCard.tsx +++ b/ui/src/components/SummaryCard.tsx @@ -22,8 +22,11 @@ import {ChartCard} from './ChartCard'; import {getSourceName, getSources, Report} from '../api/report'; import RedhatIcon from "@patternfly/react-icons/dist/esm/icons/redhat-icon"; import SecurityCheckIcon from '../images/security-check.svg'; +import {constructImageName, imageRemediationLink} from '../utils/utils'; +import {useAppContext} from "../App"; -export const SummaryCard = ({report}: { report: Report }) => { +export const SummaryCard = ({report, isReportMap, purl}: { report: Report, isReportMap?: boolean, purl?: string }) => { + const appContext = useAppContext(); return ( @@ -37,7 +40,10 @@ export const SummaryCard = ({report}: { report: Report }) => { <CardHeader> <CardTitle> <DescriptionListTerm style={{fontSize: "large"}}> - Vendor Issues + {isReportMap ? (<>{purl ? constructImageName(purl) : "No Image name"} - Vendor Issues</> + ) : ( + <>Vendor Issues</> + )} </DescriptionListTerm> </CardTitle> </CardHeader> @@ -86,29 +92,46 @@ export const SummaryCard = ({report}: { report: Report }) => { </CardTitle> <CardBody> <DescriptionListDescription> - <List isPlain> - {getSources(report).map((source, index) => { - if (Object.keys(source.report).length > 0) { + {isReportMap ? ( + <List isPlain> + <ListItem> + Switch to UBI 9 for enhanced security and enterprise-grade stability in your containerized + applications, backed by Red Hat's support and compatibility assurance. + </ListItem> + <ListItem> + <a href={purl ? imageRemediationLink(purl, report, appContext.imageMapping) : '###'} + target="_blank" rel="noreferrer"> + <Button variant="primary" size="sm"> + Take me there + </Button> + </a> + </ListItem> + </List> + ) : ( + <List isPlain> + {getSources(report).map((source, index) => { + if (Object.keys(source.report).length > 0) { + return ( + <ListItem> + <Icon isInline status="success"> + <img src={SecurityCheckIcon} alt="Security Check Icon"/> + </Icon> {source.report.summary.remediations} remediations are available from Red Hat + for {source.provider} + </ListItem> + ) + } return ( <ListItem> <Icon isInline status="success"> <img src={SecurityCheckIcon} alt="Security Check Icon"/> - </Icon> {source.report.summary.remediations} remediations are available from Red Hat - for {source.provider} + </Icon>  + There are no available Red Hat remediations for your SBOM at this time for {source.provider} </ListItem> ) + }) } - return ( - <ListItem> - <Icon isInline status="success"> - <img src={SecurityCheckIcon} alt="Security Check Icon"/> - </Icon>  - There are no available Red Hat remediations for your SBOM at this time for {source.provider} - </ListItem> - ) - }) - } - </List> + </List> + )} </DescriptionListDescription> </CardBody> </DescriptionListGroup> diff --git a/ui/src/mocks/reportDocker.mock.ts b/ui/src/mocks/reportDocker.mock.ts index 2cdd6e29..36e2e416 100644 --- a/ui/src/mocks/reportDocker.mock.ts +++ b/ui/src/mocks/reportDocker.mock.ts @@ -1,9 +1,9 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const dockerReport: AppData = { providerPrivateData: null, report: { - "pkg:maven/org.acme.dbaas/postgresql-orm-quarkus@1.0.0-SNAPSHOT?type=jar": { + "pkg:oci/test-repository@sha256:333224a233db31852ac1085c6cd702016ab8aaf54cecde5c4bed5451d636adcf?repository_url=test.io/test-namespace/test-repository&tag=test-tag&os=linux&arch=amd64": { "scanned": { "total": 10, "direct": 3, @@ -34,7 +34,7 @@ export const dockerReport: AppData = { }, "dependencies": [ { - "ref": "pkg:maven/io.quarkus/quarkus-hibernate-orm@2.13.5.Final?type=jar", + "ref": "pkg:oci/test-repository@sha256%3A333224a233db31852ac1085c6cd702016ab8aaf54cecde5c4bed5451d636adcf?arch=amd64&os=linux&repository_url=test.io%2Ftest-namespace%2Ftest-repository&tag=test-tag ", "transitive": [ { "ref": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.1?type=jar", @@ -144,7 +144,7 @@ export const dockerReport: AppData = { } } ], - "recommendation": "pkg:maven/io.quarkus/quarkus-hibernate-orm@2.13.8.Final-redhat-00006?repository_url=https%3A%2F%2Fmaven.repository.redhat.com%2Fga%2F&type=jar", + "recommendation": "pkg:oci/ubi@sha256%3Af5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?arch=amd64&repository_url=registry.access.redhat.com%2Fubi9%2Fubi&tag=9.3-1552", "highestVulnerability": { "id": "CVE-2020-36518", "title": "[CVE-2020-36518] CWE-787: Out-of-bounds Write", @@ -177,7 +177,7 @@ export const dockerReport: AppData = { }, { "ref": "pkg:maven/io.quarkus/quarkus-jdbc-postgresql@2.13.5.Final?type=jar", - "recommendation": "pkg:maven/io.quarkus/quarkus-jdbc-postgresql@2.13.8.Final-redhat-00006?repository_url=https%3A%2F%2Fmaven.repository.redhat.com%2Fga%2F&type=jar" + "recommendation": "pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64" } ] } @@ -843,7 +843,7 @@ export const dockerReport: AppData = { } } }, - "pkg:oci/quay.io/default-app@0.0.1": { + "pkg:oci/default-app@sha256:333224a233db31852ac1085c6cd702016ab8aaf54cecde5c4bed5451d636adcf?repository_url=quay.io/default-app&tag=0.0.1": { "scanned": { "total": 2, "direct": 2, @@ -890,8 +890,8 @@ export const dockerReport: AppData = { }, "dependencies": [ { - "ref": "pkg:oci/quay.io/default-app@0.0.1", - "recommendation": "pkg:oci/quay.io/test-app@0.0.2" + "ref": "pkg:oci/default-app@sha256%3A333224a233db31852ac1085c6cd702016ab8aaf54cecde5c4bed5451d636adcf?repository_url=quay.io%2Fdefault-app&tag=0.0.1", + "recommendation": "pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64" } ] } @@ -941,5 +941,15 @@ export const dockerReport: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/mocks/reportMixed.mock.ts b/ui/src/mocks/reportMixed.mock.ts index 2d64dcc5..4a4ef526 100644 --- a/ui/src/mocks/reportMixed.mock.ts +++ b/ui/src/mocks/reportMixed.mock.ts @@ -1,4 +1,4 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const reportMixed: AppData = { providerPrivateData: null, @@ -7223,5 +7223,15 @@ export const reportMixed: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/mocks/reportWithError.mock.ts b/ui/src/mocks/reportWithError.mock.ts index 62a73948..73975f0e 100644 --- a/ui/src/mocks/reportWithError.mock.ts +++ b/ui/src/mocks/reportWithError.mock.ts @@ -1,4 +1,4 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const errorReport: AppData = { providerPrivateData: null , @@ -31,5 +31,15 @@ export const errorReport: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/mocks/reportWithForbidden.mock.ts b/ui/src/mocks/reportWithForbidden.mock.ts index eebca1f1..5277f99f 100644 --- a/ui/src/mocks/reportWithForbidden.mock.ts +++ b/ui/src/mocks/reportWithForbidden.mock.ts @@ -1,4 +1,4 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const forbiddenReport: AppData = { providerPrivateData: null, @@ -31,5 +31,15 @@ export const forbiddenReport: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/mocks/reportWithToken.mock.ts b/ui/src/mocks/reportWithToken.mock.ts index 18fee911..22a48be3 100644 --- a/ui/src/mocks/reportWithToken.mock.ts +++ b/ui/src/mocks/reportWithToken.mock.ts @@ -1,4 +1,4 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const withTokenReport: AppData = { providerPrivateData: null, @@ -438,5 +438,15 @@ export const withTokenReport: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/mocks/reportWithUnauthenticated.mock.ts b/ui/src/mocks/reportWithUnauthenticated.mock.ts index ff13352c..a1a00625 100644 --- a/ui/src/mocks/reportWithUnauthenticated.mock.ts +++ b/ui/src/mocks/reportWithUnauthenticated.mock.ts @@ -1,4 +1,4 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const unauthenticatedReport: AppData = { providerPrivateData: null, @@ -300,5 +300,15 @@ export const unauthenticatedReport: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/mocks/reportWithUnauthorized.mock.ts b/ui/src/mocks/reportWithUnauthorized.mock.ts index d8c87128..0885e88f 100644 --- a/ui/src/mocks/reportWithUnauthorized.mock.ts +++ b/ui/src/mocks/reportWithUnauthorized.mock.ts @@ -1,4 +1,4 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const unauthorizedReport: AppData = { providerPrivateData: null, @@ -31,5 +31,15 @@ export const unauthorizedReport: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/mocks/reportWithoutToken.mock.ts b/ui/src/mocks/reportWithoutToken.mock.ts index d3438a18..f769662e 100644 --- a/ui/src/mocks/reportWithoutToken.mock.ts +++ b/ui/src/mocks/reportWithoutToken.mock.ts @@ -1,4 +1,4 @@ -import { AppData } from '@app/api/report'; +import {AppData} from '@app/api/report'; export const withoutTokenReport: AppData = { providerPrivateData: ['snyk'], @@ -386,5 +386,15 @@ export const withoutTokenReport: AppData = { snykIssueTemplate: 'https://security.snyk.io/vuln/__ISSUE_ID__', nvdIssueTemplate: 'https://nvd.nist.gov/vuln/detail/__ISSUE_ID__', snykSignup: 'https://app.snyk.io/login', - cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__' + cveIssueTemplate: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=__ISSUE_ID__', + imageMapping: "[\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi@sha256:f5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?repository_url=registry.access.redhat.com/ubi9/ubi&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi/615bcf606feffc5384e8452e?architecture=amd64&image=65a82982a10f3e68777870b5\"\n" + + " },\n" + + " {\n" + + " \"purl\": \"pkg:oci/ubi-minimal@sha256:06d06f15f7b641a78f2512c8817cbecaa1bf549488e273f5ac27ff1654ed33f0?repository_url=registry.access.redhat.com/ubi9/ubi-minimal&tag=9.3-1552&arch=amd64\",\n" + + " \"catalogUrl\": \"https://catalog.redhat.com/software/containers/ubi9/ubi-minimal/615bd9b4075b022acc111bf5?architecture=amd64&image=65a828e3cda4984705d45d26\"\n" + + " }\n" + + "]" }; diff --git a/ui/src/utils/utils.ts b/ui/src/utils/utils.ts index 6e09fce7..1d1bb562 100644 --- a/ui/src/utils/utils.ts +++ b/ui/src/utils/utils.ts @@ -1,4 +1,4 @@ -import { AppData, ProviderStatus } from "../api/report"; +import {AppData, CatalogEntry, getSources, ProviderStatus, Report} from "../api/report"; const MAVEN_TYPE = 'maven'; const MAVEN_URL = 'https://central.sonatype.com/artifact/'; @@ -22,6 +22,8 @@ const OSS_SIGN_UP_LINK = 'https://ossindex.sonatype.org/user/register'; const REDHAT_REPOSITORY = 'https://maven.repository.redhat.com/ga/'; +const REHAT_IMAGES_CATALOG = 'https://catalog.redhat.com/software/containers/'; + export const getSignUpLink = (provider: string): string => { switch(provider) { case 'oss-index': return OSS_SIGN_UP_LINK; @@ -82,7 +84,7 @@ export const extractDependencyUrl = (name: string) => { const version = pkgUrl.version; if(version?.match(/v\d\.\d.\d-\d{14}-\w{12}/)) { //pseudo-version return `${GOLANG_URL}${pkgUrl.namespace}/${pkgUrl.name}`; - } + } return `${GOLANG_URL}${pkgUrl.namespace}/${pkgUrl.name}@${pkgUrl.version}`; case NPM_TYPE: if(pkgUrl.namespace) { @@ -122,6 +124,76 @@ export const uppercaseFirstLetter = (val: string) => { return val.toLowerCase().replace(/./, (c) => c.toUpperCase()); }; +export const constructImageName = (purl: string): string => { + const purlObj = parsePurl(purl); + let imageName = ''; + if (purlObj.repository_url) { + const indexOfFirstSlash = purlObj.repository_url.indexOf("/"); + const parsedRepoUrl = indexOfFirstSlash !== -1 ? purlObj.repository_url.substring(indexOfFirstSlash + 1) : ""; + imageName += parsedRepoUrl; + } else { + imageName += `${purlObj.short_name}`; + } + if (purlObj.tag) { + imageName += `:${purlObj.tag}`; + } + return imageName; +} + +const parsePurl = (purl: string) =>{ + const parts = purl.split('?'); + const nameVersion = parts[0]; + const queryParams = parts[1]; + const query = new URLSearchParams(queryParams); + + const repository_url = query.get('repository_url') || ''; + const tag = query.get('tag') || ''; + const arch = query.get('arch') || ''; + const atIndex = nameVersion.split("@"); + const short_name = atIndex[0].substring(atIndex[0].indexOf("/") + 1); + // Extract version and replace "%" with ":" + const version = nameVersion.substring(nameVersion.lastIndexOf("@")).replace("%3A", ":"); + + return { repository_url, tag, short_name, version, arch }; +} + +export const imageRemediationLink = (purl: string, report: Report, imageMapping: string) => { + const sources = getSources(report); + let result = REHAT_IMAGES_CATALOG; + + for (const key in sources) { + const source = sources[key]; + const dependencies = source.report.dependencies; + if (dependencies) { + // Find the Dependency with matching ref to the provided purl + const matchingDependency = Object.values(dependencies).find(dependency => { + const originalRef = dependency.ref; + const transformedRef = decodeURIComponent(originalRef); + + return PackageURL.fromString(transformedRef).toString() === PackageURL.fromString(purl).toString(); + }); + + if (matchingDependency && matchingDependency.recommendation ) { + const transformedRecommUrl = decodeURIComponent(matchingDependency.recommendation); + const catalogUrl = getCatalogUrlByPurl(transformedRecommUrl, imageMapping); + + if (catalogUrl !== undefined) { + return catalogUrl; + } + } + } + } + return result + "search"; +}; + +const getCatalogUrlByPurl = (recommendPurl: string, imageMapping: string): string | undefined => { + const catalogEntries: CatalogEntry[] = JSON.parse(imageMapping); + // Find the matching entry + const matchingEntry = catalogEntries.find(entry => PackageURL.fromString(entry.purl).toString() === PackageURL.fromString(recommendPurl).toString()); + + return matchingEntry?.catalogUrl; +}; + class PackageURL { readonly type: string;