Skip to content

Feature/threat actor config #2559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,47 +1,31 @@
package com.akto.action.threat_detection;

import java.util.List;

@lombok.Getter
@lombok.Setter
@lombok.AllArgsConstructor
@lombok.NoArgsConstructor
public class ThreatConfiguration {

private Actor actor;

@lombok.Getter
@lombok.Setter
@lombok.AllArgsConstructor
@lombok.NoArgsConstructor
public static class Actor {
private ActorId actorId;

public ActorId getActorId() {
return actorId;
}

public void setActorId(ActorId actorId) {
this.actorId = actorId;
}
private List<ActorId> actorId;
}

@lombok.Getter
@lombok.Setter
@lombok.AllArgsConstructor
@lombok.NoArgsConstructor
public static class ActorId {
private String type;
private String key;
private String kind;
private String pattern;

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}
}

public Actor getActor() {
return actor;
}

public void setActor(Actor actor) {
this.actor = actor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,6 @@ export default function LeftNav() {
url: "#",
key: "7",
subNavigationItems: [
{
label: "Threat Configuration",
onClick: () => {
navigate("/dashboard/protection/threat-configuration");
handleSelect("dashboard_threat_configuration");
setActive("active");
},
selected: leftNavSelected === "dashboard_threat_configuration",
},
{
label: "Threat Actors",
onClick: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ const SettingsLeftNav = () => {
onClick: () => navigate("/dashboard/settings/integrations/ci-cd")
}] : [];

const threatConfigArr = window?.STIGG_FEATURE_WISE_ALLOWED?.THREAT_DETECTION?.isGranted ? [{
label: 'Threat Configuration',
icon: AutomationFilledMajor,
selected: page === "threat-configuration",
onClick: () => navigate("/dashboard/settings/threat-configuration")
}] : [];

return (
<Navigation>
<Navigation.Section
Expand All @@ -80,6 +87,7 @@ const SettingsLeftNav = () => {
},
...usersArr,
...roleArr,
...threatConfigArr,
// {
// label: 'Alerts',
// icon: DiamondAlertMinor,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { useState, useEffect } from "react";
import func from "@/util/func"
import { LegacyCard, VerticalStack, HorizontalStack, Divider, Text, Button, Box, Autocomplete, TextField, HorizontalGrid } from "@shopify/polaris";
import api from "../../../pages/threat_detection/api.js";
import Dropdown from "../../../components/layouts/Dropdown.jsx";
import { DeleteMinor } from "@shopify/polaris-icons"

const ThreatActorConfigComponent = ({ title, description }) => {
const [actorIds, setActorIds] = useState([]);
const [isSaveDisabled, setIsSaveDisabled] = useState(true);

const fetchData = async () => {
const response = await api.fetchThreatConfiguration();
const actorIds = response?.threatConfiguration?.actor?.actorId || [];
setActorIds(actorIds);
};

const onSave = async () => {
const payload = {
actor: {
actorId: actorIds
}
};
await api.modifyThreatConfiguration(payload).then(() => {
try {
func.setToast(true, false, "Actor config saved successfully");
fetchData()
} catch (error) {
func.setToast(true, true, "Error saving actor config");
}
});
};

const addActorId = () => {
setActorIds([...actorIds, { kind: "hostname", pattern: "", key: "", type: "header" }]);
};

useEffect(() => {
fetchData().then(() => {
validateSaveButton(actorIds);
});
}, []);

useEffect(() => {
validateSaveButton(actorIds);
}, [actorIds]);

function TitleComponent({ title, description }) {
return (
<Box paddingBlockEnd="4">
<Text variant="headingMd">{title}</Text>
<Box paddingBlockStart="2">
<Text variant="bodyMd">{description}</Text>
</Box>
</Box>
)
}

const handleInputChange = (index, field, value) => {
setActorIds((prevActorIds) => {
const updatedActorIds = [...prevActorIds];
updatedActorIds[index] = { ...updatedActorIds[index], [field]: value };
validateSaveButton(updatedActorIds);
return updatedActorIds;
});
};

const handleDelete = (index) => {
setActorIds((prevActorIds) => {
const updatedActorIds = [...prevActorIds];
updatedActorIds.splice(index, 1);
validateSaveButton(updatedActorIds);
return updatedActorIds;
});
};

const validateSaveButton = (actorIds) => {
const hasEmptyFields = actorIds.some(actor => !actor.pattern || !actor.key);
setIsSaveDisabled(hasEmptyFields);
};

const dropdownOptions = [
{ value: "hostname", label: "Hostname" },
];

return (
<LegacyCard title={<TitleComponent title={title} description={description} />}
primaryFooterAction={{
content: 'Save',
onAction: onSave,
loading: false,
disabled: isSaveDisabled
}}
>
<Divider />
<LegacyCard.Section>
<VerticalStack gap="4">
{actorIds.map((actor, index) => (
<HorizontalGrid columns={"4"} key={index} gap="4">
<Dropdown
menuItems={dropdownOptions}
selected={(val) => handleInputChange(index, "kind", val)}
label="Select Type"
initial={() => actor.kind}
/>
<TextField
label="Hostname"
value={actor.pattern || ""}
onChange={(value) => handleInputChange(index, "pattern", value)}
placeholder="Enter hostname"
requiredIndicator={true}
/>
<TextField
label="Header Name"
value={actor.key || ""}
onChange={(value) => handleInputChange(index, "key", value)}
placeholder="Enter header name"
requiredIndicator={true}
/>
<Box paddingBlockStart="6" width="100px">
<Button icon={DeleteMinor} onClick={() => handleDelete(index)} />
</Box>
</HorizontalGrid>
))}
<HorizontalStack align="space-between">
<Button onClick={addActorId}>Add Actor ID</Button>
</HorizontalStack>
</VerticalStack>
</LegacyCard.Section>
</LegacyCard>
);
};

export default ThreatActorConfigComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import PageWithMultipleCards from "../../../components/layouts/PageWithMultipleCards"
import ThreatActorConfigComponent from "./ThreatActorConfig.jsx"

function ThreatConfiguration() {

const components = [
<ThreatActorConfigComponent
title={"Actor Information"}
description={"Configure threat actors. By default the actor is set to IP"}
key={"actorConfig"}
/>
];

return (
<PageWithMultipleCards
title={"Threat Configuration"}
isFirstPage={true}
divider={true}
components={components}
/>
)
}

export default ThreatConfiguration;

This file was deleted.

This file was deleted.

Loading
Loading