Skip to content

Commit

Permalink
Merge pull request #939 from hmrc/BDOG-3186c
Browse files Browse the repository at this point in the history
BDOG-3186: Clarify service vulnerabilities
  • Loading branch information
Stegi56 committed Aug 16, 2024
2 parents bb6f6bd + 2f6021d commit 503860c
Show file tree
Hide file tree
Showing 17 changed files with 137 additions and 92 deletions.
73 changes: 40 additions & 33 deletions app/uk/gov/hmrc/cataloguefrontend/CatalogueController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
package uk.gov.hmrc.cataloguefrontend

import cats.data.{EitherT, OptionT}
import cats.implicits._
import cats.implicits.*
import play.api.data.{Form, Forms}
import play.api.i18n.I18nSupport
import play.api.mvc._
import play.api.mvc.*
import play.api.{Configuration, Logger}
import play.api.data.validation.{Constraint, Invalid, Valid}
import play.twirl.api.Html
import uk.gov.hmrc.cataloguefrontend.auth.{AuthController, CatalogueAuthBuilders}
import uk.gov.hmrc.cataloguefrontend.connector.BuildDeployApiConnector.PrototypeStatus
import uk.gov.hmrc.cataloguefrontend.connector._
import uk.gov.hmrc.cataloguefrontend.connector.*
import uk.gov.hmrc.cataloguefrontend.connector.model.RepositoryModules
import uk.gov.hmrc.cataloguefrontend.cost.{CostEstimateConfig, CostEstimationService, Zone}
import uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionService
Expand All @@ -37,8 +37,8 @@ import uk.gov.hmrc.cataloguefrontend.serviceconfigs.{ServiceConfigsConnector, Se
import uk.gov.hmrc.cataloguefrontend.shuttering.{ShutterService, ShutterState, ShutterType}
import uk.gov.hmrc.cataloguefrontend.util.TelemetryLinks
import uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.{LifecycleStatus, ServiceCommissioningStatusConnector}
import uk.gov.hmrc.cataloguefrontend.vulnerabilities.VulnerabilitiesConnector
import uk.gov.hmrc.cataloguefrontend.whatsrunningwhere.{WhatsRunningWhereService}
import uk.gov.hmrc.cataloguefrontend.vulnerabilities.{TotalVulnerabilityCount, VulnerabilitiesConnector, VulnerabilitySummary, CurationStatus}
import uk.gov.hmrc.cataloguefrontend.whatsrunningwhere.WhatsRunningWhereService
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.internalauth.client.{FrontendAuthComponents, IAAction, Predicate, Resource, Retrieval}
import uk.gov.hmrc.internalauth.client.Predicate.Permission
Expand All @@ -49,11 +49,12 @@ import javax.inject.{Inject, Singleton}
import scala.concurrent.{ExecutionContext, Future}

case class EnvData(
version : Version,
repoModules : Option[RepositoryModules],
shutterStates : Seq[ShutterState],
telemetryLinks : Seq[Link],
nonPerformantQueryLinks: Seq[Link],
version : Version,
repoModules : Option[RepositoryModules],
shutterStates : Seq[ShutterState],
telemetryLinks : Seq[Link],
nonPerformantQueryLinks : Seq[Link],
actionReqVulnerabilityCount: Int
)

@Singleton
Expand Down Expand Up @@ -168,22 +169,26 @@ class CatalogueController @Inject() (
deployedVersions.sorted.headOption match
case Some(version) =>
for
repoModules <- serviceDependenciesConnector.getRepositoryModules(repositoryName, version)
shutterStates <- ShutterType.values.toSeq.foldLeftM[Future, Seq[ShutterState]](Seq.empty): (acc, shutterType) =>
shutterService
.getShutterStates(shutterType, env, Some(serviceName))
.map(acc ++ _)
data = EnvData(
version = version,
repoModules = repoModules.headOption,
shutterStates = shutterStates,
telemetryLinks = Seq(
telemetryLinks.grafanaDashboard(env, serviceName),
telemetryLinks.kibanaDashboard(env, serviceName)
),
nonPerformantQueryLinks = database.fold(Seq[uk.gov.hmrc.cataloguefrontend.connector.Link]()): databaseName =>
telemetryLinks.kibanaNonPerformantQueries(env, serviceName, databaseName, nonPerformantQueries)
)
repoModules <- serviceDependenciesConnector.getRepositoryModules(repositoryName, version)
shutterStates <- ShutterType.values.toSeq.foldLeftM[Future, Seq[ShutterState]](Seq.empty): (acc, shutterType) =>
shutterService
.getShutterStates(shutterType, env, Some(serviceName))
.map(acc ++ _)
vulnerabilitiesCount <- vulnerabilitiesConnector
.vulnerabilityCounts(flag = SlugInfoFlag.ForEnvironment(env), serviceName = Some(serviceName))
.map(_.headOption) // should only return one result for defined serviceName
data = EnvData(
version = version,
repoModules = repoModules.headOption,
shutterStates = shutterStates,
telemetryLinks = Seq(
telemetryLinks.grafanaDashboard(env, serviceName),
telemetryLinks.kibanaDashboard(env, serviceName)
),
nonPerformantQueryLinks = database.fold(Seq[uk.gov.hmrc.cataloguefrontend.connector.Link]()): databaseName =>
telemetryLinks.kibanaNonPerformantQueries(env, serviceName, databaseName, nonPerformantQueries),
actionReqVulnerabilityCount = vulnerabilitiesCount.fold(0)(_.actionRequired)
)
yield Some((SlugInfoFlag.ForEnvironment(env): SlugInfoFlag) -> data)
case None =>
Future.successful(None)
Expand All @@ -194,17 +199,20 @@ class CatalogueController @Inject() (
optLatestServiceInfo <- serviceDependenciesConnector.getSlugInfo(serviceName)
serviceCostEstimate <- costEstimationService.estimateServiceCost(serviceName)
commenterReport <- prCommenterConnector.report(repositoryName)
vulnerabilitiesCount <- vulnerabilitiesConnector.deployedVulnerabilityCount(serviceName)
latestVulnerabilitiesCount<- vulnerabilitiesConnector
.vulnerabilityCounts(flag = SlugInfoFlag.Latest, serviceName=Some(serviceName))
.map(_.headOption)
serviceRelationships <- serviceConfigsService.serviceRelationships(serviceName)
zone <- retrieveZone(serviceName)
optLatestData = optLatestServiceInfo.map: latestServiceInfo =>
SlugInfoFlag.Latest ->
EnvData(
version = latestServiceInfo.version,
repoModules = latestRepoModules,
shutterStates = Seq.empty,
telemetryLinks = Seq.empty,
nonPerformantQueryLinks = Seq.empty,
version = latestServiceInfo.version,
repoModules = latestRepoModules,
shutterStates = Seq.empty,
telemetryLinks = Seq.empty,
nonPerformantQueryLinks = Seq.empty,
actionReqVulnerabilityCount = latestVulnerabilitiesCount.fold(0)(_.actionRequired)
)
canMarkForDecommissioning <- hasMarkForDecommissioningAuthorisation(repositoryName)
lifecycle <- serviceCommissioningStatusConnector.getLifecycle(serviceName)
Expand All @@ -221,7 +229,6 @@ class CatalogueController @Inject() (
serviceRoutes = serviceRoutes,
hasBranchProtectionAuth = hasBranchProtectionAuth,
commenterReport = commenterReport,
distinctVulnerabilitiesCount = vulnerabilitiesCount.map(_.actionRequired),
serviceRelationships = serviceRelationships,
canMarkForDecommissioning = canMarkForDecommissioning,
lifecycle = lifecycle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ case class Dependency(
currentVersion : Version,
latestVersion : Option[Version],
bobbyRuleViolations: Seq[BobbyRuleViolation] = Seq.empty,
vulnerabilityIds : Seq[String] = Seq.empty,
importBy : Option[ImportedBy] = None,
scope : DependencyScope
):
Expand Down Expand Up @@ -127,6 +128,7 @@ object Dependency:
~ (__ \ "currentVersion" ).read[Version]
~ (__ \ "latestVersion" ).readNullable[Version]
~ (__ \ "bobbyRuleViolations").read[Seq[BobbyRuleViolation]]
~ (__ \ "vulnerabilities" ).read[Seq[String]]
~ (__ \ "importBy" ).readNullable[ImportedBy]
~ (__ \ "scope" ).read[DependencyScope]
)(Dependency.apply)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ <h1 class="page-heading mt-4">
</div>

<div class="col-md-6">
@partials.code(serviceName = None, library, hasBranchProtectionAuth, commenterReport, None)
@partials.code(serviceName = None, library, hasBranchProtectionAuth, commenterReport)
</div>

<div class="col-md-6">
@partials.build(library, hasBranchProtectionAuth, commenterReport)
</div>

<div class="col-md-6">
@partials.dependency_legend(showNewVersionAvailable = true)
@partials.dependency_legend(showNewVersionAvailable = true, showVulnerabilitity = false)
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ <h1 class="page-heading mt-4">
</div>

<div class="col-md-6">
@partials.code(serviceName = None, prototype, hasBranchProtectionAuth, commenterReport, None)
@partials.code(serviceName = None, prototype, hasBranchProtectionAuth, commenterReport)
</div>
</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ <h1 class="page-heading mt-4">
@partials.repo_owning_teams(repository)
</div>
<div class="col-md-6">
@partials.code(serviceName = None, repository, hasBranchProtectionAuth, commenterReport, None)
@partials.code(serviceName = None, repository, hasBranchProtectionAuth, commenterReport)
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
serviceRoutes : ServiceRoutes,
hasBranchProtectionAuth : EnableBranchProtection.HasAuthorisation,
commenterReport : Option[PrCommenterReport],
distinctVulnerabilitiesCount : Option[Int],
serviceRelationships : ServiceConfigsService.ServiceRelationshipsEnriched,
canMarkForDecommissioning : MarkForDecommissioning.HasAuthorisation,
lifecycle : Option[Lifecycle],
Expand Down Expand Up @@ -124,7 +123,7 @@ <h1 id="service-header" class="page-heading mt-4 position-relative">
</div>

<div class="col-md-6 mb-3">
@partials.code(Some(serviceName), repositoryDetails, hasBranchProtectionAuth, commenterReport, distinctVulnerabilitiesCount)
@partials.code(Some(serviceName), repositoryDetails, hasBranchProtectionAuth, commenterReport)
</div>
<div class="col-md-6 mb-3">
@partials.service_relationships(serviceRelationships)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ <h1 class="page-heading mt-4">
}
</div>
<div class="col-md-6">
@partials.code(serviceName = None, repository, hasBranchProtectionAuth, commenterReport, None)
@partials.code(serviceName = None, repository, hasBranchProtectionAuth, commenterReport)
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

@import uk.gov.hmrc.cataloguefrontend.EnvData
@import uk.gov.hmrc.cataloguefrontend.connector.Link
@import uk.gov.hmrc.cataloguefrontend.vulnerabilities.TotalVulnerabilityCount
@import uk.gov.hmrc.cataloguefrontend.connector.model.{Dependency, DependencyScope}
@import uk.gov.hmrc.cataloguefrontend.shuttering.{ShutterState, ShutterStatusValue}

Expand All @@ -27,7 +28,8 @@
serviceName: ServiceName,
envDatas : Map[SlugInfoFlag, EnvData]
)(implicit
messages : Messages
request : RequestHeader,
messages: Messages
)


Expand Down Expand Up @@ -56,7 +58,7 @@
<span>
@renderShutterStatusBadge(optEnvData.fold(Seq.empty[uk.gov.hmrc.cataloguefrontend.shuttering.ShutterState])(_.shutterStates))
@defining(optEnvData.toSeq.flatMap(_.repoModules).flatMap(_.allDependencies)) { dependencies =>
@renderActiveBobbyRuleViolationBadge(slugInfoFlag, dependencies)
@renderViolationBadge(slugInfoFlag, dependencies, optEnvData.fold(0)(_.actionReqVulnerabilityCount))
@renderPendingBobbyRuleViolationBadge(slugInfoFlag, dependencies)
}
</span>
Expand Down Expand Up @@ -94,15 +96,18 @@
}

@defining(optEnvData.toSeq.flatMap(_.repoModules).flatMap(_.allDependencies)){ dependencies =>

<div class="row">
<div class="col-md-12">
@dependenciesPartial(
dependencies.filter(_.scope == DependencyScope.Compile)
, s"platform-dependencies-${slugInfoFlag.asString}"
, "Compile Dependencies"
, optEnvData.map(envData => (serviceName, envData.version))
)
@{
dependenciesPartial(
dependencies.filter(_.scope == DependencyScope.Compile)
, s"platform-dependencies-${slugInfoFlag.asString}"
, "Compile Dependencies"
, optEnvData.map(envData => (serviceName, envData.version))
, false
, true
)
}
</div>
</div>

Expand Down Expand Up @@ -172,19 +177,33 @@
}
}

@renderActiveBobbyRuleViolationBadge(slugInfoFlag: SlugInfoFlag, dependencies: Seq[Dependency]) = {
@if(dependencies.exists(_.activeBobbyRuleViolations.nonEmpty)) {
<span id="bobby-violation-active-badge-@{slugInfoFlag.asString}" class="environment-badge bobby-violation-active-badge"
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="@messages("bobbyrules.active.badge")"></span>
@renderViolationBadge(slugInfoFlag: SlugInfoFlag, dependencies: Seq[Dependency], vulnerabilitiesCount: Int) = {
@if(dependencies.exists(_.activeBobbyRuleViolations.nonEmpty) || vulnerabilitiesCount != 0) {
<span id="violation-active-badge-@{slugInfoFlag.asString}" class="environment-badge bobby-violation-active-badge text-black"
data-bs-toggle="tooltip" data-bs-placement="top"
data-bs-title="@{
val bobbyViolations = if(dependencies.exists(_.activeBobbyRuleViolations.nonEmpty)) {
s"${messages("bobbyrules.active.badge")}: ${dependencies.map(_.activeBobbyRuleViolations.size).sum}"
} else {
""
}
val vulnerabilities = if(vulnerabilitiesCount != 0) {
s"Vulnerabilities: $vulnerabilitiesCount"
} else {
""
}
Seq(bobbyViolations, vulnerabilities).filter(_.nonEmpty).mkString("\n")
}"
></span>
} else {
<span id="bobby-violation-active-badge-@{slugInfoFlag.asString}" class="environment-badge no-badge"></span>
<span id="violation-active-badge-@{slugInfoFlag.asString}" class="environment-badge no-badge"></span>
}
}

@renderPendingBobbyRuleViolationBadge(slugInfoFlag: SlugInfoFlag, dependencies: Seq[Dependency]) = {
@if(dependencies.exists(_.pendingBobbyRuleViolations.nonEmpty)) {
<span id="bobby-violation-pending-badge-@{slugInfoFlag.asString}" class="environment-badge bobby-violation-pending-badge"
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="@messages("bobbyrules.pending.badge")"></span>
<span id="bobby-violation-pending-badge-@{slugInfoFlag.asString}" class="environment-badge bobby-violation-pending-badge text-black"
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="@messages("bobbyrules.pending.badge"): @dependencies.map(_.pendingBobbyRuleViolations.size).sum"></span>
} else {
<span id="bobby-violation-pending-badge-@{slugInfoFlag.asString}" class="environment-badge no-badge"></span>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,27 @@
<div class="col-4">
<p class="fw-bold">Libraries</p>
</div>
<div class="col-3">
<div class="col-2">
<p class="fw-bold">Current Version</p>
</div>
<div class="col-3">
<div class="col-2">
<p class="fw-bold">Latest Version</p>
</div>
<div class="col-2">
<p class="fw-bold">Vulnerability</p>
</div>
<div class="col-2">
<p class="fw-bold">Violation</p>
</div>
</div>
@partials.dependency_section(dependencies, rootId)
@partials.dependency_section(dependencies, rootId, false)
} else {
<p class="card-text dependency-row">No dependencies available</p>
}
</div>
@if(dependencies.nonEmpty && showLegend) {
<div class="col-3">
@partials.dependency_legend(showNewVersionAvailable = true)
@partials.dependency_legend(showNewVersionAvailable = true, showVulnerabilitity = true)
</div>
}
</div>
Expand Down
Loading

0 comments on commit 503860c

Please sign in to comment.