Created
April 19, 2022 02:49
-
-
Save ribsy/7570d3b8b68b59792c220bb9486335d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Package names | |
packages <- c("readr", "tidyverse", "lubridate", "survival", "survminer", "shiny", "shinydashboard","reactable","shinyalert") | |
# Install packages not yet installed | |
installed_packages <- packages %in% rownames(installed.packages()) | |
if (any(installed_packages == FALSE)) { | |
install.packages(packages[!installed_packages]) | |
} | |
# Packages loading | |
invisible(lapply(packages, library, character.only = TRUE)) | |
GetSearchButton <- function(){ | |
return(div(style="display:inline-block; width:43%;text-align: left;",actionButton("search", "Search Dates"))) | |
} | |
GetResetButton <- function(){ | |
return(div(style="display:inline-block; width:43%;text-align: left;",actionButton("reset", "Reset Values"))) | |
} | |
GetUpdatedVulnData <- function(df){ | |
min_date <- min(mdy(df$discovered_date)) | |
max_date <- max(mdy(df$last_scan_date)) | |
#Fetch Data from data() | |
vuln_update <- UpdateVulnData(df, min_date, max_date) | |
return(vuln_update) | |
} | |
PlotPois <- function(df){ | |
gf <- goodfit(df, "poisson") | |
return (plot(gf, type = "standing", scale = "raw")) | |
} | |
GetPoisVals <- function(v){ | |
gs <- GetGammaParams(v) | |
res <- rpois(n=100, lambda=rgamma(100, shape=gs[2],scale=gs[1])) | |
return(mean(res)) | |
} | |
GetGammaParams <- function(v){ | |
#Requires fitdistplus | |
fg <- fitdist(v, "gamma", lower=c(0,0), start=list(scale=1,shape=1)) | |
return(fg$estimate) | |
} | |
UpdateVulnData <- function(vmd, start, end){ | |
#message("The value of start_date is ", start_date) | |
vuln_data <- vmd %>% filter( mdy(discovered_date) >= start & mdy(last_scan_date) <= end ) | |
return(vuln_data) | |
} | |
GetVulnTable <- function(vmd, status){ | |
vtable <- vmd %>% select(severity, remediation_status, vulnerability_title, cvss_score, risk, ip_address, diff_date, | |
discovered_date, last_scan_date, func_code, server_type, site_code, environment_type) %>% | |
filter(remediation_status == status) %>% | |
mutate(diff_date = as.numeric(diff_date)) | |
vtable <- vtable %>% rename(title = vulnerability_title, function.code = func_code, ip = ip_address, | |
first.seen = discovered_date, last.seen = last_scan_date, time.open = diff_date, | |
server.type = server_type, site.code = site_code, env.type = environment_type, | |
status = remediation_status, cvss = cvss_score) | |
return(vtable) | |
} | |
GetFileData <- function(file_val){ | |
csv = vroom::vroom(file_val$datapath, delim = ",") | |
df <- CleanVulnData(csv) | |
return(df) | |
} | |
GetTTLBox <- function(severity, vmd){ | |
fixed <- GetTimesByAsset(vmd, min(vmd$discovered_date), max(vmd$last_scan_date), "REMEDIATED", c(severity)) | |
not_fixed <- GetAvgOpenTime(vmd, min(mdy(vmd$discovered_date)), max(mdy(vmd$last_scan_date)), c(severity)) | |
infoBox( | |
paste0(severity ," Time To Live Rates"), paste0(fixed$ratio_val,"% Closed Vuln < ", fixed$fifty_or_less, "D ",fixed$change_text), icon = icon(fixed$icon_name), | |
color = fixed$color_val, subtitle = paste0(not_fixed$ratio_val,"% of Open < ", not_fixed$fifty_less,"D | Max Open: ", not_fixed$max_days_total, "D") | |
) | |
} | |
GetCountBox <- function(severity, vulns){ | |
icon_val <- "user-secret" | |
if( vulns$vuln_count <= vulns$vuln_count_lweek){ | |
color_val <- "green" | |
diff_text <- "Decrease" | |
}else if(abs(vulns$vuln_diff) <= 5){ | |
color_val <- "yellow" | |
diff_text <- "Increase" | |
}else{ | |
color_val <- "red" | |
diff_text <- "Increase" | |
} | |
res <- infoBox( | |
paste0(severity," Open Vulnerabilities"), paste0(vulns$vuln_count, " Open Now (", vulns$vuln_diff,"% ", diff_text ,")"), icon = icon(icon_val), | |
color = color_val, subtitle = paste0("-1W: ", vulns$vuln_count_lweek, " | -1M: ", vulns$vuln_count_lmonth, " | Uniq: ", vulns$vuln_count_unique ) | |
) | |
return(res) | |
} | |
GetBurndownBox <- function(severity, vmd, kpi = .95, mode){ | |
crit_rates <- RateValues(vmd, severity, kpi) | |
kpi_success_rate <- 100 - round(crit_rates$fail_rates[length(crit_rates$fail_rates)] * 100) | |
crvals <- InfoBoxRateConfig(crit_rates$rates) | |
kpi_trend <- GetBestKPI(vmd, severity) * 100 | |
kpi_diff <- (kpi * 100) - kpi_trend | |
diff_val <- crvals$diff | |
fill_val <- FALSE | |
#Adjust colors for KPI slider activity | |
if( mode == "kpi" ){ | |
fill_val <- TRUE | |
if(kpi_success_rate <= 25){ | |
crvals$color_val <- "red" | |
}else if(kpi_success_rate > 25 & kpi_success_rate <= 75){ | |
crvals$color_val <- "yellow" | |
}else{ | |
crvals$color_val <- "green" | |
} | |
} | |
if( mode == "mixed"){ | |
fill_val <- TRUE | |
message("In Mixed Diff Val: ", diff_val, " KPI Success RateL ", kpi_success_rate ) | |
if( diff_val < 0 & kpi_success_rate <= 25){ | |
crvals$color_val <- "red" | |
}else if(kpi_success_rate <= 100 & diff_val < 0){ | |
crvals$color_val <- "yellow" | |
}else{ | |
crvals$color_val <- "green" | |
} | |
} | |
if(mode == "kpi" | mode == "mixed"){ | |
ret_val <- infoBox( | |
paste0(severity," Vulnerability Burndown Rate"), | |
paste0(kpi * 100, "% KPI (",kpi_success_rate,"% Met)"), | |
icon = icon(crvals$icon_name), | |
color = crvals$color_val, | |
fill = fill_val, | |
subtitle = paste0(crvals$rate_now ,"% Burn ", crvals$change_text," -",crvals$one_mon,"W: ", crvals$rate_last_mn,"% | -",crvals$two_mon,"W: ", | |
crvals$rate_prev_mn,"%" ) | |
) | |
}else{ | |
ret_val <- infoBox( | |
paste0(severity," Vulnerability Burndown Rate"), | |
paste0(crvals$rate_now, "% Now ", crvals$change_text), | |
icon = icon(crvals$icon_name), | |
color = crvals$color_val, | |
fill = fill_val, | |
subtitle = paste0("-",crvals$one_mon,"W: ", crvals$rate_last_mn,"% | -",crvals$two_mon,"W: ", | |
crvals$rate_prev_mn,"% | ", kpi * 100 ,"% Goal: ", kpi_success_rate,"% Met") | |
) | |
} | |
return(ret_val) | |
} | |
GetVulnVariables <- function(vmd){ | |
vulns <- list() | |
#Crit Vulns | |
vulns[["critical"]][["vuln_count"]] <- GetVulnCount(vmd, c("Critical")) | |
vulns[["critical"]][["vuln_count_unique"]] <- GetVulnCountUnique(vmd, c("Critical")) | |
vulns[["critical"]][["vuln_count_lweek"]] <- GetVulnCountPast(vmd, c("Critical"), 7) | |
vulns[["critical"]][["vuln_diff"]] <- GetVulnDiff(vulns$critical$vuln_count, vulns$critical$vuln_count_lweek) | |
vulns[["critical"]][["vuln_count_lmonth"]] <- GetVulnCountPast(vmd, c("Critical"), 30) | |
#Severe Vulns | |
vulns[["severe"]][["vuln_count"]] <- GetVulnCount(vmd, c("Severe")) | |
vulns[["severe"]][["vuln_count_unique"]] <- GetVulnCountUnique(vmd, c("Severe")) | |
vulns[["severe"]][["vuln_count_lweek"]] <- GetVulnCountPast(vmd, c("Severe"), 7) | |
vulns[["severe"]][["vuln_diff"]] <- GetVulnDiff(vulns$severe$vuln_count, vulns$severe$vuln_count_lweek) | |
vulns[["severe"]][["vuln_count_lmonth"]] <- GetVulnCountPast(vmd, c("Severe"), 30) | |
#Moderate Vulns | |
vulns[["moderate"]][["vuln_count"]] <- GetVulnCount(vmd, c("Moderate")) | |
vulns[["moderate"]][["vuln_count_unique"]] <- GetVulnCountUnique(vmd, c("Moderate")) | |
vulns[["moderate"]][["vuln_count_lweek"]] <- GetVulnCountPast(vmd, c("Moderate"), 7) | |
vulns[["moderate"]][["vuln_diff"]] <- GetVulnDiff(vulns$moderate$vuln_count, vulns$moderate$vuln_count_lweek) | |
vulns[["moderate"]][["vuln_count_lmonth"]] <- GetVulnCountPast(vmd, c("Moderate"), 30) | |
return(vulns) | |
} | |
CleanVulnData <- function(vmd){ | |
print_cols <- c( | |
"asset_id: Integer", | |
"ip_address: 10.97.2.67", | |
"scan_finished: MM/DD/YY", | |
"host_name: dash delim text like: SAL-VS-COMMWFE1", | |
"vulnerability_title: Text", | |
"severity: Critical, Severe, Moderate", | |
"vulnerability_id: Integer", | |
"cvss_score: numbers like 4.5, 9.5 etc", | |
"risk: Integer", | |
"remediation_status: REMEDIATED, NOT_REMEDIATED", | |
"discovered_date: MM/DD/YY", | |
"last_scan_date: : MM/DD/YY" | |
) | |
required_columns <- c('asset_id', 'ip_address', 'scan_finished', 'host_name', 'vulnerability_title', | |
'severity', 'vulnerability_id', 'cvss_score', 'risk', 'remediation_status', | |
'discovered_date', 'last_scan_date') | |
column_names <- colnames(vmd) | |
max_columns <- 12 | |
ncol_vmd <- ncol(vmd) | |
if( ncol_vmd != max_columns){ | |
print_cols <- c(" ",print_cols) | |
col_str <- paste(print_cols,collapse = "\n",sep="") | |
return(paste("Error: Uploaded data must have 12 columns.\nRequired Cols:", col_str)) | |
} | |
dvals <- setdiff(required_columns,column_names) | |
if( length(dvals) >= 1){ | |
dvals <- c(" ", dvals) | |
col_str <- paste(dvals,collapse = "\n",sep="") | |
return(paste("Error: Missing Colums:", col_str)) | |
} | |
#### Depricated - but useful if you have meaningful host names | |
## That can be split by a delimiter into useful components | |
## I put in dummy data for now. | |
#hn <- str_split(vmd$host_name,"-",simplify = TRUE) | |
#Get first portion (site code) of host name | |
vmd <- vmd %>% mutate(site_code = "Unknown") | |
#Get Second Section of Host name and create columns | |
stenv <- "test" | |
vmd <- GetServerType(vmd, stenv) | |
vmd <- GetEnvType(vmd, stenv) | |
#Get Third portion of host name and create columns | |
stcode <- "test" | |
vmd <- GetAppCode(vmd, stcode) | |
vmd <- GetFunCode(vmd, stcode) | |
#Create Columns with first portion of host name | |
#fp <- str_split(stcode,"\\.",simplify = TRUE) | |
vmd <- vmd %>% mutate(fqdn_first = "test") | |
#If Last Scan Date Is Empty - Put Max Date | |
vmd <- SetRemediatedClosedDate(vmd) | |
#Add +1 so that a vulnerability discovered and closed on the same day is 1 | |
vmd <- vmd %>% mutate( diff_date = (mdy(last_scan_date) - mdy(discovered_date) + 1)) | |
#print(vmd) | |
return(vmd) | |
} | |
GetBestKPI <- function(vmd, severity){ | |
hit_vals <- GetCountByAsset(vmd,min(vmd$discovered_date), max(vmd$last_scan_date), "REMEDIATED", c(severity)) | |
miss_vals <- GetCountByAsset(vmd,min(vmd$discovered_date), max(vmd$last_scan_date), "NOT_REMEDIATED", c(severity)) | |
for(i in 100:1){ | |
rate <- i/100 | |
#Really this is success rate...but anyway.... | |
fail_rate_vals <- GetFailRates(rate, hit_vals$n, miss_vals$n) | |
max_fail <- fail_rate_vals[length(fail_rate_vals)] | |
kpi_fail_rate <- 100 - round(max_fail * 100) | |
if(kpi_fail_rate == 100){ | |
return(rate) | |
} | |
} | |
} | |
GetSurvData <- function(vmd){ | |
vmd <- vmd %>% select(diff_date, remediation_status, severity) %>% | |
mutate(status = ifelse(remediation_status == "NOT_REMEDIATED",0,1), | |
diff_date = as.numeric(diff_date)) %>% | |
select(diff_date, status, severity) | |
#paste0("res:", head(res_val,10)) | |
t_surv <- survfit(data = vmd, Surv(vmd$diff_date, vmd$status) ~ vmd$severity) | |
return(t_surv) | |
} | |
GetSurvPlot <- function(vmd){ | |
#t_surv <- GetSurvData(vmd) | |
res <- vmd %>% select(diff_date, remediation_status, severity) %>% | |
mutate(status = ifelse(remediation_status == "NOT_REMEDIATED",0,1), | |
diff_date = as.numeric(diff_date)) %>% | |
select(diff_date, status, severity) | |
#paste("VMD: ", vmd) | |
t_surv <- surv_fit(data = res, Surv(diff_date, status) ~ severity) | |
#print(t_surv) | |
surv_plot <- ggsurvplot(t_surv, | |
conf.int = TRUE, | |
risk.table.col = "strata", # Change risk table color by groups | |
ggtheme = theme_light(), # Change ggplot2 theme | |
palette = c("coral3", "darkorange","deepskyblue4"), | |
risk.table = "abs_pct", | |
risk.table.y.text.col = T, | |
fun = "event") | |
return(surv_plot) | |
} | |
SetRemediatedClosedDate <- function(vmd){ | |
m_date <- max(mdy(vmd[!is.na(vmd$last_scan_date),"last_scan_date"][[1]])) | |
m_date <- format(m_date, "%m/%d/%y") | |
m_date <- sub("^0", "", m_date) | |
vmd[is.na(vmd$last_scan_date),"last_scan_date"] <- as.character(m_date) | |
return(vmd) | |
} | |
TimeValues <- function(vmd, severity){ | |
hit_vals <- GetTimesByAsset(vmd,min(vmd$discovered_date), max(vmd$last_scan_date), "REMEDIATED", c(severity)) | |
miss_vals <- GetTimesByAsset(vmd,min(vmd$discovered_date), max(vmd$last_scan_date), "NOT_REMEDIATED", c(severity)) | |
rate_vals <- round(cumsum(hit_vals$n)/(cumsum(miss_vals$n) + cumsum(hit_vals$n)) ,2) * 100 | |
fail_rate_vals <- GetFailRates(kpi, hit_vals$n, miss_vals$n) | |
rate_return <- tibble( | |
hits = hit_vals, | |
misses = miss_vals, | |
rates = rate_vals, | |
fail_rates = fail_rate_vals | |
) | |
return(rate_return) | |
} | |
GetAvgOpenTime_test <- function(vmd, start, end, sev){ | |
print(paste("Start: ", start, " End: ", end)) | |
res <- vmd %>% select(asset_id, vulnerability_id, severity,risk, discovered_date, last_scan_date, remediation_status, diff_date) %>% | |
filter(remediation_status == "NOT_REMEDIATED" & severity %in% sev) %>% | |
filter(mdy(discovered_date) >= start & mdy(last_scan_date) <= end) %>% distinct() | |
return(res) | |
time_val <- table(res$diff_date) | |
#print(paste("Time Val: ", time_val)) | |
time_tib <- tibble( | |
day_val = as.numeric(names(time_val)), | |
vuln_count = as.vector(time_val), | |
sum_val = cumsum(vuln_count), | |
day_ratio = round(sum_val / sum(vuln_count) * 100,1) | |
) | |
#print(paste("Time Tib: ", time_tib)) | |
if ( min(time_tib$day_ratio) > 50 ){ | |
ratio_val <- min(time_tib$day_ratio) | |
}else{ | |
ratio_val <- 50 | |
} | |
fifty_less <- max(time_tib[time_tib$day_ratio <= ratio_val,]$day_val) | |
max_days_total <- max(time_tib$day_val) | |
ret_tibble <- tibble( | |
fifty_less = fifty_less, | |
max_days_total = max_days_total | |
) | |
return(ret_tibble) | |
} | |
GetAvgOpenTime <- function(vmd, start, end, sev){ | |
res <- vmd %>% select(asset_id, vulnerability_id, severity,risk, discovered_date, last_scan_date, remediation_status, diff_date) %>% | |
filter(remediation_status == "NOT_REMEDIATED" & severity %in% sev) %>% | |
filter(mdy(discovered_date) >= start & mdy(last_scan_date) <= end) %>% distinct() | |
time_val <- table(res$diff_date) | |
#print(paste("Time Val: ", time_val)) | |
time_tib <- tibble( | |
day_val = as.numeric(names(time_val)), | |
vuln_count = as.vector(time_val), | |
sum_val = cumsum(vuln_count), | |
day_ratio = round(sum_val / sum(vuln_count) * 100,1) | |
) | |
#print(paste("Time Tib: ", time_tib)) | |
if ( min(time_tib$day_ratio) > 50 ){ | |
ratio_val <- min(time_tib$day_ratio) | |
}else{ | |
ratio_val <- 50 | |
} | |
fifty_less <- max(time_tib[time_tib$day_ratio <= ratio_val,]$day_val) | |
max_days_total <- max(time_tib$day_val) | |
ret_tibble <- tibble( | |
fifty_less = fifty_less, | |
max_days_total = max_days_total, | |
ratio_val = ratio_val | |
) | |
return(ret_tibble) | |
} | |
GetTimesByAsset_test <- function(vmd, start, end, rem_status, sev){ | |
res <- vmd %>% select(asset_id, vulnerability_id, severity,risk, discovered_date, last_scan_date, remediation_status, diff_date) %>% | |
filter(remediation_status == rem_status & severity %in% sev) %>% | |
filter(mdy(discovered_date) >= mdy(start) & mdy(last_scan_date) <= mdy(end)) %>% distinct() | |
time_val <- table(res$diff_date) | |
#return(res) | |
time_tib <- tibble( | |
day_val = as.numeric(names(time_val)), | |
vuln_count = as.vector(time_val), | |
sum_val = cumsum(vuln_count), | |
day_ratio = round(sum_val / sum(vuln_count) * 100,1) | |
) | |
if(max(res$diff_date) < 30){ | |
sub_days <- round(max(res$diff_date)/2) | |
}else{ | |
sub_days <- 30 | |
} | |
print(paste("Sub Days: ", sub_days)) | |
return(time_tib) | |
thirty_days <- res %>% select(asset_id, vulnerability_id, discovered_date, last_scan_date, diff_date) %>% | |
filter(mdy(last_scan_date) < max(mdy(last_scan_date)) - sub_days) | |
prior_val <- table(thirty_days$diff_date) | |
prior_tib <- tibble( | |
day_val = as.numeric(names(prior_val)), | |
vuln_count = as.vector(prior_val), | |
sum_val = cumsum(vuln_count), | |
day_ratio = round(sum_val / sum(vuln_count) * 100,1) | |
) | |
#return(prior_tib) | |
} | |
GetTimesByAsset <- function(vmd, start, end, rem_status, sev){ | |
#Build A Table Object and Tibble to Hold First REsults | |
res <- vmd %>% select(asset_id, vulnerability_id, severity,risk, discovered_date, last_scan_date, remediation_status, diff_date) %>% | |
filter(remediation_status == rem_status & severity %in% sev) %>% | |
filter(mdy(discovered_date) >= mdy(start) & mdy(last_scan_date) <= mdy(end)) %>% distinct() | |
time_val <- table(res$diff_date) | |
#Current Tibb | |
time_tib <- tibble( | |
day_val = as.numeric(names(time_val)), | |
vuln_count = as.vector(time_val), | |
sum_val = cumsum(vuln_count), | |
day_ratio = round(sum_val / sum(vuln_count) * 100,1) | |
) | |
if(max(res$diff_date) < 30){ | |
sub_days <- round(max(res$diff_date)/2) | |
}else{ | |
sub_days <- 30 | |
} | |
#Make A Second Result Set For 30 days ago | |
thirty_days <- res %>% select(asset_id, vulnerability_id, discovered_date, last_scan_date, diff_date) %>% | |
filter(mdy(last_scan_date) < max(mdy(last_scan_date)) - sub_days) | |
prior_val <- table(thirty_days$diff_date) | |
#print(paste("Prior Val: ", prior_val)) | |
#For 30 days ago | |
prior_tib <- tibble( | |
day_val = as.numeric(names(prior_val)), | |
vuln_count = as.vector(prior_val), | |
sum_val = cumsum(vuln_count), | |
day_ratio = round(sum_val / sum(vuln_count) * 100,1) | |
) | |
#print(paste("Prior TIB: ", prior_tib)) | |
if ( min(time_tib$day_ratio) > 50 ){ | |
ratio_val <- min(time_tib$day_ratio) | |
}else{ | |
ratio_val <- 50 | |
} | |
if ( min(prior_tib$day_ratio) > 50 ){ | |
prior_ratio_val <- min(prior_tib$day_ratio) | |
}else{ | |
prior_ratio_val <- 50 | |
} | |
fifty_less <- max(time_tib[time_tib$day_ratio <= ratio_val,]$day_val) | |
#ninety_less <- max(time_tib[time_tib$day_ratio <= 90,]$day_val) | |
max_days_total <- max(time_tib$day_val) | |
thirty_days_ago <- max(prior_tib[prior_tib$day_ratio <= prior_ratio_val,]$day_val) | |
diff_val <- thirty_days_ago - fifty_less | |
if(diff_val >= 0){ | |
color_val = "green" | |
if( diff_val == 0){ | |
change_text <- "" | |
}else{ | |
change_text <- paste0("(",diff_val,"D -)") | |
} | |
icon_name <- "clock" | |
}else if(diff_val >= -5){ | |
color_val = "yellow" | |
change_text <- paste0("(",abs(diff_val),"D +)") | |
icon_name <- "clock" | |
}else{ | |
color_val = "red" | |
change_text <- paste0("(",abs(diff_val),"D +)") | |
icon_name <- "clock" | |
} | |
ret_tib <- tibble( | |
fifty_or_less = fifty_less, | |
#ninety_or_less = ninety_less, | |
max_days = max_days_total, | |
thirty_d_prior = thirty_days_ago, | |
color_val = color_val, | |
change_text = change_text, | |
icon_name = icon_name, | |
ratio_val = ratio_val, | |
prior_ratio_val = prior_ratio_val | |
) | |
return(ret_tib) | |
} | |
GetKpiRate <- function(crit_rates){ | |
last_fail_rate <- crit_rates$fail_rates[length(crit_rates$fail_rates)] | |
kpi_fail_rate <- 100 - round(last_fail_rate * 100) | |
return(kpi_fail_rate) | |
} | |
RateValues <- function(vmd, severity, kpi){ | |
hit_vals <- GetCountByAsset(vmd,min(vmd$discovered_date), max(vmd$last_scan_date), "REMEDIATED", c(severity)) | |
miss_vals <- GetCountByAsset(vmd,min(vmd$discovered_date), max(vmd$last_scan_date), "NOT_REMEDIATED", c(severity)) | |
rate_vals <- round(cumsum(hit_vals$n)/(cumsum(miss_vals$n) + cumsum(hit_vals$n)) ,2) * 100 | |
fail_rate_vals <- GetFailRates(kpi, hit_vals$n, miss_vals$n) | |
rate_return <- tibble( | |
hits = hit_vals, | |
misses = miss_vals, | |
rates = rate_vals, | |
fail_rates = fail_rate_vals | |
) | |
return(rate_return) | |
} | |
InfoBoxRateConfig <- function(rate_vals){ | |
r_len <- length(rate_vals) | |
one_mon <- 4 | |
two_mon <- 8 | |
if( r_len < 9){ | |
one_mon <- round(r_len/2) #It's suppose to be a month...but it may be short | |
two_mon <- r_len - 1 #It's suppose to be two month...but it may be short | |
} | |
rate_val_now <- rate_vals[r_len] | |
rate_val_last_mn <- rate_vals[r_len - one_mon] | |
rate_val_prev_mn <- rate_vals[r_len - two_mon] | |
diff_val <- rate_val_now - rate_val_last_mn | |
if(diff_val >= 0){ | |
color_val = "green" | |
change_text <- paste0("(",diff_val,"% Increase)") | |
icon_name <- "fire-alt" | |
}else if(diff_val >= -5){ | |
color_val = "yellow" | |
change_text <- paste0("(",abs(diff_val),"% Decrease)") | |
icon_name <- "fire-alt" | |
}else{ | |
color_val = "red" | |
change_text <- paste0("(",abs(diff_val),"% Decrease)") | |
icon_name <- "fire-alt" | |
} | |
if(r_len < 13 & r_len > 6){ | |
msg_val <- paste0(r_len, " weeks SMALL data") | |
}else if(r_len < 6){ | |
msg_val <- paste0(r_len, " weeks TINY data") | |
}else{ | |
msg_val <- paste0(r_len, " weeks data") | |
} | |
#For now, hold off on this - could confuse the user | |
msg_val <- "" | |
rates <- tibble( | |
rate_now = rate_val_now, | |
rate_last_mn = rate_val_last_mn, | |
rate_prev_mn = rate_val_prev_mn, | |
diff = diff_val, | |
color_val = color_val, | |
change_text = change_text, | |
icon_name = icon_name, | |
one_mon = one_mon, | |
two_mon = two_mon, | |
msg_val = msg_val | |
) | |
return(rates) | |
} | |
GetVulnDiff <- function(new, old){ | |
diff <- new - old | |
diff_rate <- round(diff / old,2) * 100 | |
return(diff_rate) | |
} | |
GetVulnCountPast <- function(vmd, severity_val, delay){ | |
#While the record may say remediated, the last date it was found is LATER than the day we are asking for. | |
# So, we may has for 30 days ago, but this record was actually found fixed 10 days ago...for example | |
critical_vulns_rem <- vmd %>% select(asset_id, vulnerability_id, severity, remediation_status,last_scan_date) %>% | |
filter(remediation_status == "REMEDIATED" & severity %in% severity_val & (mdy(last_scan_date) > max(mdy(vmd$last_scan_date)) - delay)) | |
critical_vulns_rem <- unique(critical_vulns_rem) | |
critical_vuln_count_rem <- count(critical_vulns_rem) | |
#vuln still not remediated and its discovery date is before the time being asked for. | |
critical_vulns_not <- vmd %>% select(asset_id, vulnerability_id, severity, remediation_status, discovered_date) %>% | |
filter(remediation_status == "NOT_REMEDIATED" & severity %in% severity_val & (mdy(discovered_date) < max(mdy(vmd$last_scan_date)) - delay)) | |
critical_vulns_not <- unique(critical_vulns_not) | |
critical_vuln_count_not <- count(critical_vulns_not) | |
return(critical_vuln_count_rem + critical_vuln_count_not) | |
} | |
GetVulnCountUnique <- function(vmd,severity_val){ | |
critical_vulns <- vmd %>% select(vulnerability_id, severity, remediation_status) %>% | |
filter(remediation_status == "NOT_REMEDIATED" & severity %in% severity_val) | |
critical_vulns <- unique(critical_vulns) | |
critical_vuln_count <- count(critical_vulns) | |
return(critical_vuln_count) | |
} | |
GetVulnCount <- function(vmd,severity_val){ | |
critical_vulns <- vmd %>% select(asset_id, vulnerability_id, severity, remediation_status) %>% | |
filter(remediation_status == "NOT_REMEDIATED" & severity %in% severity_val) | |
critical_vulns <- unique(critical_vulns) | |
critical_vuln_count <- count(critical_vulns) | |
return(critical_vuln_count) | |
} | |
GetFailRates <- function(KPIRate, hits, misses){ | |
fail_rate <- round(pbeta(KPIRate, cumsum(hits), cumsum(misses)),3) | |
#qvalue <- cummean(arrange(fail_rate)) | |
#qvalue <- round(cummean(sort(fail_rate)),4) | |
return(fail_rate) | |
} | |
GetWeekYears <- function(start_year, cur_date){ | |
cur_date <- mdy(cur_date) | |
cur_year <- year(cur_date) | |
start_year_add <- (cur_year - start_year) * 52 | |
week_val <- week(cur_date) + start_year_add | |
#print(paste("Week Val: ", week_val)) | |
return(week_val) | |
} | |
GetCountByVuln <- function(vmd, start, end, remediation_state, sev = c("Severe","Critical","Moderate"), risk_score = 0){ | |
#We are creating a week over week cummulative count of discovered vulnerabilties. | |
#And they are all within a time range in terms of when they are discovered. | |
#Week #, Vuln Count | |
#Adjust for multiple year span - add multiples of 52 to account of yeach additional year from a baseline min_year | |
min_year <- min(year(mdy(vmd$discovered_date))) | |
start_year <- year(mdy(start)) | |
start_year_add <- (start_year - min_year) * 52 # Number of weeks to add to start week | |
end_year <- year(mdy(end)) | |
end_year_add <- (end_year - min_year) * 52 # Number of weeks to add to end week. | |
start_week <- week(mdy(start)) + start_year_add | |
end_week <- week(mdy(end)) + end_year_add | |
#print(paste("Start Week: ", start_week)) | |
#print(paste("End Week: ", end_week)) | |
rem_val <- vmd %>% select(vulnerability_id, severity,risk, discovered_date, last_scan_date, remediation_status) %>% | |
filter(mdy(discovered_date) >= mdy(start) & mdy(discovered_date) <= mdy(end)) %>% | |
#Need to create dataframe columns to hold the week number for discovery and last scan | |
mutate(week_disc = GetWeekYears(min_year, discovered_date)) %>% | |
mutate(week_last = GetWeekYears(min_year, last_scan_date)) %>% | |
select(vulnerability_id, severity,risk, remediation_status, week_disc, week_last) %>% | |
filter(remediation_status == remediation_state & severity %in% sev) %>% | |
filter(risk >= risk_score) %>% | |
distinct() %>% | |
group_by(week = week_disc) %>% | |
tally() | |
#print(paste("Rem Val: ", rem_val)) | |
#This creates a simple data frame with a week index starting with the | |
# starting week and the ending week. | |
# Pre load the count field (n) with 0x | |
res <- tibble( | |
week = start_week:end_week, | |
n = 0 | |
) | |
#print(paste("Res Tibble: ", res)) | |
#Get the weeks that are missing in rem_val and give them 0s for counts | |
missing_vals <- res %>% anti_join(rem_val, by = "week") | |
rem_val <- rbind(rem_val,missing_vals) #Bind it all together as a whole set of weeks with counts | |
rem_val <- arrange(rem_val, week) #Rank order buy week. | |
return(rem_val) | |
} | |
GetCountByAsset <- function(vmd, start, end, remediation_state, sev = c("Severe","Critical","Moderate"), risk_score = 0){ | |
#Largely the same as above, but more voluminous due to vuln and asset_id | |
min_year <- min(year(mdy(vmd$discovered_date))) | |
start_year <- year(mdy(start)) | |
start_year_add <- (start_year - min_year) * 52 # Number of weeks to add to start week | |
end_year <- year(mdy(end)) | |
end_year_add <- (end_year - min_year) * 52 # Number of weeks to add to end week. | |
start_week <- week(mdy(start)) + start_year_add | |
end_week <- week(mdy(end)) + end_year_add | |
#Query | |
rem_val <- vmd %>% select(asset_id, vulnerability_id, severity,risk, discovered_date, last_scan_date, remediation_status) %>% | |
filter(remediation_status == remediation_state & severity %in% sev) %>% | |
filter(risk >= risk_score) %>% | |
filter(mdy(discovered_date) >= mdy(start) & mdy(discovered_date) <= mdy(end)) %>% | |
#group_by(week = week(mdy(discovered_date))) %>% | |
group_by(week = GetWeekYears(min_year, discovered_date)) %>% | |
tally() | |
#A Tibble To Hold Results To Fix Missing Values | |
res <- tibble( | |
week = start_week:end_week, | |
n = 0 | |
) | |
#Get Missing Values, Merge, Sort | |
missing_vals <- res %>% anti_join(rem_val, by = "week") | |
rem_val <- rbind(rem_val,missing_vals) | |
rem_val <- arrange(rem_val, week) | |
return(rem_val) | |
} | |
#Server Type | |
GetServerType <- function(vmd, stenv){ | |
# Function Code (if needed) | |
# Overwrite here to "Unknown" but could include options as seen below... | |
vmd <- vmd %>% mutate(server_type = "Unknown") | |
# vmd$server_type[grep("^P|^S",stenv,ignore.case = TRUE)] <- "Server" | |
# vmd$server_type[grep("^V",stenv, ignore.case = TRUE)] <- "Virtual" | |
return(vmd) | |
} | |
#Env Type | |
GetEnvType <- function(vmd, stenv){ | |
# Function Code (if needed) | |
# Overwrite here to "Unknown" but could include options as seen below... | |
vmd <- vmd %>% mutate(environment_type = "Unknown") | |
# vmd$environment_type[grep("DZ",stenv,ignore.case = TRUE)] <- "DMZ" | |
# vmd$environment_type[grep("ST",stenv,ignore.case = TRUE)] <- "Staging" | |
# vmd$environment_type[grep("X",stenv,ignore.case = TRUE)] <- "Sandbox" | |
# vmd$environment_type[grep("Q",stenv,ignore.case = TRUE)] <- "QA" | |
# vmd$environment_type[grep("U",stenv,ignore.case = TRUE)] <- "UAT" | |
# vmd$environment_type[grep("D",stenv,ignore.case = TRUE)] <- "Dev" | |
return(vmd) | |
} | |
GetAppCode <- function(vmd,stcode){ | |
# Function Code (if needed) | |
# Overwrite here to "Unknown" but could include options as seen below... | |
vmd <- vmd %>% mutate(app_code = "Unknown") | |
# vmd$app_code[grep("CRD",stcode,ignore.case = TRUE)] <- "CARD Systems" | |
# vmd$app_code[grep("HRM",stcode,ignore.case = TRUE)] <- "HR Systems" | |
# vmd$app_code[grep("TPC",stcode,ignore.case = TRUE)] <- "Third Party Cloud" | |
return(vmd) | |
} | |
GetFunCode <- function(vmd,stcode){ | |
# Function Code (if needed) | |
# Overwrite here to "Unknown" but could include options as seen below... | |
vmd <- vmd %>% mutate(func_code = "Unknown") | |
# vmd$func_code[grep("APP",stcode,ignore.case = TRUE)] <- "Application Server" | |
# vmd$func_code[grep("DB",stcode,ignore.case = TRUE)] <- "Database Server" | |
# vmd$func_code[grep("WEB",stcode,ignore.case = TRUE)] <- "Web Server" | |
# vmd$func_code[grep("HI",stcode,ignore.case = TRUE)] <- "Host Interface" | |
# vmd$func_code[grep("MBL",stcode,ignore.case = TRUE)] <- "Mobile" | |
# vmd$func_code[grep("SQL",stcode,ignore.case = TRUE)] <- "SQL" | |
# vmd$func_code[grep("WFE",stcode,ignore.case = TRUE)] <- "Web Front End" | |
# vmd$func_code[grep("apig",stcode,ignore.case = TRUE)] <- "API Gateway" | |
# vmd$func_code[grep("dhcp",stcode,ignore.case = TRUE)] <- "DHCP" | |
return(vmd) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment