diff --git a/admin/src/main/scala/com/neu/api/device/DeviceApi.scala b/admin/src/main/scala/com/neu/api/device/DeviceApi.scala index 9f4601b34..09ad8e284 100644 --- a/admin/src/main/scala/com/neu/api/device/DeviceApi.scala +++ b/admin/src/main/scala/com/neu/api/device/DeviceApi.scala @@ -277,7 +277,7 @@ class DeviceApi(resourceService: DeviceService) extends BaseApi { path("check") { get { Utils.respondWithWebServerHeaders() { - resourceService.checkDebugLog() + resourceService.checkDebugLog(tokenId) } } } diff --git a/admin/src/main/scala/com/neu/api/notification/NotificationApi.scala b/admin/src/main/scala/com/neu/api/notification/NotificationApi.scala index e1e5af83c..7961b9a12 100644 --- a/admin/src/main/scala/com/neu/api/notification/NotificationApi.scala +++ b/admin/src/main/scala/com/neu/api/notification/NotificationApi.scala @@ -179,7 +179,7 @@ class NotificationApi(resourceService: NotificationService) extends BaseApi { post { entity(as[UserGraphLayout]) { (graphLayout: UserGraphLayout) => Utils.respondWithWebServerHeaders() { - resourceService.createNetworkGraph(graphLayout) + resourceService.createNetworkGraph(graphLayout, tokenId) } } } @@ -188,7 +188,7 @@ class NotificationApi(resourceService: NotificationService) extends BaseApi { get { parameter(Symbol("user")) { user => Utils.respondWithWebServerHeaders() { - resourceService.getNetworkGraphLayout(user) + resourceService.getNetworkGraphLayout(user, tokenId) } } } @@ -197,14 +197,14 @@ class NotificationApi(resourceService: NotificationService) extends BaseApi { get { parameter(Symbol("user")) { user => Utils.respondWithWebServerHeaders() { - resourceService.getNetworkGraphBlacklist(user) + resourceService.getNetworkGraphBlacklist(user, tokenId) } } } ~ post { entity(as[UserBlacklist]) { (userBlacklist: UserBlacklist) => Utils.respondWithWebServerHeaders() { - resourceService.createNetworkGraphBlacklist(userBlacklist) + resourceService.createNetworkGraphBlacklist(userBlacklist, tokenId) } } } diff --git a/admin/src/main/scala/com/neu/api/risk/RiskApi.scala b/admin/src/main/scala/com/neu/api/risk/RiskApi.scala index b16cc278e..524828ca4 100644 --- a/admin/src/main/scala/com/neu/api/risk/RiskApi.scala +++ b/admin/src/main/scala/com/neu/api/risk/RiskApi.scala @@ -204,7 +204,7 @@ class RiskApi(resourceService: RiskService) extends BaseApi { path("complianceNIST") { post { entity(as[ComplianceNISTConfigData]) { complianceNISTConfigData => - resourceService.queryNistCompliances(complianceNISTConfigData) + resourceService.queryNistCompliances(complianceNISTConfigData, tokenId) } } } ~ diff --git a/admin/src/main/scala/com/neu/core/AuthenticationManager.scala b/admin/src/main/scala/com/neu/core/AuthenticationManager.scala index f7e83d7c0..c5936873e 100644 --- a/admin/src/main/scala/com/neu/core/AuthenticationManager.scala +++ b/admin/src/main/scala/com/neu/core/AuthenticationManager.scala @@ -9,6 +9,10 @@ import com.typesafe.scalalogging.LazyLogging import java.security.MessageDigest import java.text.SimpleDateFormat import scala.collection.mutable +import com.neu.client.RestClient +import com.neu.client.RestClient.* +import org.apache.pekko.http.scaladsl.model.* +import scala.concurrent.Future /** * Created by bxu on 3/25/16. @@ -109,6 +113,14 @@ object AuthenticationManager extends LazyLogging { def putToken(id: String, userToken: UserTokenNew): Unit = tokenMap += id -> userToken + def validateToken(tokenId: String): Future[HttpResponse] = + RestClient.httpRequestWithHeader( + s"${baseClusterUri(tokenId)}/$auth", + HttpMethods.PATCH, + "", + tokenId + ) + private def getRolesDigit( global_role: String, role_domains: Option[Map[String, Array[String]]] diff --git a/admin/src/main/scala/com/neu/service/authentication/SuseAuthService.scala b/admin/src/main/scala/com/neu/service/authentication/SuseAuthService.scala index 765a05ff0..57ccf3225 100644 --- a/admin/src/main/scala/com/neu/service/authentication/SuseAuthService.scala +++ b/admin/src/main/scala/com/neu/service/authentication/SuseAuthService.scala @@ -39,12 +39,7 @@ class SuseAuthService()(implicit override def validateToken(tokenId: Option[String], ip: Option[RemoteAddress]): Route = complete { - RestClient.httpRequestWithHeader( - s"${baseClusterUri(tokenId.get)}/$auth", - HttpMethods.PATCH, - "", - tokenId.get - ) + AuthenticationManager.validateToken(tokenId.get) } override def login(ip: RemoteAddress, host: String, ctx: RequestContext): Route = { diff --git a/admin/src/main/scala/com/neu/service/device/DeviceService.scala b/admin/src/main/scala/com/neu/service/device/DeviceService.scala index 6119abbf5..8f1b0ba8a 100644 --- a/admin/src/main/scala/com/neu/service/device/DeviceService.scala +++ b/admin/src/main/scala/com/neu/service/device/DeviceService.scala @@ -629,15 +629,31 @@ class DeviceService extends Directives with DefaultJsonFormats with LazyLogging } } - def checkDebugLog(): Route = complete { - val isFileReady = Files.exists(Paths.get(logFile)) && Files.isReadable( - Paths.get(logFile) - ) - logger.info(s"Log file $logFile is ready: $isFileReady") - if (isFileReady) { - HttpResponse(StatusCodes.OK, entity = "Ready") - } else { - HttpResponse(StatusCodes.PartialContent, entity = "In progress") + def checkDebugLog(tokenId: String): Route = complete { + try { + val resultPromise = AuthenticationManager.validateToken(tokenId) + Await.result(resultPromise, RestClient.waitingLimit.seconds) + if (SupportLogAuthCacheManager.getSupportLogAuth(tokenId).isDefined) { + val isFileReady = Files.exists(Paths.get(logFile)) && Files.isReadable( + Paths.get(logFile) + ) + logger.info(s"Log file $logFile is ready: $isFileReady") + if (isFileReady) { + HttpResponse(StatusCodes.OK, entity = "Ready") + } else { + HttpResponse(StatusCodes.PartialContent, entity = "In progress") + } + } else { + (StatusCodes.Forbidden, "File can not be accessed.") + } + } catch { + case NonFatal(e) => + RestClient.handleError( + timeOutStatus, + authenticationFailedStatus, + serverErrorStatus, + e + ) } } diff --git a/admin/src/main/scala/com/neu/service/notification/NotificationService.scala b/admin/src/main/scala/com/neu/service/notification/NotificationService.scala index 02a1ec6c6..e0794b44a 100644 --- a/admin/src/main/scala/com/neu/service/notification/NotificationService.scala +++ b/admin/src/main/scala/com/neu/service/notification/NotificationService.scala @@ -5,6 +5,7 @@ import com.neu.cache.GraphCacheManager import com.neu.cache.paginationCacheManager import com.neu.client.RestClient import com.neu.client.RestClient.* +import com.neu.core.AuthenticationManager import com.neu.core.IpGeoManager import com.neu.model.AlertJsonProtocol.{ *, given } import com.neu.model.DashboardJsonProtocol.{ *, given } @@ -16,10 +17,9 @@ import com.neu.model.* import com.neu.service.BaseService import com.neu.utils.EnumUtils import com.typesafe.scalalogging.LazyLogging -import org.apache.pekko.http.scaladsl.model.HttpEntity import org.apache.pekko.http.scaladsl.model.HttpMethods.* -import org.apache.pekko.http.scaladsl.model.StatusCodes import org.apache.pekko.http.scaladsl.server.Route +import org.apache.pekko.http.scaladsl.model.* import org.joda.time.DateTime import org.json4s.* import org.json4s.native.JsonMethods.* @@ -39,8 +39,9 @@ class NotificationService()(implicit with DefaultJsonFormats with LazyLogging { - val topLimit = 5 - val client = "client" + final val serverErrorStatus = "Status: 503" + val topLimit = 5 + val client = "client" def getIpLocations(ipList: Array[String]): Route = complete { logger.info("Getting ip locations") @@ -162,27 +163,39 @@ class NotificationService()(implicit } if (start.isDefined && limit.isDefined) { - if (elements == null) { - elements = paginationCacheManager[List[org.json4s.JsonAST.JValue]] + try { + val resultPromise = AuthenticationManager.validateToken(tokenId) + Await.result(resultPromise, RestClient.waitingLimit.seconds) + if (elements == null) { + elements = paginationCacheManager[List[org.json4s.JsonAST.JValue]] + .getPagedData(s"$cacheKey-audit") + .getOrElse(List[org.json4s.JsonAST.JValue]()) + } + val output = + elements.slice(start.get.toInt, start.get.toInt + limit.get.toInt) + if (output.length < limit.get.toInt) { + paginationCacheManager[List[org.json4s.JsonAST.JValue]] + .removePagedData(s"$cacheKey-audit") + } + val pagedRes = compact(render(JArray(output))) + val cachedData = paginationCacheManager[List[org.json4s.JsonAST.JValue]] .getPagedData(s"$cacheKey-audit") .getOrElse(List[org.json4s.JsonAST.JValue]()) + logger.info("Cached data size: {}", cachedData.size) + logger.info( + "Paged response size: {}", + compact(render(JArray(output))).length + ) + pagedRes + } catch { + case NonFatal(e) => + RestClient.handleError( + timeOutStatus, + authenticationFailedStatus, + serverErrorStatus, + e + ) } - val output = - elements.slice(start.get.toInt, start.get.toInt + limit.get.toInt) - if (output.length < limit.get.toInt) { - paginationCacheManager[List[org.json4s.JsonAST.JValue]] - .removePagedData(s"$cacheKey-audit") - } - val pagedRes = compact(render(JArray(output))) - val cachedData = paginationCacheManager[List[org.json4s.JsonAST.JValue]] - .getPagedData(s"$cacheKey-audit") - .getOrElse(List[org.json4s.JsonAST.JValue]()) - logger.info("Cached data size: {}", cachedData.size) - logger.info( - "Paged response size: {}", - compact(render(JArray(output))).length - ) - pagedRes } else { auditStr } @@ -382,12 +395,12 @@ class NotificationService()(implicit val (edges: Array[Edge], markedNodes: Array[Node]) = getDataSet(graphData) logger.info("Sending data") - logger.info("blacklist: {}", BlacklistCacheManager.getBlacklist(user)) + logger.info("blacklist: {}", BlacklistCacheManager.getBlacklist(user, tokenId)) NetworkGraph( markedNodes, edges, - BlacklistCacheManager.getBlacklist(user), + BlacklistCacheManager.getBlacklist(user, tokenId), enableGPU == "true" ) @@ -400,26 +413,75 @@ class NotificationService()(implicit } } - def createNetworkGraph(graphLayout: UserGraphLayout): Route = { - logger.info("saving positions for user: {}", graphLayout.user) - GraphCacheManager.saveNodeLayout(graphLayout) - logger.debug(layoutToJson(graphLayout)) + def createNetworkGraph(graphLayout: UserGraphLayout, tokenId: String): Route = complete { + try { + val resultPromise = AuthenticationManager.validateToken(tokenId) + Await.result(resultPromise, RestClient.waitingLimit.seconds) + + logger.info("saving positions for user: {}", graphLayout.user) + GraphCacheManager.saveNodeLayout(graphLayout, tokenId) + logger.debug(layoutToJson(graphLayout)) - complete(HttpEntity.Empty) + HttpEntity.Empty + } catch { + case NonFatal(e) => + RestClient.handleError( + timeOutStatus, + authenticationFailedStatus, + serverErrorStatus, + e + ) + } } - def getNetworkGraphLayout(user: String): Route = complete { - UserGraphLayout(user, GraphCacheManager.getNodeLayout(user)) + def getNetworkGraphLayout(user: String, tokenId: String): Route = complete { + try { + val resultPromise = AuthenticationManager.validateToken(tokenId) + Await.result(resultPromise, RestClient.waitingLimit.seconds) + UserGraphLayout(user, GraphCacheManager.getNodeLayout(user, tokenId)) + } catch { + case NonFatal(e) => + RestClient.handleError( + timeOutStatus, + authenticationFailedStatus, + serverErrorStatus, + e + ) + } } - def getNetworkGraphBlacklist(user: String): Route = complete { - BlacklistCacheManager.getBlacklist(user) + def getNetworkGraphBlacklist(user: String, tokenId: String): Route = complete { + try { + val resultPromise = AuthenticationManager.validateToken(tokenId) + Await.result(resultPromise, RestClient.waitingLimit.seconds) + BlacklistCacheManager.getBlacklist(user, tokenId) + } catch { + case NonFatal(e) => + RestClient.handleError( + timeOutStatus, + authenticationFailedStatus, + serverErrorStatus, + e + ) + } } - def createNetworkGraphBlacklist(userBlacklist: UserBlacklist): Route = { - logger.info("saving blacklist for user: {}", userBlacklist.user) - BlacklistCacheManager.saveBlacklist(userBlacklist) - complete(HttpEntity.Empty) + def createNetworkGraphBlacklist(userBlacklist: UserBlacklist, tokenId: String): Route = complete { + try { + val resultPromise = AuthenticationManager.validateToken(tokenId) + Await.result(resultPromise, RestClient.waitingLimit.seconds) + logger.info("saving blacklist for user: {}", userBlacklist.user) + BlacklistCacheManager.saveBlacklist(userBlacklist, tokenId) + HttpEntity.Empty + } catch { + case NonFatal(e) => + RestClient.handleError( + timeOutStatus, + authenticationFailedStatus, + serverErrorStatus, + e + ) + } } def getSecurityEvents(tokenId: String): Route = complete { diff --git a/admin/src/main/scala/com/neu/service/risk/RiskService.scala b/admin/src/main/scala/com/neu/service/risk/RiskService.scala index aaded96b5..dfece0859 100644 --- a/admin/src/main/scala/com/neu/service/risk/RiskService.scala +++ b/admin/src/main/scala/com/neu/service/risk/RiskService.scala @@ -20,6 +20,8 @@ import scala.concurrent.TimeoutException import scala.util.control.NonFatal import java.net.URLEncoder import java.nio.charset.StandardCharsets +import scala.concurrent.Await +import scala.concurrent.duration.DurationInt class RiskService extends BaseService with DefaultJsonFormats with LazyLogging { @@ -317,9 +319,24 @@ class RiskService extends BaseService with DefaultJsonFormats with LazyLogging { } } - def queryNistCompliances(complianceNISTConfigData: ComplianceNISTConfigData): Route = complete { - logger.info("Get NIST compliances: {}", complianceNISTConfigData.config.names) - CisNISTManager.getCompliancesNIST(complianceNISTConfigData.config.names) + def queryNistCompliances( + complianceNISTConfigData: ComplianceNISTConfigData, + tokenId: String + ): Route = complete { + try { + val resultPromise = AuthenticationManager.validateToken(tokenId) + Await.result(resultPromise, RestClient.waitingLimit.seconds) + logger.info("Get NIST compliances: {}", complianceNISTConfigData.config.names) + CisNISTManager.getCompliancesNIST(complianceNISTConfigData.config.names) + } catch { + case NonFatal(e) => + RestClient.handleError( + timeOutStatus, + authenticationFailedStatus, + serverErrorStatus, + e + ) + } } def getCompliances(tokenId: String): Route = complete { diff --git a/admin/webapp/websrc/app/routes/components/score-improvement-modal/partial/score-improvement-completed-view/score-improvement-completed-view.component.html b/admin/webapp/websrc/app/routes/components/score-improvement-modal/partial/score-improvement-completed-view/score-improvement-completed-view.component.html index a03f71981..fa143ccb3 100644 --- a/admin/webapp/websrc/app/routes/components/score-improvement-modal/partial/score-improvement-completed-view/score-improvement-completed-view.component.html +++ b/admin/webapp/websrc/app/routes/components/score-improvement-modal/partial/score-improvement-completed-view/score-improvement-completed-view.component.html @@ -12,8 +12,6 @@ [foregroundColor]="gaugeColor" [thick]="10" cap="round" - [thick]="10" - cap="round" [size]="120">
@@ -35,7 +33,9 @@ [animate]="true" [duration]="1" [foregroundColor]="gaugeLabelColorFixed" - [size]="40"> + [thick]="10" + cap="round" + [size]="120">
{{ gaugeLabelFixed }} diff --git a/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.html b/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.html index 71c871e3f..c593c394c 100644 --- a/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.html +++ b/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.html @@ -19,20 +19,23 @@ close
-
-
- - - +
+
+ + {{ 'dashboard.ALL_NAMESPACE' | translate }} + +
+
- + [matTooltip]="domain" + [matTooltipDisabled]="!isOverflow(domainTextEl)" + matTooltipPosition="above"> + + {{ domain }} + +
diff --git a/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.scss b/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.scss index e69de29bb..54e5b320b 100644 --- a/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.scss +++ b/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.scss @@ -0,0 +1,11 @@ +.text-overflow-ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.text-ns { + color: var(--mat-dialog-subhead-color, var(--mat-sys-on-surface, rgba(0, 0, 0, 0.87))) !important; + font-weight: 400 !important; + font-family: var(--mat-dialog-subhead-font, var(--mat-font-family, Roboto, "Helvetica Neue", sans-serif)) !important; +} \ No newline at end of file diff --git a/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.ts b/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.ts index 495412562..805d37a5f 100644 --- a/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.ts +++ b/admin/webapp/websrc/app/routes/dashboard/report-by-namespace-modal/report-by-namespace-modal.component.ts @@ -50,4 +50,8 @@ export class ReportByNamespaceModalComponent { } ); }; + + isOverflow(el: HTMLElement): boolean { + return el.scrollWidth > el.clientWidth; + } } diff --git a/common/src/main/scala/com/neu/cache/BlacklistCacheManager.scala b/common/src/main/scala/com/neu/cache/BlacklistCacheManager.scala index ad01bd352..824a8c78c 100644 --- a/common/src/main/scala/com/neu/cache/BlacklistCacheManager.scala +++ b/common/src/main/scala/com/neu/cache/BlacklistCacheManager.scala @@ -3,6 +3,7 @@ package com.neu.cache import com.neu.model.Blacklist import com.neu.model.UserBlacklist import net.sf.ehcache.CacheManager +import com.neu.utils.Common.shortKey object BlacklistCacheManager { given cacheKeyGenerator: ToStringCacheKeyGenerator.type = ToStringCacheKeyGenerator @@ -16,15 +17,20 @@ object BlacklistCacheManager { /** * Save blacklist for Graph. */ - def saveBlacklist(userBlacklist: UserBlacklist): Unit = - userBlacklist.blacklist.foreach(cache.put(userBlacklist.user + "blacklist", _)) + def saveBlacklist(userBlacklist: UserBlacklist, tokenId: String): Unit = + userBlacklist.blacklist.foreach( + cache.put(userBlacklist.user + shortKey(tokenId) + "blacklist", _) + ) /** * Get blacklist of user for Graph * @param user * the user + * @param tokenId + * the token ID * @return * [[com.neu.model.Blacklist]] */ - def getBlacklist(user: String): Option[Blacklist] = cache.get(user + "blacklist") + def getBlacklist(user: String, tokenId: String): Option[Blacklist] = + cache.get(user + shortKey(tokenId) + "blacklist") } diff --git a/common/src/main/scala/com/neu/cache/GraphCacheManager.scala b/common/src/main/scala/com/neu/cache/GraphCacheManager.scala index 653e4994d..b59c2e789 100644 --- a/common/src/main/scala/com/neu/cache/GraphCacheManager.scala +++ b/common/src/main/scala/com/neu/cache/GraphCacheManager.scala @@ -3,6 +3,7 @@ package com.neu.cache import com.neu.model.Position import com.neu.model.UserGraphLayout import net.sf.ehcache.CacheManager +import com.neu.utils.Common.shortKey /** * Created by bxu on 2/2/18. Manager graph layout for node and group view. @@ -23,8 +24,9 @@ object GraphCacheManager { * @param layout * the [[com.neu.model.UserGraphLayout]] */ - def saveNodeLayout(layout: UserGraphLayout): Unit = - if (layout.nodePositions.nonEmpty) cache.put(layout.user + "node", layout.nodePositions.get) + def saveNodeLayout(layout: UserGraphLayout, tokenId: String): Unit = + if (layout.nodePositions.nonEmpty) + cache.put(layout.user + shortKey(tokenId) + "node", layout.nodePositions.get) /** * Get node graph layout for user @@ -33,7 +35,8 @@ object GraphCacheManager { * @return * [[com.neu.model.Position]] */ - def getNodeLayout(user: String): Option[Map[String, Position]] = cache.get(user + "node") + def getNodeLayout(user: String, tokenId: String): Option[Map[String, Position]] = + cache.get(user + shortKey(tokenId) + "node") /** * Get group layout for user diff --git a/common/src/main/scala/com/neu/utils/Common.scala b/common/src/main/scala/com/neu/utils/Common.scala new file mode 100644 index 000000000..ed98d01b4 --- /dev/null +++ b/common/src/main/scala/com/neu/utils/Common.scala @@ -0,0 +1,14 @@ +package com.neu.utils + +import java.security.MessageDigest + +object Common { + def shortKey(jwt: String): String = { + val digest = MessageDigest.getInstance("SHA-256") + digest + .digest(jwt.getBytes(java.nio.charset.StandardCharsets.UTF_8)) + .take(10) + .map("%02x".format(_)) + .mkString + } +}