560 lines
No EOL
13 KiB
JavaScript
560 lines
No EOL
13 KiB
JavaScript
class Auth {
|
|
constructor() {
|
|
this.url = "http://localhost:8000"
|
|
this.settings = {
|
|
authority: "https://sso.sr2.uk/realms/sr2",
|
|
client_id: "chris-dev",
|
|
redirect_uri: this.url + "/signin-callback.html",
|
|
response_type: "code",
|
|
scope: "openid email profile",
|
|
|
|
response_mode: "fragment",
|
|
}
|
|
|
|
this.user_manager = new oidc.UserManager(this.settings)
|
|
this.get_user().then(() => {
|
|
window.is_authenticated = Boolean(this.user);
|
|
ui.update_auth_button()
|
|
})
|
|
}
|
|
|
|
async get_user() {
|
|
this.user = await this.user_manager.getUser()
|
|
}
|
|
|
|
async login() {
|
|
try {
|
|
this.user = await this.user_manager.signinPopup();
|
|
window.is_authenticated = Boolean(auth.user);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
|
|
async logout() {
|
|
try {
|
|
this.user = await this.user_manager.signoutPopup();
|
|
window.is_authenticated = Boolean(auth.user);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
class UI {
|
|
constructor() {
|
|
this.auth_button = document.getElementById("auth_button");
|
|
|
|
this.blocked_domains = document.getElementById("blocked_domains")
|
|
this.timer_status = document.getElementById("timer_status")
|
|
this.overall_status = document.getElementById("overall_status")
|
|
this.last_update_complete_time = document.getElementById("last_update_complete_time")
|
|
this.last_update_duration = document.getElementById("last_update_duration")
|
|
|
|
this.manual_update_btn = document.getElementById("manual_update_btn")
|
|
this.start_timer_btn = document.getElementById("start_timer_btn")
|
|
this.stop_timer_btn = document.getElementById("stop_timer_btn")
|
|
|
|
this.domain_search_btn = document.getElementById("domain_search_btn")
|
|
|
|
this.false_positive_actions = document.getElementById("false_positive_actions")
|
|
this.false_positive_load_btn = document.getElementById("false_positive_load_btn")
|
|
this.event_container = document.getElementById("events_container")
|
|
|
|
this.create_listeners()
|
|
}
|
|
|
|
create_listeners() {
|
|
this.auth_button.addEventListener("click", this.onclick_auth_button)
|
|
|
|
this.manual_update_btn.addEventListener("click", this.onclick_manual_update_btn)
|
|
this.start_timer_btn.addEventListener("click", this.onclick_start_timer_btn)
|
|
this.stop_timer_btn.addEventListener("click", this.onclick_stop_timer_btn)
|
|
|
|
this.domain_search_btn.addEventListener("click", this.onclick_domain_search_btn)
|
|
|
|
this.false_positive_load_btn.addEventListener("click", this.onclick_false_positive_load_btn)
|
|
this.event_container.addEventListener("click", this.onclick_event_button)
|
|
|
|
document.getElementById("modal_button").addEventListener("click", this.onclick_modal_button)
|
|
}
|
|
|
|
open_modal(title, message) {
|
|
document.getElementById("modal_title").innerText = title;
|
|
document.getElementById("modal_message").innerText = message;
|
|
|
|
document.getElementById("modal_backdrop").style.display = "flex";
|
|
}
|
|
|
|
set_loading(button_id, loading) {
|
|
const button = document.getElementById(button_id);
|
|
|
|
button.disabled = loading;
|
|
|
|
if (loading) {
|
|
button.dataset.original_text = button.innerText;
|
|
button.innerText = "Loading...";
|
|
} else {
|
|
button.innerText = button.dataset.original_text;
|
|
}
|
|
}
|
|
|
|
sync_timer_buttons() {
|
|
this.start_timer_btn.disabled = timer_running;
|
|
this.stop_timer_btn.disabled = !timer_running;
|
|
}
|
|
|
|
render_search_results(results) {
|
|
const container = document.getElementById("domain_search_results");
|
|
container.innerHTML = "";
|
|
const result_count = Object.keys(results).length;
|
|
if (!result_count) {
|
|
container.innerHTML = `<div class="search-result">No results found.</div>`;
|
|
return;
|
|
}
|
|
for (const [key, value] of Object.entries(results)) {
|
|
const row = document.createElement("div");
|
|
row.className = "search-result";
|
|
row.innerHTML = `
|
|
<div class="row">
|
|
<div class="col-8">
|
|
${key}
|
|
</div>
|
|
|
|
<div class="col-4 ${ui.event_status_class(value)}">
|
|
${value}
|
|
</div>
|
|
</div>
|
|
`;
|
|
container.appendChild(row);
|
|
}
|
|
}
|
|
|
|
onclick_auth_button() {
|
|
if (is_authenticated) {
|
|
auth.logout().then(() => {
|
|
ui.update_auth_button()
|
|
})
|
|
} else {
|
|
auth.login().then(() => {
|
|
ui.update_auth_button()
|
|
})
|
|
}
|
|
ui.update_auth_button()
|
|
}
|
|
|
|
update_auth_button() {
|
|
const button = document.getElementById("auth_button");
|
|
|
|
if (is_authenticated) {
|
|
button.innerText = "Logged In";
|
|
button.className = "button default-dm success";
|
|
} else {
|
|
button.innerText = "Logged Out";
|
|
button.className = "button default-dm secondary";
|
|
}
|
|
}
|
|
|
|
event_status_class(value) {
|
|
switch (value.toUpperCase()) {
|
|
case "ALLOWED":
|
|
return "status-good";
|
|
case "IGNORED":
|
|
return "status-warning";
|
|
default:
|
|
return "status-bad";
|
|
}
|
|
}
|
|
|
|
update_metrics(metrics){
|
|
this.blocked_domains.innerHTML = metrics.blocked_domain_count;
|
|
|
|
let date
|
|
let pretty_length
|
|
if(!metrics.last_update_complete_time){
|
|
date = "No update since last restart"
|
|
pretty_length = ""
|
|
} else {
|
|
date = new Date(metrics.last_update_complete_time * 1000).toLocaleString();
|
|
pretty_length = `${Math.round(metrics.last_update_length)} seconds`
|
|
}
|
|
this.last_update_complete_time.innerHTML = date;
|
|
this.last_update_duration.innerHTML = pretty_length;
|
|
|
|
let timer_value = ""
|
|
switch (metrics.TIMER_STATE) {
|
|
case 0:
|
|
timer_value = "RUNNING"
|
|
window.timer_running = true;
|
|
break;
|
|
case 1:
|
|
timer_value = "STOPPING"
|
|
window.timer_running = true;
|
|
break;
|
|
case 2:
|
|
timer_value = "STOPPED"
|
|
window.timer_running = false;
|
|
break;
|
|
}
|
|
this.timer_status.innerHTML = timer_value;
|
|
this.timer_status.className = timer_running ? "status-good" : "status-warning";
|
|
this.sync_timer_buttons()
|
|
|
|
let overall_status = ""
|
|
switch (metrics.MISP_STATE) {
|
|
case 0:
|
|
overall_status = "IDLE"
|
|
break;
|
|
case 1:
|
|
overall_status = "FETCHING"
|
|
break;
|
|
case 2:
|
|
overall_status = "UPDATING"
|
|
break;
|
|
case 3:
|
|
overall_status = "RELOADING"
|
|
break;
|
|
case 4:
|
|
overall_status = "ERROR"
|
|
break;
|
|
}
|
|
this.overall_status.innerHTML = overall_status;
|
|
}
|
|
|
|
render_false_positive_controls(domain_data) {
|
|
ui.false_positive_actions.style.display = "block";
|
|
const always_allow_btn = document.getElementById("always_allow_btn");
|
|
|
|
always_allow_btn.innerText = domain_data.always_allow ? "Enabled" : "Disabled";
|
|
always_allow_btn.className = domain_data.always_allow ? "button default-dm success" : "button default-dm secondary";
|
|
always_allow_btn.dataset.domain = domain_data.domain;
|
|
always_allow_btn.dataset.always_allow = domain_data.always_allow;
|
|
|
|
always_allow_btn.addEventListener("click", ui.onclick_always_allow_btn)
|
|
|
|
ui.event_container.innerHTML = "";
|
|
|
|
domain_data.events.forEach(event => {
|
|
const button = document.createElement("button");
|
|
|
|
button.className = `button event-btn ${event.ignored ? "default-dm warning" : "default-dm danger" }`;
|
|
button.innerText = event.id;
|
|
button.dataset.id = event.id;
|
|
button.dataset.ignored = event.ignored
|
|
button.dataset.domain = domain_data.domain;
|
|
|
|
ui.event_container.appendChild(button);
|
|
});
|
|
}
|
|
|
|
async onclick_manual_update_btn() {
|
|
ui.set_loading("manual_update_btn", true);
|
|
try {
|
|
const data = await api.manual_update()
|
|
if(data.state==="Starting"){
|
|
ui.open_modal(
|
|
"Update Triggered",
|
|
"Manual update process successfully started."
|
|
);
|
|
} else {
|
|
throw new Error()
|
|
}
|
|
} catch (error) {
|
|
ui.open_modal(
|
|
"Update Failed",
|
|
"Failed to trigger update process."
|
|
);
|
|
} finally {
|
|
ui.set_loading("manual_update_btn", false);
|
|
}
|
|
}
|
|
|
|
async onclick_start_timer_btn() {
|
|
ui.set_loading("start_timer_btn", true);
|
|
try {
|
|
const data = await api.start_timer()
|
|
api.update_metrics()
|
|
} catch (error) {
|
|
console.error(error);
|
|
} finally {
|
|
ui.set_loading("start_timer_btn", false);
|
|
}
|
|
}
|
|
|
|
async onclick_stop_timer_btn() {
|
|
ui.set_loading("stop_timer_btn", true);
|
|
try {
|
|
const data = await api.stop_timer()
|
|
api.update_metrics()
|
|
} catch (error) {
|
|
console.error(error);
|
|
} finally {
|
|
ui.set_loading("stop_timer_btn", false);
|
|
}
|
|
}
|
|
|
|
async onclick_domain_search_btn(){
|
|
ui.set_loading("domain_search_btn", true);
|
|
try {
|
|
const data = await api.domain_search()
|
|
ui.render_search_results(data.domains)
|
|
} catch (error) {
|
|
console.error(error);
|
|
} finally {
|
|
ui.set_loading("domain_search_btn", false);
|
|
}
|
|
}
|
|
|
|
async load_false_positive_controls(){
|
|
ui.set_loading("false_positive_load_btn", true);
|
|
ui.false_positive_actions.style.display = "none";
|
|
ui.event_container.innerHTML = "";
|
|
console.log(".")
|
|
try {
|
|
const data = await api.load_domain_fp()
|
|
if(!data){return;}
|
|
const parsed_data= {
|
|
domain: data.domain,
|
|
always_allow: data.always_allowed,
|
|
events: []
|
|
}
|
|
|
|
data.events.forEach(event => {
|
|
parsed_data.events.push({"id": event, "ignored": data.ignored_events.includes(event)});
|
|
})
|
|
ui.render_false_positive_controls(parsed_data)
|
|
} catch (error) {
|
|
console.error(error);
|
|
} finally {
|
|
ui.set_loading("false_positive_load_btn", false);
|
|
}
|
|
}
|
|
|
|
async onclick_false_positive_load_btn(){
|
|
await ui.load_false_positive_controls()
|
|
}
|
|
|
|
async onclick_event_button(event){
|
|
if (event.target === event.currentTarget) return;
|
|
const event_id = event.target.dataset.id;
|
|
const domain = event.target.dataset.domain;
|
|
const ignored = event.target.dataset.ignored === "true";
|
|
try {
|
|
if(ignored){
|
|
await api.reinstate_event(domain, event_id)
|
|
} else {
|
|
await api.ignore_event(domain, event_id)
|
|
}
|
|
await ui.load_false_positive_controls()
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
|
|
async onclick_always_allow_btn(event){
|
|
const domain = event.target.dataset.domain;
|
|
const always_allowed = event.target.dataset.always_allow === "true";
|
|
try {
|
|
await api.change_always_allow(domain, always_allowed)
|
|
await ui.load_false_positive_controls()
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
|
|
onclick_modal_button() {
|
|
document.getElementById("modal_backdrop").style.display = "none";
|
|
}
|
|
}
|
|
|
|
class API {
|
|
constructor() {
|
|
const self = this
|
|
this.update_metrics()
|
|
this.metrics_timer = setInterval(self.update_metrics, 5000)
|
|
}
|
|
|
|
update_metrics() {
|
|
axios.get(`misp/dashboard_metrics`)
|
|
.then(response => {
|
|
ui.update_metrics(response.data);
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async manual_update(published_timestamp = null){
|
|
const user = await auth.get_user()
|
|
return axios.put(
|
|
`misp/manual_update`,
|
|
{
|
|
"published_timestamp": published_timestamp
|
|
},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async start_timer(){
|
|
const user = await auth.get_user()
|
|
return axios.put(
|
|
`control/start_timer`,
|
|
{},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async stop_timer(){
|
|
const user = await auth.get_user()
|
|
return axios.put(
|
|
`control/stop_timer`,
|
|
{},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async domain_search(){
|
|
const user = await auth.get_user()
|
|
const search_term = document.getElementById("domain_search_input").value
|
|
return axios.get(
|
|
`misp/domain/search?domain=${search_term}`,
|
|
{},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async load_domain_fp(){
|
|
const user = await auth.get_user()
|
|
const search_term = document.getElementById("false_positive_domain").value
|
|
return axios.get(
|
|
`/misp/domain/details/${search_term}`,
|
|
{},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async ignore_event(domain, event_id){
|
|
const user = await auth.get_user()
|
|
return axios.patch(
|
|
`/misp/domain/events/${domain}/ignore?event=${event_id}`,
|
|
{},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async reinstate_event(domain, event_id){
|
|
const user = await auth.get_user()
|
|
return axios.patch(
|
|
`/misp/domain/events/${domain}/reinstate?event=${event_id}`,
|
|
{},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
async change_always_allow(domain, currently_allowed){
|
|
const user = await auth.get_user()
|
|
return axios.patch(
|
|
`/misp/domain/always_allowed/${domain}?allow=${!currently_allowed}`,
|
|
{},
|
|
{
|
|
headers: {
|
|
"Authorization": `Bearer ${user?.access_token}`
|
|
}
|
|
|
|
}
|
|
)
|
|
.then(response => {
|
|
return response.data
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
})
|
|
}
|
|
}
|
|
|
|
window.onload = () => {
|
|
window.ui = new UI()
|
|
window.auth = new Auth()
|
|
window.api = new API()
|
|
|
|
window.timer_running = false;
|
|
|
|
ui.sync_timer_buttons();
|
|
} |