diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml index 302a14378f..6f900295ff 100644 --- a/.github/workflows/prod.yml +++ b/.github/workflows/prod.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: inputs: release_version: - required: true + required: true dashboard: type: boolean default: true @@ -23,11 +23,16 @@ on: type: boolean default: true description: Internal - protection: + threat_detection: type: boolean default: true - description: Protection - + description: Threat Detection Client + + threat_detection_backend: + type: boolean + default: true + description: Threat Deteection Backend + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" @@ -37,16 +42,16 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - uses: actions/setup-java@v2 with: - distribution: 'adopt' - java-version: '8' + distribution: "adopt" + java-version: "8" architecture: x64 - uses: actions/setup-node@v2 with: - node-version: '17' + node-version: "17" - uses: bufbuild/buf-action@v1 with: setup_only: true @@ -61,6 +66,14 @@ jobs: wget -O filetypes.json https://raw.githubusercontent.com/akto-api-security/akto/master/pii-types/filetypes.json wget -O automated_api_groups.csv https://raw.githubusercontent.com/akto-api-security/akto/master/automated-api-groups/automated-api-groups.csv + + - name: Create maxmind directory + run: mkdir -p ./apps/threat-detection-backend/src/main/resources/maxmind + - name: Download Maxmind Country database + working-directory: ./apps/threat-detection-backend/src/main/resources/maxmind + run: | + wget -O Geo-Country.mmdb https://raw.githubusercontent.com/akto-api-security/tests-library/refs/heads/master/resources/Geo-Country.mmdb + - name: Prepare Dashboard polaris UI working-directory: ./apps/dashboard/web/polaris_web run: npm install && export RELEASE_VERSION=${{github.event.inputs.release_version}} && npm run build @@ -79,7 +92,7 @@ jobs: DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}} DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}} run: | - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD + docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD - name: Build, tag, and push the image to DockerHub id: build-image-dockerhub @@ -98,36 +111,40 @@ jobs: docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/$ECR_REPOSITORY-dashboard:$IMAGE_TAG_1 -t $ECR_REGISTRY/$ECR_REPOSITORY-dashboard:$IMAGE_TAG_2 . --push echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY-dashboard:$IMAGE_TAG" fi - + if [[ "${{ github.event.inputs.testing }}" == "true" ]]; then cd ../testing docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-api-testing:$IMAGE_TAG_1 -t $ECR_REGISTRY/akto-api-testing:$IMAGE_TAG_2 . --push echo "::set-output name=image::$ECR_REGISTRY/akto-api-testing:$IMAGE_TAG" fi - + if [[ "${{ github.event.inputs.testing }}" == "true" ]]; then cd ../testing-cli docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-api-testing-cli:$IMAGE_TAG_1 -t $ECR_REGISTRY/akto-api-testing-cli:$IMAGE_TAG_2 . --push echo "::set-output name=image::$ECR_REGISTRY/akto-api-testing-cli:$IMAGE_TAG" fi - + if [[ "${{ github.event.inputs.billing }}" == "true" ]]; then cd ../billing docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-billing:$IMAGE_TAG_1 -t $ECR_REGISTRY/akto-billing:$IMAGE_TAG_2 . --push echo "::set-output name=image::$ECR_REGISTRY/akto-billing:$IMAGE_TAG" fi - + if [[ "${{ github.event.inputs.internal }}" == "true" ]]; then cd ../internal docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-internal:$IMAGE_TAG_1 -t $ECR_REGISTRY/akto-internal:$IMAGE_TAG_2 . --push echo "::set-output name=image::$ECR_REGISTRY/akto-internal:$IMAGE_TAG" fi - - if [[ "${{ github.event.inputs.protection }}" == "true" ]]; then - cd ../api-threat-detection - docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-api-protection:$IMAGE_TAG_1 -t $ECR_REGISTRY/akto-api-protection:$IMAGE_TAG_2 -t $ECR_REGISTRY/akto-api-protection:$IMAGE_TAG_3 . --push - echo "::set-output name=image::$ECR_REGISTRY/akto-api-protection:$IMAGE_TAG" - fi + + if [[ "${{ github.event.inputs.threat_detection}}" == "true" ]]; then + cd apps/threat-detection + docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-threat-detection:$IMAGE_TAG . --push + fi + + if [[ "${{ github.event.inputs.threat_detection_backend}}" == "true" ]]; then + cd ../threat-detection-backend + docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-threat-detection-backend:$IMAGE_TAG . --push + fi - name: Configure AWS Credentials for ECR uses: aws-actions/configure-aws-credentials@v1 with: @@ -138,7 +155,7 @@ jobs: id: login-ecr uses: aws-actions/amazon-ecr-login@v1 with: - mask-password: 'true' + mask-password: "true" registry-type: public - name: Push git tag diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 278e5afe54..e49403036c 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -41,9 +41,13 @@ jobs: wget -O general.json https://raw.githubusercontent.com/akto-api-security/pii-types/master/general.json wget -O fintech.json https://raw.githubusercontent.com/akto-api-security/akto/master/pii-types/fintech.json wget -O filetypes.json https://raw.githubusercontent.com/akto-api-security/akto/master/pii-types/filetypes.json - - name: Prepare Dashboard polaris UI - working-directory: ./apps/dashboard/web/polaris_web - run: npm install && export RELEASE_VERSION=${{steps.docker_tag.outputs.IMAGE_TAG}} && npm run build + - name: Create maxmind directory + run: mkdir -p ./apps/threat-detection-backend/src/main/resources/maxmind + - name: Download Maxmind Country database + working-directory: ./apps/threat-detection-backend/src/main/resources/maxmind + run: | + wget -O Geo-Country.mmdb https://raw.githubusercontent.com/akto-api-security/tests-library/refs/heads/master/resources/Geo-Country.mmdb + - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: @@ -51,10 +55,7 @@ jobs: aws-secret-access-key: ${{secrets.AWS_SECRET_ACCESS_KEY}} aws-region: ap-south-1 - - name: Deploy polaris site to S3 bucket - run: aws s3 sync ./apps/dashboard/web/polaris_web/web/dist s3://dashboard-on-cdn/polaris_web/${{steps.docker_tag.outputs.IMAGE_TAG}}/dist --delete - - - run: mvn package -Dakto-image-tag=${{ github.event.inputs.Tag }} -Dakto-build-time=$(eval "date +%s") -Dakto-release-version=${{steps.docker_tag.outputs.IMAGE_TAG}} + - run: mvn package -Dakto-image-tag=${{ github.event.inputs.Tag }} -Dakto-build-time=$(eval "date +%s") -Dakto-release-version=${{steps.docker_tag.outputs.IMAGE_TAG}} -DskipTests - name: DockerHub login env: DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}} @@ -84,10 +85,12 @@ jobs: docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-billing:$IMAGE_TAG . --push cd ../internal docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-internal:$IMAGE_TAG . --push - cd ../api-threat-detection - docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-api-protection:$IMAGE_TAG . --push cd ../source-code-analyser docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/source-code-analyser:$IMAGE_TAG . --push + cd ../threat-detection + docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-threat-detection:$IMAGE_TAG . --push + cd ../threat-detection-backend + docker buildx build --platform linux/arm64/v8,linux/amd64 -t $ECR_REGISTRY/akto-threat-detection-backend:$IMAGE_TAG . --push - name: Set up JDK 11 uses: actions/setup-java@v1 diff --git a/Makefile b/Makefile index b79b0909a1..f3912396b6 100644 --- a/Makefile +++ b/Makefile @@ -5,4 +5,4 @@ build: proto-gen mvn install -DskipTests build-clean: proto-gen - mvn clean install -DskipTests \ No newline at end of file + mvn clean install -DskipTests diff --git a/apps/api-threat-detection/Dockerfile b/apps/api-threat-detection/Dockerfile deleted file mode 100644 index 80e2dad6aa..0000000000 --- a/apps/api-threat-detection/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM openjdk -WORKDIR /app -COPY ./target/api-threat-detection-1.0-SNAPSHOT-jar-with-dependencies.jar /app/api-threat-detection-1.0-SNAPSHOT-jar-with-dependencies.jar -CMD "java" "-XX:+ExitOnOutOfMemoryError" "-jar" "/app/api-threat-detection-1.0-SNAPSHOT-jar-with-dependencies.jar" \ No newline at end of file diff --git a/apps/api-threat-detection/pom.xml b/apps/api-threat-detection/pom.xml deleted file mode 100644 index 64a129a342..0000000000 --- a/apps/api-threat-detection/pom.xml +++ /dev/null @@ -1,190 +0,0 @@ - - - 4.0.0 - - - com.akto.apps - apps - ${revision} - - - com.akto.apps.api-threat-detection - api-threat-detection - jar - - - - org.apache.commons - commons-lang3 - 3.12.0 - - - com.akto.libs.dao - dao - ${project.version} - - - com.akto.libs.utils - utils - ${project.version} - - - com.akto.apps.mini-runtime - mini-runtime - ${project.version} - - - com.akto.apps.testing - testing - ${project.version} - - - org.apache.httpcomponents - httpclient - 4.5.13 - - - org.jetbrains - annotations - RELEASE - compile - - - org.junit.jupiter - junit-jupiter-api - 5.4.2 - test - - - org.apache.kafka - kafka-clients - 3.0.0 - - - com.akto.libs.utils - utils - test-jar - ${project.version} - test - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 8 - 8 - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.0.1 - - - copy-dependencies - package - - copy-dependencies - - - - - - - src/main/java - src/test/java - - - src/main/resources - true - - **/version.txt - - - - - - - - normal - - true - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - package - - single - - - - - - com.akto.threat.detection.Main - - - - - jar-with-dependencies - - - - - - - - - - - devcontainer - - - - org.apache.maven.plugins - maven-jar-plugin - - api-threat-detection-1.0-SNAPSHOT-jar-with-dependencies - - - true - com.akto.threat.detection.Main - dependency-jars/ - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/dependency-jars/ - - - - - - - - - - diff --git a/apps/api-threat-detection/src/main/java/com/akto/filters/HttpCallFilter.java b/apps/api-threat-detection/src/main/java/com/akto/filters/HttpCallFilter.java deleted file mode 100644 index ecbc8e5ac7..0000000000 --- a/apps/api-threat-detection/src/main/java/com/akto/filters/HttpCallFilter.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.akto.filters; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -import com.akto.dao.context.Context; -import com.akto.dao.monitoring.FilterYamlTemplateDao; -import com.akto.data_actor.DataActor; -import com.akto.data_actor.DataActorFactory; -import com.akto.dto.ApiInfo.ApiInfoKey; -import com.akto.dto.HttpResponseParams; -import com.akto.dto.RawApi; -import com.akto.dto.bulk_updates.BulkUpdates; -import com.akto.dto.bulk_updates.UpdatePayload; -import com.akto.dto.monitoring.FilterConfig; -import com.akto.dto.test_editor.YamlTemplate; -import com.akto.dto.traffic.SuspectSampleData; -import com.akto.dto.type.URLMethods.Method; -import com.akto.hybrid_parsers.HttpCallParser; -import com.akto.log.LoggerMaker; -import com.akto.log.LoggerMaker.LogDb; -import com.akto.rules.TestPlugin; -import com.akto.runtime.policies.ApiAccessTypePolicy; -import com.akto.test_editor.execution.VariableResolver; -import com.akto.test_editor.filter.data_operands_impl.ValidationResult; - -public class HttpCallFilter { - private static final LoggerMaker loggerMaker = new LoggerMaker(HttpCallFilter.class, LogDb.THREAT_DETECTION); - - private Map apiFilters; - private List bulkUpdates = new ArrayList<>(); - private final int sync_threshold_count; - private final int sync_threshold_time; - private int last_synced; - private int sync_count; - private HttpCallParser httpCallParser; - - private static final int FILTER_REFRESH_INTERVAL = 10 * 60; - private int lastFilterFetch; - - private static final DataActor dataActor = DataActorFactory.fetchInstance(); - - public HttpCallFilter(int sync_threshold_count, int sync_threshold_time) { - apiFilters = new HashMap<>(); - bulkUpdates = new ArrayList<>(); - this.sync_threshold_count = sync_threshold_count; - this.sync_threshold_time = sync_threshold_time; - last_synced = 0; - sync_count = 0; - lastFilterFetch = 0; - httpCallParser = new HttpCallParser(sync_threshold_count, sync_threshold_time); - } - - public void filterFunction(List responseParams) { - - int now = Context.now(); - if ((lastFilterFetch + FILTER_REFRESH_INTERVAL) < now) { - // TODO: add support for only active templates. - List templates = dataActor.fetchFilterYamlTemplates(); - apiFilters = FilterYamlTemplateDao.instance.fetchFilterConfig(false, templates, false); - lastFilterFetch = now; - } - - if (apiFilters != null && !apiFilters.isEmpty()) { - for (HttpResponseParams responseParam : responseParams) { - for (Entry apiFilterEntry : apiFilters.entrySet()) { - try { - FilterConfig apiFilter = apiFilterEntry.getValue(); - String filterId = apiFilterEntry.getKey(); - String message = responseParam.getOrig(); - List sourceIps = ApiAccessTypePolicy.getSourceIps(responseParam); - RawApi rawApi = RawApi.buildFromMessage(message); - int apiCollectionId = httpCallParser.createApiCollectionId(responseParam); - responseParam.requestParams.setApiCollectionId(apiCollectionId); - String url = responseParam.getRequestParams().getURL(); - Method method = Method.fromString(responseParam.getRequestParams().getMethod()); - ApiInfoKey apiInfoKey = new ApiInfoKey(apiCollectionId, url, method); - Map varMap = apiFilter.resolveVarMap(); - VariableResolver.resolveWordList(varMap, new HashMap>() { - { - put(apiInfoKey, Arrays.asList(message)); - } - }, apiInfoKey); - String filterExecutionLogId = UUID.randomUUID().toString(); - ValidationResult res = TestPlugin.validateFilter(apiFilter.getFilter().getNode(), rawApi, - apiInfoKey, varMap, filterExecutionLogId); - if (res.getIsValid()) { - now = Context.now(); - SuspectSampleData sampleData = new SuspectSampleData( - sourceIps, apiCollectionId, url, method, - message, now, filterId); - Map filterMap = new HashMap<>(); - UpdatePayload updatePayload = new UpdatePayload("obj", sampleData, "set"); - ArrayList updates = new ArrayList<>(); - updates.add(updatePayload.toString()); - bulkUpdates.add(new BulkUpdates(filterMap, updates)); - } - } catch (Exception e) { - loggerMaker.errorAndAddToDb(e, String.format("Error in httpCallFilter %s", e.toString())); - } - } - } - } - sync_count = bulkUpdates.size(); - if (sync_count > 0 && (sync_count >= sync_threshold_count || - (Context.now() - last_synced) > sync_threshold_time)) { - List updates = new ArrayList<>(); - updates.addAll(bulkUpdates); - dataActor.bulkWriteSuspectSampleData(updates); - loggerMaker.infoAndAddToDb(String.format("Inserting %d records in SuspectSampleData", sync_count)); - last_synced = Context.now(); - sync_count = 0; - bulkUpdates.clear(); - } - } -} \ No newline at end of file diff --git a/apps/api-threat-detection/src/main/java/com/akto/threat/detection/Main.java b/apps/api-threat-detection/src/main/java/com/akto/threat/detection/Main.java deleted file mode 100644 index 28693a405c..0000000000 --- a/apps/api-threat-detection/src/main/java/com/akto/threat/detection/Main.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.akto.threat.detection; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.function.FailableFunction; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.kafka.clients.consumer.ConsumerRecords; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.akto.dao.context.Context; -import com.akto.dto.HttpResponseParams; -import com.akto.log.LoggerMaker; -import com.akto.log.LoggerMaker.LogDb; -import com.akto.metrics.AllMetrics; -import com.akto.runtime.utils.Utils; -import com.akto.traffic.KafkaRunner; -import com.akto.filters.HttpCallFilter; -import com.akto.parsers.HttpCallParser; - -public class Main { - private static final LogDb module = LogDb.THREAT_DETECTION; - private static final LoggerMaker loggerMaker = new LoggerMaker(Main.class, module); - private static final Logger logger = LoggerFactory.getLogger(Main.class); - private static final int sync_threshold_time = 120; - private static final int sync_threshold_count = 1000; - private static long lastSyncOffset = 0; - - public static void main(String[] args) { - - Map httpCallFilterMap = new HashMap<>(); - String topicName = System.getenv("AKTO_KAFKA_TOPIC_NAME"); - if (topicName == null) { - String defaultTopic = "akto.api.protection"; - loggerMaker.infoAndAddToDb(String.format("Kafka topic is not defined, using default topic : %s", defaultTopic)); - topicName = defaultTopic; - } - - FailableFunction, Void, Exception> func = records -> { - - long start = System.currentTimeMillis(); - - // TODO: what happens if exception - Map> responseParamsToAccountMap = new HashMap<>(); - for (ConsumerRecord r : records) { - HttpResponseParams httpResponseParams; - try { - Utils.printL(r.value()); - AllMetrics.instance.setRuntimeKafkaRecordCount(1); - AllMetrics.instance.setRuntimeKafkaRecordSize(r.value().length()); - lastSyncOffset++; - if (lastSyncOffset % 100 == 0) { - logger.info("Committing offset at position: " + lastSyncOffset); - } - httpResponseParams = HttpCallParser.parseKafkaMessage(r.value()); - } catch (Exception e) { - loggerMaker.errorAndAddToDb(e, "Error while parsing kafka message " + e, LogDb.RUNTIME); - continue; - } - String accountId = httpResponseParams.getAccountId(); - if (!responseParamsToAccountMap.containsKey(accountId)) { - responseParamsToAccountMap.put(accountId, new ArrayList<>()); - } - responseParamsToAccountMap.get(accountId).add(httpResponseParams); - } - - for (String accountId : responseParamsToAccountMap.keySet()) { - int accountIdInt; - try { - accountIdInt = Integer.parseInt(accountId); - } catch (Exception ignored) { - loggerMaker.errorAndAddToDb("Account id not string", LogDb.RUNTIME); - continue; - } - - Context.accountId.set(accountIdInt); - - if (!httpCallFilterMap.containsKey(accountId)) { - HttpCallFilter filter = new HttpCallFilter(sync_threshold_count, sync_threshold_time); - httpCallFilterMap.put(accountId, filter); - loggerMaker.infoAndAddToDb("New filter created for account: " + accountId); - } - - HttpCallFilter filter = httpCallFilterMap.get(accountId); - List accWiseResponse = responseParamsToAccountMap.get(accountId); - filter.filterFunction(accWiseResponse); - } - - AllMetrics.instance.setRuntimeProcessLatency(System.currentTimeMillis()-start); - - return null; - }; - KafkaRunner.processKafkaRecords(module, Arrays.asList(topicName), func); - } -} \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/leftnav/LeftNav.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/leftnav/LeftNav.js index 1e17e6f3ec..d35c8d770b 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/leftnav/LeftNav.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/leftnav/LeftNav.js @@ -1,194 +1,278 @@ -import {Navigation, Text} from "@shopify/polaris" -import {SettingsFilledMinor,AppsFilledMajor, InventoryFilledMajor, MarketingFilledMinor, FileFilledMinor, AnalyticsFilledMinor, ReportFilledMinor, DiamondAlertMinor} from "@shopify/polaris-icons" -import {useLocation, useNavigate} from "react-router-dom" +import { Navigation, Text } from "@shopify/polaris"; +import { + SettingsFilledMinor, + AppsFilledMajor, + InventoryFilledMajor, + MarketingFilledMinor, + FileFilledMinor, + AnalyticsFilledMinor, + ReportFilledMinor, + DiamondAlertMinor, +} from "@shopify/polaris-icons"; +import { useLocation, useNavigate } from "react-router-dom"; -import './LeftNav.css' -import PersistStore from "../../../../main/PersistStore" -import { useState } from "react" -import func from "@/util/func" - - -export default function LeftNav(){ +import "./LeftNav.css"; +import PersistStore from "../../../../main/PersistStore"; +import { useState } from "react"; +import func from "@/util/func"; +export default function LeftNav() { const navigate = useNavigate(); const location = useLocation(); - const currPathString = func.transformString(location.pathname) - - const[leftNavSelected, setLeftNavSelected] = useState(currPathString) + const currPathString = func.transformString(location.pathname); - const active = PersistStore((state) => state.active) - const setActive = PersistStore((state) => state.setActive) + const [leftNavSelected, setLeftNavSelected] = useState(currPathString); + + const active = PersistStore((state) => state.active); + const setActive = PersistStore((state) => state.setActive); const handleSelect = (selectedId) => { setLeftNavSelected(selectedId); }; - - const navigationMarkup = ( -
- - Quick Start, - icon: AppsFilledMajor, - onClick: ()=>{ - handleSelect("dashboard_quick_start") - setActive("normal") - navigate("/dashboard/quick-start") - }, - selected: leftNavSelected === 'dashboard_quick_start', - key: '1', + + const navigationMarkup = ( +
+ + + Quick Start + + ), + icon: AppsFilledMajor, + onClick: () => { + handleSelect("dashboard_quick_start"); + setActive("normal"); + navigate("/dashboard/quick-start"); }, - { - label: 'API Security Posture', - icon: ReportFilledMinor, - onClick: ()=>{ - handleSelect("dashboard_home") - navigate("/dashboard/home") - setActive("normal") - }, - selected: leftNavSelected === 'dashboard_home', - key: '2', + selected: leftNavSelected === "dashboard_quick_start", + key: "1", + }, + { + label: "API Security Posture", + icon: ReportFilledMinor, + onClick: () => { + handleSelect("dashboard_home"); + navigate("/dashboard/home"); + setActive("normal"); }, - { - url: '#', - label: API Discovery, - icon: InventoryFilledMajor, - onClick: ()=>{ - handleSelect("dashboard_observe_inventory") - navigate('/dashboard/observe/inventory') - setActive("normal") - }, - selected: leftNavSelected.includes('_observe'), - subNavigationItems:[ - { - label: 'API Collections', - onClick: ()=>{ - navigate('/dashboard/observe/inventory') - handleSelect("dashboard_observe_inventory") - setActive('active') - }, - selected: leftNavSelected === "dashboard_observe_inventory" - }, - { - label: 'API Changes', - onClick: ()=>{ - navigate('/dashboard/observe/changes') - handleSelect("dashboard_observe_changes") - setActive('active') - }, - selected: leftNavSelected === "dashboard_observe_changes" - }, - { - label: 'Sensitive Data', - onClick: ()=>{ - navigate('/dashboard/observe/sensitive') - handleSelect("dashboard_observe_sensitive") - setActive('active') - }, - selected: leftNavSelected === "dashboard_observe_sensitive" - } - ], - key: '3', + selected: leftNavSelected === "dashboard_home", + key: "2", + }, + { + url: "#", + label: ( + + API Discovery + + ), + icon: InventoryFilledMajor, + onClick: () => { + handleSelect("dashboard_observe_inventory"); + navigate("/dashboard/observe/inventory"); + setActive("normal"); }, - { - url: '#', - label: Testing, - icon: MarketingFilledMinor, - onClick: ()=>{ - navigate('/dashboard/testing/') - handleSelect('dashboard_testing') - setActive("normal") + selected: leftNavSelected.includes("_observe"), + subNavigationItems: [ + { + label: "API Collections", + onClick: () => { + navigate("/dashboard/observe/inventory"); + handleSelect("dashboard_observe_inventory"); + setActive("active"); + }, + selected: leftNavSelected === "dashboard_observe_inventory", }, - selected: leftNavSelected.includes('_testing'), - subNavigationItems:[ - { - label: 'Results', - onClick: ()=>{ - navigate('/dashboard/testing/') - handleSelect('dashboard_testing') - setActive('active') - }, - selected: leftNavSelected === 'dashboard_testing' + { + label: "API Changes", + onClick: () => { + navigate("/dashboard/observe/changes"); + handleSelect("dashboard_observe_changes"); + setActive("active"); }, - { - label: 'Test Roles', - onClick: ()=>{ - navigate('/dashboard/testing/roles') - handleSelect('dashboard_testing_roles') - setActive('active') - }, - selected: leftNavSelected === 'dashboard_testing_roles' + selected: leftNavSelected === "dashboard_observe_changes", + }, + { + label: "Sensitive Data", + onClick: () => { + navigate("/dashboard/observe/sensitive"); + handleSelect("dashboard_observe_sensitive"); + setActive("active"); }, - { - label: 'User Config', - onClick: ()=>{ - navigate('/dashboard/testing/user-config') - handleSelect('dashboard_testing_user_config') - setActive('active') - }, - selected: leftNavSelected === 'dashboard_testing_user_config' - } - ], - key: '4', - }, - { - label: Test Editor, - icon: FileFilledMinor, - onClick: ()=>{ - handleSelect("dashboard_test_editor") - navigate("/dashboard/test-editor/REMOVE_TOKENS") - setActive("normal") + selected: leftNavSelected === "dashboard_observe_sensitive", }, - selected: leftNavSelected.includes("dashboard_test_editor"), - key: '5', + ], + key: "3", + }, + { + url: "#", + label: ( + + Testing + + ), + icon: MarketingFilledMinor, + onClick: () => { + navigate("/dashboard/testing/"); + handleSelect("dashboard_testing"); + setActive("normal"); }, - { - label: Issues, - icon: AnalyticsFilledMinor, - onClick: ()=>{ - handleSelect("dashboard_issues") - navigate("/dashboard/issues") - setActive("normal") + selected: leftNavSelected.includes("_testing"), + subNavigationItems: [ + { + label: "Results", + onClick: () => { + navigate("/dashboard/testing/"); + handleSelect("dashboard_testing"); + setActive("active"); }, - selected: leftNavSelected === 'dashboard_issues', - key: '6', - }, - window?.STIGG_FEATURE_WISE_ALLOWED?.THREAT_DETECTION?.isGranted ? + selected: leftNavSelected === "dashboard_testing", + }, { - label: API Runtime Threats, - icon: DiamondAlertMinor, + label: "Test Roles", onClick: () => { - handleSelect("dashboard_threat_detection") - navigate("/dashboard/threat-detection") - setActive("normal") + navigate("/dashboard/testing/roles"); + handleSelect("dashboard_testing_roles"); + setActive("active"); }, - selected: leftNavSelected === 'dashboard_threat_detection', - key: '7', - } : {} - ]} - /> - Settings, - icon: SettingsFilledMinor, - onClick: ()=>{ - navigate("/dashboard/settings/about") - setActive("normal") + label: "User Config", + onClick: () => { + navigate("/dashboard/testing/user-config"); + handleSelect("dashboard_testing_user_config"); + setActive("active"); + }, + selected: leftNavSelected === "dashboard_testing_user_config", + }, + ], + key: "4", + }, + { + label: ( + + Test Editor + + ), + icon: FileFilledMinor, + onClick: () => { + handleSelect("dashboard_test_editor"); + navigate("/dashboard/test-editor/REMOVE_TOKENS"); + setActive("normal"); + }, + selected: leftNavSelected.includes("dashboard_test_editor"), + key: "5", + }, + { + label: ( + + Issues + + ), + icon: AnalyticsFilledMinor, + onClick: () => { + handleSelect("dashboard_issues"); + navigate("/dashboard/issues"); + setActive("normal"); + }, + selected: leftNavSelected === "dashboard_issues", + key: "6", + }, + window?.STIGG_FEATURE_WISE_ALLOWED?.THREAT_DETECTION?.isGranted + ? { + label: ( + + API Protection + + ), + icon: DiamondAlertMinor, + onClick: () => { + handleSelect("dashboard_threat_activity"); + navigate("/dashboard/protection/threat-activity"); + setActive("normal"); }, - selected: currPathString === 'settings', - key: '7', + selected: leftNavSelected.includes("_threat"), + url: "#", + key: "7", + subNavigationItems: [ + { + label: "Threat Activity", + onClick: () => { + navigate("/dashboard/protection/threat-activity"); + handleSelect("dashboard_threat_activity"); + setActive("active"); + }, + selected: + leftNavSelected === "dashboard_threat_activity", + }, + { + label: "Threat Actors", + onClick: () => { + navigate("/dashboard/protection/threat-actor"); + handleSelect("dashboard_threat_actor"); + setActive("active"); + }, + selected: leftNavSelected === "dashboard_threat_actor", + }, + { + label: "APIs Under Threat", + onClick: () => { + navigate("/dashboard/protection/threat-api"); + handleSelect("dashboard_threat_api"); + setActive("active"); + }, + selected: + leftNavSelected === "dashboard_threat_api", + }, + ], } - ]} - /> - -
- ); + : {}, + ]} + /> + + Settings + + ), + icon: SettingsFilledMinor, + onClick: () => { + navigate("/dashboard/settings/about"); + setActive("normal"); + }, + selected: currPathString === "settings", + key: "7", + }, + ]} + /> +
+
+ ); - return( - navigationMarkup - ) + return navigationMarkup; } - - diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/ThreatDetectionPage.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/ThreatDetectionPage.jsx index d762e307e7..d33f9594a7 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/ThreatDetectionPage.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/ThreatDetectionPage.jsx @@ -33,19 +33,15 @@ function ThreatDetectionPage() { const components = [ - horizontalComponent, , - ] return } diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/components/SusDataTable.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/components/SusDataTable.jsx index 4af459eab5..1bf2b2a759 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/components/SusDataTable.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/components/SusDataTable.jsx @@ -118,6 +118,7 @@ function SusDataTable({ currDateRange, rowClicked }) { let ret = res?.maliciousEvents.map((x) => { return { ...x, + id: x.id, actorComp: x?.actor, endpointComp: ( diff --git a/apps/dashboard/web/polaris_web/web/src/apps/main/App.js b/apps/dashboard/web/polaris_web/web/src/apps/main/App.js index 42bad35beb..eb6860b3ed 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/main/App.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/main/App.js @@ -175,21 +175,26 @@ const router = createBrowserRouter([ element: }, { - path: "quick-start", - element: , - }, - { - path:"threat-detection", - element: + path: "protection", + children: [ + { + path: "threat-activity", + element: + }, + { + path: "threat-api", + element: + }, + { + path: "threat-actor", + element: + } + ] }, { - path: "threat-api", - element: + path: "quick-start", + element: , }, - { - path: "threat-actor", - element: - } ] }, { diff --git a/apps/pom.xml b/apps/pom.xml index 20dcc1cb26..d6c4886121 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -1,7 +1,8 @@ - + 4.0.0 @@ -148,4 +149,4 @@ - + \ No newline at end of file diff --git a/apps/threat-detection-backend/.gitignore b/apps/threat-detection-backend/.gitignore new file mode 100644 index 0000000000..1ffb9e7e9d --- /dev/null +++ b/apps/threat-detection-backend/.gitignore @@ -0,0 +1 @@ +*.mmdb \ No newline at end of file diff --git a/apps/threat-detection-backend/Dockerfile b/apps/threat-detection-backend/Dockerfile new file mode 100644 index 0000000000..e2ec8f2cbf --- /dev/null +++ b/apps/threat-detection-backend/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk +WORKDIR /app +COPY ./target/threat-detection-backend-1.0-SNAPSHOT-jar-with-dependencies.jar /app/threat-detection-backend-1.0-SNAPSHOT-jar-with-dependencies.jar +CMD "java" "-XX:+ExitOnOutOfMemoryError" "-jar" "/app/threat-detection-backend-1.0-SNAPSHOT-jar-with-dependencies.jar" \ No newline at end of file diff --git a/apps/threat-detection-backend/pom.xml b/apps/threat-detection-backend/pom.xml new file mode 100644 index 0000000000..b7e4129a9c --- /dev/null +++ b/apps/threat-detection-backend/pom.xml @@ -0,0 +1,210 @@ + + + 4.0.0 + + + 9.4.27.v20200227 + 4.5.11 + + + + com.akto.apps + apps + ${revision} + + + com.akto.apps.threat-detection-backend + threat-detection-backend + jar + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + com.akto.libs.dao + dao + ${project.version} + + + com.akto.libs.utils + utils + ${project.version} + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + + org.jetbrains + annotations + RELEASE + compile + + + org.junit.jupiter + junit-jupiter-api + 5.4.2 + test + + + com.akto.libs.utils + utils + test-jar + ${project.version} + test + + + com.akto.libs.protobuf + protobuf + 1.0-SNAPSHOT + compile + + + + io.vertx + vertx-web + ${vertex.version} + + + + io.vertx + vertx-core + ${vertex.version} + + + + + com.maxmind.geoip2 + geoip2 + 2.15.0 + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + com.akto.threat.backend.Main + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 8 + 8 + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.1 + + + copy-dependencies + package + + copy-dependencies + + + + + + + src/main/java + src/test/java + + + src/main/resources + + + + + + + normal + + true + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + + + com.akto.threat.backend.Main + + + + + jar-with-dependencies + + + + + + + + + + + devcontainer + + + + org.apache.maven.plugins + maven-jar-plugin + + api-threat-detection-1.0-SNAPSHOT-jar-with-dependencies + + + true + com.akto.threat.backend.Main + dependency-jars/ + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory}/dependency-jars/ + + + + + + + + + + \ No newline at end of file diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/BackendVerticle.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/BackendVerticle.java new file mode 100644 index 0000000000..e29a6ea135 --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/BackendVerticle.java @@ -0,0 +1,80 @@ +package com.akto.threat.backend; + +import com.akto.threat.backend.interceptors.AuthenticationInterceptor; +import com.akto.threat.backend.router.DashboardRouter; +import com.akto.threat.backend.router.ThreatDetectionRouter; +import com.akto.threat.backend.service.MaliciousEventService; +import com.akto.threat.backend.service.ThreatActorService; +import com.akto.threat.backend.service.ThreatApiService; +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Vertx; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.BodyHandler; + +public class BackendVerticle extends AbstractVerticle { + + private final MaliciousEventService maliciousEventService; + private final ThreatActorService threatActorService; + private final ThreatApiService threatApiService; + + public BackendVerticle( + MaliciousEventService maliciousEventService, + ThreatActorService threatActorService, + ThreatApiService threatApiService) { + this.maliciousEventService = maliciousEventService; + this.threatActorService = threatActorService; + this.threatApiService = threatApiService; + } + + @Override + public void start() { + Vertx vertx = Vertx.vertx(); + + // Create the router + Router router = Router.router(vertx); + + Router api = Router.router(vertx); + + api.route().handler(BodyHandler.create()); + api.route().handler(new AuthenticationInterceptor()); + + Router dashboardRouter = + new DashboardRouter(maliciousEventService, threatActorService, threatApiService) + .setup(vertx); + Router threatDetectionRouter = new ThreatDetectionRouter(maliciousEventService).setup(vertx); + + api.route("/dashboard/*").subRouter(dashboardRouter); + api.route("/threat_detection/*").subRouter(threatDetectionRouter); + + router.route("/api/*").subRouter(api); + + // Start the HTTP server + + router.route("/health").handler(ctx -> ctx.response().setStatusCode(200).end("OK")); + + // 404 handler + router + .route() + .handler( + rc -> { + rc.response().setStatusCode(404).end("404 - Not Found: " + rc.request().uri()); + }); + + int port = + Integer.parseInt( + System.getenv().getOrDefault("THREAT_DETECTION_BACKEND_SERVER_PORT", "9090")); + + vertx + .createHttpServer() + .requestHandler(router) + .listen(port) + .onSuccess( + server -> { + System.out.println("HTTP server started on port " + port); + }) + .onFailure( + err -> { + System.err.println("Failed to start HTTP server: " + err.getMessage()); + }); + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/Main.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/Main.java new file mode 100644 index 0000000000..d9fd627e8b --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/Main.java @@ -0,0 +1,85 @@ +package com.akto.threat.backend; + +import static org.bson.codecs.configuration.CodecRegistries.fromProviders; +import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; + +import com.akto.DaoInit; +import com.akto.kafka.KafkaConfig; +import com.akto.kafka.KafkaConsumerConfig; +import com.akto.kafka.KafkaProducerConfig; +import com.akto.threat.backend.client.IPLookupClient; +import com.akto.threat.backend.service.MaliciousEventService; +import com.akto.threat.backend.service.ThreatActorService; +import com.akto.threat.backend.service.ThreatApiService; +import com.akto.threat.backend.tasks.FlushMessagesToDB; +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.ReadPreference; +import com.mongodb.WriteConcern; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import org.apache.commons.io.IOUtils; +import org.bson.codecs.configuration.CodecRegistry; +import org.bson.codecs.pojo.PojoCodecProvider; + +public class Main { + public static void main(String[] args) throws Exception { + + DaoInit.init(new ConnectionString(System.getenv("AKTO_MONGO_CONN"))); + + ConnectionString connectionString = + new ConnectionString(System.getenv("AKTO_THREAT_PROTECTION_MONGO_CONN")); + CodecRegistry pojoCodecRegistry = + fromProviders(PojoCodecProvider.builder().automatic(true).build()); + CodecRegistry codecRegistry = + fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry); + MongoClientSettings clientSettings = + MongoClientSettings.builder() + .readPreference(ReadPreference.secondary()) + .writeConcern(WriteConcern.ACKNOWLEDGED) + .applyConnectionString(connectionString) + .codecRegistry(codecRegistry) + .build(); + + MongoClient threatProtectionMongo = MongoClients.create(clientSettings); + KafkaConfig internalKafkaConfig = + KafkaConfig.newBuilder() + .setBootstrapServers(System.getenv("THREAT_EVENTS_KAFKA_BROKER_URL")) + .setGroupId("akto.threat_protection.flush_db") + .setConsumerConfig( + KafkaConsumerConfig.newBuilder() + .setMaxPollRecords(100) + .setPollDurationMilli(100) + .build()) + .setProducerConfig( + KafkaProducerConfig.newBuilder().setBatchSize(100).setLingerMs(1000).build()) + .build(); + + IPLookupClient ipLookupClient = new IPLookupClient(getMaxmindFile()); + + new FlushMessagesToDB(internalKafkaConfig, threatProtectionMongo).run(); + + MaliciousEventService maliciousEventService = + new MaliciousEventService(internalKafkaConfig, threatProtectionMongo, ipLookupClient); + + ThreatActorService threatActorService = new ThreatActorService(threatProtectionMongo); + ThreatApiService threatApiService = new ThreatApiService(threatProtectionMongo); + + new BackendVerticle(maliciousEventService, threatActorService, threatApiService).start(); + } + + private static File getMaxmindFile() throws IOException { + File maxmindTmpFile = File.createTempFile("tmp-geo-country", ".mmdb"); + maxmindTmpFile.deleteOnExit(); + + try (FileOutputStream fos = new FileOutputStream(maxmindTmpFile)) { + IOUtils.copy( + Main.class.getClassLoader().getResourceAsStream("maxmind/Geo-Country.mmdb"), fos); + } + + return maxmindTmpFile; + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/client/IPLookupClient.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/client/IPLookupClient.java new file mode 100644 index 0000000000..10b64166ab --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/client/IPLookupClient.java @@ -0,0 +1,26 @@ +package com.akto.threat.backend.client; + +import com.maxmind.geoip2.DatabaseReader; +import com.maxmind.geoip2.model.CountryResponse; +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.util.Optional; + +public class IPLookupClient { + private final DatabaseReader db; + + public IPLookupClient(File dbFile) throws IOException { + this.db = new DatabaseReader.Builder(dbFile).build(); + } + + public Optional getCountryISOCodeGivenIp(String ip) { + try { + InetAddress ipAddr = InetAddress.getByName(ip); + CountryResponse resp = db.country(ipAddr); + return Optional.of(resp.getCountry().getIsoCode()); + } catch (Exception e) { + return Optional.empty(); + } + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/constants/KafkaTopic.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/constants/KafkaTopic.java new file mode 100644 index 0000000000..3f056fc39a --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/constants/KafkaTopic.java @@ -0,0 +1,7 @@ +package com.akto.threat.backend.constants; + +public class KafkaTopic { + public static class ThreatDetection { + public static final String INTERNAL_DB_MESSAGES = "akto.threat_detection.internal_db_messages"; + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/constants/MongoDBCollection.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/constants/MongoDBCollection.java new file mode 100644 index 0000000000..879af94557 --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/constants/MongoDBCollection.java @@ -0,0 +1,9 @@ +package com.akto.threat.backend.constants; + +public class MongoDBCollection { + public static class ThreatDetection { + public static final String MALICIOUS_EVENTS = "malicious_events"; + public static final String AGGREGATE_SAMPLE_MALICIOUS_REQUESTS = + "aggregate_sample_malicious_requests"; + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/db/AggregateSampleMaliciousEventModel.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/db/AggregateSampleMaliciousEventModel.java new file mode 100644 index 0000000000..cc5f876d8b --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/db/AggregateSampleMaliciousEventModel.java @@ -0,0 +1,138 @@ +package com.akto.threat.backend.db; + +import com.akto.dto.type.URLMethods.Method; +import java.util.UUID; + +public class AggregateSampleMaliciousEventModel { + + private String id; + private String filterId; + private String actor; + private String ip; + private String url; + private String country; + private Method method; + private String orig; + private int apiCollectionId; + private long requestTime; + + public AggregateSampleMaliciousEventModel() {} + + private AggregateSampleMaliciousEventModel(Builder builder) { + this.id = UUID.randomUUID().toString(); + this.filterId = builder.filterId; + this.actor = builder.actor; + this.ip = builder.ip; + this.country = builder.country; + this.method = builder.method; + this.orig = builder.orig; + this.requestTime = builder.requestTime; + this.url = builder.url; + this.apiCollectionId = builder.apiCollectionId; + } + + public static class Builder { + public int apiCollectionId; + private String filterId; + private String actor; + private String ip; + private String country; + private String url; + private Method method; + private String orig; + private long requestTime; + + public Builder setFilterId(String filterId) { + this.filterId = filterId; + return this; + } + + public Builder setActor(String actor) { + this.actor = actor; + return this; + } + + public Builder setIp(String ip) { + this.ip = ip; + return this; + } + + public Builder setCountry(String country) { + this.country = country; + return this; + } + + public Builder setUrl(String url) { + this.url = url; + return this; + } + + public Builder setMethod(Method method) { + this.method = method; + return this; + } + + public Builder setOrig(String orig) { + this.orig = orig; + return this; + } + + public Builder setRequestTime(long requestTime) { + this.requestTime = requestTime; + return this; + } + + public Builder setApiCollectionId(int apiCollectionId) { + this.apiCollectionId = apiCollectionId; + return this; + } + + public AggregateSampleMaliciousEventModel build() { + return new AggregateSampleMaliciousEventModel(this); + } + } + + public String getId() { + return id; + } + + public String getFilterId() { + return filterId; + } + + public String getActor() { + return actor; + } + + public String getIp() { + return ip; + } + + public String getUrl() { + return url; + } + + public String getCountry() { + return country; + } + + public Method getMethod() { + return method; + } + + public String getOrig() { + return orig; + } + + public long getRequestTime() { + return requestTime; + } + + public int getApiCollectionId() { + return apiCollectionId; + } + + public static Builder newBuilder() { + return new Builder(); + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/db/MaliciousEventModel.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/db/MaliciousEventModel.java new file mode 100644 index 0000000000..83aeb1c148 --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/db/MaliciousEventModel.java @@ -0,0 +1,231 @@ +package com.akto.threat.backend.db; + +import com.akto.dto.type.URLMethods; +import java.util.UUID; + +public class MaliciousEventModel { + + private String id; + private String filterId; + private String actor; + private String latestApiIp; + private String latestApiEndpoint; + private String country; + private URLMethods.Method latestApiMethod; + private String latestApiOrig; + private long detectedAt; + private int latestApiCollectionId; + private EventType eventType; + private String category; + private String subCategory; + + public enum EventType { + SINGLE, + AGGREGATED + } + + public MaliciousEventModel() {} + + private MaliciousEventModel(Builder builder) { + this.id = UUID.randomUUID().toString(); + this.filterId = builder.filterId; + this.actor = builder.actor; + this.latestApiIp = builder.latestApiIp; + this.country = builder.country; + this.latestApiEndpoint = builder.latestApiEndpoint; + this.latestApiMethod = builder.latestApiMethod; + this.latestApiOrig = builder.latestApiOrig; + this.latestApiCollectionId = builder.latestApiCollectionId; + this.detectedAt = builder.detectedAt; + this.eventType = builder.eventType; + this.category = builder.category; + this.subCategory = builder.subCategory; + } + + public static class Builder { + public EventType eventType; + private String filterId; + private String actor; + private String latestApiIp; + private String country; + private String latestApiEndpoint; + private URLMethods.Method latestApiMethod; + private String latestApiOrig; + private int latestApiCollectionId; + private long detectedAt; + private String category; + private String subCategory; + + public Builder setFilterId(String filterId) { + this.filterId = filterId; + return this; + } + + public Builder setActor(String actor) { + this.actor = actor; + return this; + } + + public Builder setLatestApiIp(String ip) { + this.latestApiIp = ip; + return this; + } + + public Builder setCountry(String country) { + this.country = country; + return this; + } + + public Builder setLatestApiEndpoint(String latestApiEndpoint) { + this.latestApiEndpoint = latestApiEndpoint; + return this; + } + + public Builder setLatestApiMethod(URLMethods.Method latestApiMethod) { + this.latestApiMethod = latestApiMethod; + return this; + } + + public Builder setLatestApiOrig(String latestApiOrig) { + this.latestApiOrig = latestApiOrig; + return this; + } + + public Builder setDetectedAt(long detectedAt) { + this.detectedAt = detectedAt; + return this; + } + + public Builder setLatestApiCollectionId(int latestApiCollectionId) { + this.latestApiCollectionId = latestApiCollectionId; + return this; + } + + public Builder setEventType(EventType eventType) { + this.eventType = eventType; + return this; + } + + public Builder setCategory(String category) { + this.category = category; + return this; + } + + public Builder setSubCategory(String subCategory) { + this.subCategory = subCategory; + return this; + } + + public MaliciousEventModel build() { + return new MaliciousEventModel(this); + } + } + + public String getId() { + return id; + } + + public String getFilterId() { + return filterId; + } + + public String getActor() { + return actor; + } + + public String getLatestApiIp() { + return latestApiIp; + } + + public String getLatestApiEndpoint() { + return latestApiEndpoint; + } + + public String getCountry() { + return country; + } + + public URLMethods.Method getLatestApiMethod() { + return latestApiMethod; + } + + public String getLatestApiOrig() { + return latestApiOrig; + } + + public long getDetectedAt() { + return detectedAt; + } + + public int getLatestApiCollectionId() { + return latestApiCollectionId; + } + + public EventType getEventType() { + return eventType; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public void setId(String id) { + this.id = id; + } + + public void setFilterId(String filterId) { + this.filterId = filterId; + } + + public void setActor(String actor) { + this.actor = actor; + } + + public void setLatestApiIp(String ip) { + this.latestApiIp = ip; + } + + public void setLatestApiEndpoint(String latestApiEndpoint) { + this.latestApiEndpoint = latestApiEndpoint; + } + + public void setCountry(String country) { + this.country = country; + } + + public void setLatestApiMethod(URLMethods.Method latestApiMethod) { + this.latestApiMethod = latestApiMethod; + } + + public void setLatestApiOrig(String latestApiOrig) { + this.latestApiOrig = latestApiOrig; + } + + public void setDetectedAt(long detectedAt) { + this.detectedAt = detectedAt; + } + + public void setLatestApiCollectionId(int latestApiCollectionId) { + this.latestApiCollectionId = latestApiCollectionId; + } + + public void setEventType(EventType eventType) { + this.eventType = eventType; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getSubCategory() { + return subCategory; + } + + public void setSubCategory(String subCategory) { + this.subCategory = subCategory; + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/interceptors/AuthenticationInterceptor.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/interceptors/AuthenticationInterceptor.java new file mode 100644 index 0000000000..f17f7bdd97 --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/interceptors/AuthenticationInterceptor.java @@ -0,0 +1,69 @@ +package com.akto.threat.backend.interceptors; + +import com.akto.dao.ConfigsDao; +import com.akto.dto.Config; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.vertx.core.Handler; +import io.vertx.ext.web.RoutingContext; +import java.io.IOException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +public class AuthenticationInterceptor implements Handler { + + private static PublicKey getPublicKey() + throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { + Config.HybridSaasConfig config; + try { + config = + (Config.HybridSaasConfig) + ConfigsDao.instance.findOne("_id", Config.ConfigType.HYBRID_SAAS.name()); + } catch (Exception e) { + System.out.println(e); + throw e; + } + String rsaPublicKey = config.getPublicKey(); + + rsaPublicKey = rsaPublicKey.replace("-----BEGIN PUBLIC KEY-----", ""); + rsaPublicKey = rsaPublicKey.replace("-----END PUBLIC KEY-----", ""); + rsaPublicKey = rsaPublicKey.replace("\n", ""); + byte[] decoded = Base64.getDecoder().decode(rsaPublicKey); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoded); + KeyFactory kf = KeyFactory.getInstance("RSA"); + + try { + return kf.generatePublic(keySpec); + } catch (Exception e) { + System.out.println(e); + throw e; + } + } + + @Override + public void handle(RoutingContext context) { + String token = context.request().getHeader("Authorization"); + if (token == null || !token.startsWith("Bearer ")) { + context.response().setStatusCode(401).end("Missing or Invalid Authorization header"); + return; + } + + token = token.substring(7); + + try { + PublicKey publicKey = getPublicKey(); + Jws claims = + Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token); + int accountId = (int) claims.getBody().get("accountId"); + context.put("accountId", accountId + ""); + context.next(); + } catch (Exception e) { + context.response().setStatusCode(401).end("Missing or Invalid Authorization header"); + } + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/interceptors/Constants.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/interceptors/Constants.java new file mode 100644 index 0000000000..7c5eb033ea --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/interceptors/Constants.java @@ -0,0 +1,16 @@ +package com.akto.threat.backend.interceptors; + +import static io.grpc.Metadata.ASCII_STRING_MARSHALLER; + +import io.grpc.Context; +import io.grpc.Metadata; + +public class Constants { + public static final Metadata.Key AUTHORIZATION_METADATA_KEY = + Metadata.Key.of("Authorization", ASCII_STRING_MARSHALLER); + public static final Context.Key ACCOUNT_ID_CONTEXT_KEY = Context.key("accountId"); + + private Constants() { + throw new AssertionError(); + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/ARouter.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/ARouter.java new file mode 100644 index 0000000000..b4e54e8109 --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/ARouter.java @@ -0,0 +1,9 @@ +package com.akto.threat.backend.router; + +import io.vertx.core.Vertx; +import io.vertx.ext.web.Router; + +public interface ARouter { + + Router setup(Vertx vertx); +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/DashboardRouter.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/DashboardRouter.java new file mode 100644 index 0000000000..03705b6b4a --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/DashboardRouter.java @@ -0,0 +1,138 @@ +package com.akto.threat.backend.router; + +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.FetchAlertFiltersRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListMaliciousRequestsRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatActorsRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatApiRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ThreatActorByCountryRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ThreatCategoryWiseCountRequest; +import com.akto.proto.utils.ProtoMessageUtils; +import com.akto.threat.backend.service.MaliciousEventService; +import com.akto.threat.backend.service.ThreatActorService; +import com.akto.threat.backend.service.ThreatApiService; +import io.vertx.core.Vertx; +import io.vertx.ext.web.RequestBody; +import io.vertx.ext.web.Router; + +public class DashboardRouter implements ARouter { + + private final MaliciousEventService dsService; + private final ThreatActorService threatActorService; + private final ThreatApiService threatApiService; + + public DashboardRouter( + MaliciousEventService dsService, + ThreatActorService threatActorService, + ThreatApiService threatApiService + ) { + this.dsService = dsService; + this.threatActorService = threatActorService; + this.threatApiService = threatApiService; + } + + @Override + public Router setup(Vertx vertx) { + Router router = Router.router(vertx); + + router + .get("/fetch_filters") + .blockingHandler(ctx -> { + ProtoMessageUtils.toString( + dsService.fetchAlertFilters( + ctx.get("accountId"), + FetchAlertFiltersRequest.newBuilder().build() + ) + ).ifPresent(s -> ctx.response().setStatusCode(200).end(s)); + }); + + router + .post("/list_malicious_requests") + .blockingHandler(ctx -> { + RequestBody reqBody = ctx.body(); + ListMaliciousRequestsRequest req = ProtoMessageUtils.< + ListMaliciousRequestsRequest + >toProtoMessage( + ListMaliciousRequestsRequest.class, + reqBody.asString() + ).orElse(null); + + if (req == null) { + ctx.response().setStatusCode(400).end("Invalid request"); + return; + } + + ProtoMessageUtils.toString( + dsService.listMaliciousRequests(ctx.get("accountId"), req) + ).ifPresent(s -> ctx.response().setStatusCode(200).end(s)); + }); + + router + .post("/list_threat_actors") + .blockingHandler(ctx -> { + RequestBody reqBody = ctx.body(); + ListThreatActorsRequest req = ProtoMessageUtils.< + ListThreatActorsRequest + >toProtoMessage( + ListThreatActorsRequest.class, + reqBody.asString() + ).orElse(null); + + if (req == null) { + ctx.response().setStatusCode(400).end("Invalid request"); + return; + } + + ProtoMessageUtils.toString( + threatActorService.listThreatActors( + ctx.get("accountId"), + req + ) + ).ifPresent(s -> ctx.response().setStatusCode(200).end(s)); + }); + + router + .post("/list_threat_apis") + .blockingHandler(ctx -> { + RequestBody reqBody = ctx.body(); + ListThreatApiRequest req = ProtoMessageUtils.< + ListThreatApiRequest + >toProtoMessage( + ListThreatApiRequest.class, + reqBody.asString() + ).orElse(null); + + if (req == null) { + ctx.response().setStatusCode(400).end("Invalid request"); + return; + } + + ProtoMessageUtils.toString( + threatApiService.listThreatApis(ctx.get("accountId"), req) + ).ifPresent(s -> ctx.response().setStatusCode(200).end(s)); + }); + + router + .get("/get_actors_count_per_country") + .blockingHandler(ctx -> { + ProtoMessageUtils.toString( + threatActorService.getThreatActorByCountry( + ctx.get("accountId"), + ThreatActorByCountryRequest.newBuilder().build() + ) + ).ifPresent(s -> ctx.response().setStatusCode(200).end(s)); + }); + + router + .get("/get_subcategory_wise_count") + .blockingHandler(ctx -> { + ProtoMessageUtils.toString( + threatApiService.getSubCategoryWiseCount( + ctx.get("accountId"), + ThreatCategoryWiseCountRequest.newBuilder().build() + ) + ).ifPresent(s -> ctx.response().setStatusCode(200).end(s)); + }); + + return router; + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/ThreatDetectionRouter.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/ThreatDetectionRouter.java new file mode 100644 index 0000000000..67deec84dc --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/router/ThreatDetectionRouter.java @@ -0,0 +1,43 @@ +package com.akto.threat.backend.router; + +import com.akto.proto.generated.threat_detection.service.malicious_alert_service.v1.RecordMaliciousEventRequest; +import com.akto.proto.utils.ProtoMessageUtils; +import com.akto.threat.backend.service.MaliciousEventService; +import io.vertx.core.Vertx; +import io.vertx.ext.web.RequestBody; +import io.vertx.ext.web.Router; + +public class ThreatDetectionRouter implements ARouter { + + private final MaliciousEventService maliciousEventService; + + public ThreatDetectionRouter(MaliciousEventService maliciousEventService) { + this.maliciousEventService = maliciousEventService; + } + + @Override + public Router setup(Vertx vertx) { + Router router = Router.router(vertx); + + router + .post("/record_malicious_event") + .blockingHandler( + ctx -> { + RequestBody reqBody = ctx.body(); + RecordMaliciousEventRequest req = + ProtoMessageUtils.toProtoMessage( + RecordMaliciousEventRequest.class, reqBody.asString()) + .orElse(null); + + if (req == null) { + ctx.response().setStatusCode(400).end("Invalid request"); + return; + } + + maliciousEventService.recordMaliciousEvent(ctx.get("accountId"), req); + ctx.response().setStatusCode(202).end(); + }); + + return router; + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/MaliciousEventService.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/MaliciousEventService.java new file mode 100644 index 0000000000..f69640a7fa --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/MaliciousEventService.java @@ -0,0 +1,179 @@ +package com.akto.threat.backend.service; + +import com.akto.dto.type.URLMethods; +import com.akto.kafka.Kafka; +import com.akto.kafka.KafkaConfig; +import com.akto.proto.generated.threat_detection.message.malicious_event.event_type.v1.EventType; +import com.akto.proto.generated.threat_detection.message.malicious_event.v1.MaliciousEventMessage; +import com.akto.proto.generated.threat_detection.message.sample_request.v1.SampleMaliciousRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.FetchAlertFiltersRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.FetchAlertFiltersResponse; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListMaliciousRequestsRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListMaliciousRequestsResponse; +import com.akto.proto.generated.threat_detection.service.malicious_alert_service.v1.RecordMaliciousEventRequest; +import com.akto.threat.backend.client.IPLookupClient; +import com.akto.threat.backend.constants.KafkaTopic; +import com.akto.threat.backend.constants.MongoDBCollection; +import com.akto.threat.backend.db.AggregateSampleMaliciousEventModel; +import com.akto.threat.backend.db.MaliciousEventModel; +import com.akto.threat.backend.utils.KafkaUtils; +import com.mongodb.BasicDBObject; +import com.mongodb.client.DistinctIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.model.Filters; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.bson.conversions.Bson; + +public class MaliciousEventService { + + private final Kafka kafka; + private MongoClient mongoClient; + private IPLookupClient ipLookupClient; + + public MaliciousEventService( + KafkaConfig kafkaConfig, MongoClient mongoClient, IPLookupClient ipLookupClient) { + this.kafka = new Kafka(kafkaConfig); + this.mongoClient = mongoClient; + this.ipLookupClient = ipLookupClient; + } + + public void recordMaliciousEvent(String accountId, RecordMaliciousEventRequest request) { + System.out.println("Received malicious event: " + request); + + MaliciousEventMessage evt = request.getMaliciousEvent(); + String actor = evt.getActor(); + String filterId = evt.getFilterId(); + + EventType eventType = evt.getEventType(); + + MaliciousEventModel.EventType maliciousEventType = + EventType.EVENT_TYPE_AGGREGATED.equals(eventType) + ? MaliciousEventModel.EventType.AGGREGATED + : MaliciousEventModel.EventType.SINGLE; + + MaliciousEventModel maliciousEventModel = + MaliciousEventModel.newBuilder() + .setDetectedAt(evt.getDetectedAt()) + .setActor(actor) + .setFilterId(filterId) + .setLatestApiEndpoint(evt.getLatestApiEndpoint()) + .setLatestApiMethod(URLMethods.Method.fromString(evt.getLatestApiMethod())) + .setLatestApiOrig(evt.getLatestApiPayload()) + .setLatestApiCollectionId(evt.getLatestApiCollectionId()) + .setEventType(maliciousEventType) + .setLatestApiIp(evt.getLatestApiIp()) + .setCountry( + this.ipLookupClient.getCountryISOCodeGivenIp(evt.getLatestApiIp()).orElse("")) + .setCategory(evt.getCategory()) + .setSubCategory(evt.getSubCategory()) + .build(); + + if (MaliciousEventModel.EventType.AGGREGATED.equals(maliciousEventType)) { + List events = new ArrayList<>(); + for (SampleMaliciousRequest sampleReq : request.getSampleRequestsList()) { + events.add( + AggregateSampleMaliciousEventModel.newBuilder() + .setActor(actor) + .setIp(sampleReq.getIp()) + .setUrl(sampleReq.getUrl()) + .setMethod(URLMethods.Method.fromString(sampleReq.getMethod())) + .setOrig(sampleReq.getPayload()) + .setRequestTime(sampleReq.getTimestamp()) + .setApiCollectionId(sampleReq.getApiCollectionId()) + .setFilterId(filterId) + .build()); + } + + this.kafka.send( + KafkaUtils.generateMsg( + events, + MongoDBCollection.ThreatDetection.AGGREGATE_SAMPLE_MALICIOUS_REQUESTS, + accountId), + KafkaTopic.ThreatDetection.INTERNAL_DB_MESSAGES); + } + + this.kafka.send( + KafkaUtils.generateMsg( + maliciousEventModel, MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS, accountId), + KafkaTopic.ThreatDetection.INTERNAL_DB_MESSAGES); + } + + private static Set findDistinctFields( + MongoCollection coll, String fieldName, Class tClass, Bson filters) { + DistinctIterable r = coll.distinct(fieldName, filters, tClass); + Set result = new HashSet<>(); + MongoCursor cursor = r.cursor(); + while (cursor.hasNext()) { + result.add(cursor.next()); + } + return result; + } + + public FetchAlertFiltersResponse fetchAlertFilters( + String accountId, FetchAlertFiltersRequest request) { + MongoCollection coll = + this.mongoClient + .getDatabase(accountId) + .getCollection("malicious_events", MaliciousEventModel.class); + + Set actors = + MaliciousEventService.findDistinctFields( + coll, "actor", String.class, Filters.empty()); + Set urls = + MaliciousEventService.findDistinctFields( + coll, "latestApiEndpoint", String.class, Filters.empty()); + + return FetchAlertFiltersResponse.newBuilder().addAllActors(actors).addAllUrls(urls).build(); + } + + public ListMaliciousRequestsResponse listMaliciousRequests( + String accountId, ListMaliciousRequestsRequest request) { + int limit = request.getLimit(); + int skip = request.hasSkip() ? request.getSkip() : 0; + Map sort = request.getSortMap(); + + MongoCollection coll = + this.mongoClient + .getDatabase(accountId) + .getCollection( + MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS, MaliciousEventModel.class); + + BasicDBObject query = new BasicDBObject(); + try (MongoCursor cursor = + coll.find(query) + .sort(new BasicDBObject("detectedAt", sort.getOrDefault("detectedAt", -1))) + .skip(skip) + .limit(limit) + .cursor()) { + List maliciousEvents = new ArrayList<>(); + while (cursor.hasNext()) { + MaliciousEventModel evt = cursor.next(); + maliciousEvents.add( + ListMaliciousRequestsResponse.MaliciousEvent.newBuilder() + .setActor(evt.getActor()) + .setFilterId(evt.getFilterId()) + .setFilterId(evt.getFilterId()) + .setId(evt.getId()) + .setIp(evt.getLatestApiIp()) + .setCountry(evt.getCountry()) + .setPayload(evt.getLatestApiOrig()) + .setEndpoint(evt.getLatestApiEndpoint()) + .setMethod(evt.getLatestApiMethod().name()) + .setDetectedAt(evt.getDetectedAt()) + .setCategory(evt.getCategory()) + .setSubCategory(evt.getSubCategory()) + .build()); + } + return ListMaliciousRequestsResponse.newBuilder() + .setTotal(maliciousEvents.size()) + .addAllMaliciousEvents(maliciousEvents) + .build(); + } + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/ThreatActorService.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/ThreatActorService.java new file mode 100644 index 0000000000..fd0ae187bf --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/ThreatActorService.java @@ -0,0 +1,111 @@ +package com.akto.threat.backend.service; + +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatActorResponse; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatActorsRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ThreatActorByCountryRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ThreatActorByCountryResponse; +import com.akto.threat.backend.constants.MongoDBCollection; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.bson.Document; + +public class ThreatActorService { + + private final MongoClient mongoClient; + + public ThreatActorService(MongoClient mongoClient) { + this.mongoClient = mongoClient; + } + + public ListThreatActorResponse listThreatActors( + String accountId, ListThreatActorsRequest request) { + int skip = request.hasSkip() ? request.getSkip() : 0; + int limit = request.getLimit(); + Map sort = request.getSortMap(); + MongoCollection coll = + this.mongoClient + .getDatabase(accountId) + .getCollection(MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS, Document.class); + + List pipeline = new ArrayList<>(); + pipeline.add(new Document("$sort", new Document("actor", 1).append("detectedAt", -1))); // sort + pipeline.add( + new Document( + "$group", + new Document("_id", "$actor") + .append("latestApiEndpoint", new Document("$last", "$latestApiEndpoint")) + .append("latestApiMethod", new Document("$last", "$latestApiMethod")) + .append("latestApiIp", new Document("$last", "$latestApiIp")) + .append("country", new Document("$last", "$country")) + .append("discoveredAt", new Document("$last", "$detectedAt")))); + pipeline.add(new Document("$skip", skip)); + pipeline.add(new Document("$limit", limit)); + + pipeline.add( + new Document( + "$sort", new Document("discoveredAt", sort.getOrDefault("discoveredAt", -1)))); // sort + + List actors = new ArrayList<>(); + try (MongoCursor cursor = coll.aggregate(pipeline).cursor()) { + while (cursor.hasNext()) { + Document doc = cursor.next(); + actors.add( + ListThreatActorResponse.ThreatActor.newBuilder() + .setId(doc.getString("_id")) + .setLatestApiEndpoint(doc.getString("latestApiEndpoint")) + .setLatestApiMethod(doc.getString("latestApiMethod")) + .setLatestApiIp(doc.getString("latestApiIp")) + .setDiscoveredAt(doc.getLong("discoveredAt")) + .setCountry(doc.getString("country")) + .build()); + } + } + + return ListThreatActorResponse.newBuilder() + .addAllActors(actors) + .setTotal(actors.size()) + .build(); + } + + public ThreatActorByCountryResponse getThreatActorByCountry( + String accountId, ThreatActorByCountryRequest request) { + MongoCollection coll = + this.mongoClient + .getDatabase(accountId) + .getCollection(MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS, Document.class); + + List pipeline = new ArrayList<>(); + pipeline.add( + new Document("$sort", new Document("country", 1).append("detectedAt", -1))); // sort + pipeline.add( + new Document( + "$group", + new Document("_id", "$country") + .append("distinctActors", new Document("$addToSet", "$actor")))); + + pipeline.add( + new Document( + "$addFields", new Document("actorsCount", new Document("$size", "$distinctActors")))); + + pipeline.add(new Document("$sort", new Document("actorsCount", -1))); // sort + + List actorsByCountryCount = new ArrayList<>(); + + try (MongoCursor cursor = coll.aggregate(pipeline).cursor()) { + while (cursor.hasNext()) { + Document doc = cursor.next(); + actorsByCountryCount.add( + ThreatActorByCountryResponse.CountryCount.newBuilder() + .setCode(doc.getString("_id")) + .setCount(doc.getInteger("actorsCount", 0)) + .build()); + } + } + + return ThreatActorByCountryResponse.newBuilder().addAllCountries(actorsByCountryCount).build(); + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/ThreatApiService.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/ThreatApiService.java new file mode 100644 index 0000000000..2f794e47bf --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/ThreatApiService.java @@ -0,0 +1,127 @@ +package com.akto.threat.backend.service; + +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatApiRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatApiResponse; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ThreatCategoryWiseCountRequest; +import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ThreatCategoryWiseCountResponse; +import com.akto.threat.backend.constants.MongoDBCollection; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.bson.Document; + +public class ThreatApiService { + + private final MongoClient mongoClient; + + public ThreatApiService(MongoClient mongoClient) { + this.mongoClient = mongoClient; + } + + public ListThreatApiResponse listThreatApis(String accountId, ListThreatApiRequest request) { + int skip = request.hasSkip() ? request.getSkip() : 0; + int limit = request.getLimit(); + Map sort = request.getSortMap(); + MongoCollection coll = + this.mongoClient + .getDatabase(accountId) + .getCollection(MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS, Document.class); + + List pipeline = new ArrayList<>(); + pipeline.add( + new Document( + "$sort", + new Document("latestApiEndpoint", 1) + .append("latestApiMethod", 1) + .append("detectedAt", -1))); // sort + pipeline.add( + new Document( + "$group", + new Document( + "_id", + new Document("endpoint", "$latestApiEndpoint") + .append("method", "$latestApiMethod")) + .append("discoveredAt", new Document("$last", "$detectedAt")) + .append("distinctActors", new Document("$addToSet", "$actor")) + .append("requestsCount", new Document("$sum", 1)))); + pipeline.add( + new Document( + "$addFields", new Document("actorsCount", new Document("$size", "$distinctActors")))); + pipeline.add(new Document("$project", new Document("distinctActors", 0))); + pipeline.add(new Document("$skip", skip)); + pipeline.add(new Document("$limit", limit)); + // add sort + pipeline.add( + new Document( + "$sort", + new Document("discoveredAt", sort.getOrDefault("discoveredAt", -1)) + .append("requestsCount", sort.getOrDefault("requestsCount", -1)) + .append("actorsCount", sort.getOrDefault("actorsCount", -1)))); + + List apis = new ArrayList<>(); + try (MongoCursor cursor = coll.aggregate(pipeline).cursor()) { + while (cursor.hasNext()) { + Document doc = cursor.next(); + Document agg = (Document) doc.get("_id"); + apis.add( + ListThreatApiResponse.ThreatApi.newBuilder() + .setEndpoint(agg.getString("endpoint")) + .setMethod(agg.getString("method")) + .setDiscoveredAt(doc.getLong("discoveredAt")) + .setActorsCount(doc.getInteger("actorsCount", 0)) + .setRequestsCount(doc.getInteger("requestsCount", 0)) + .build()); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return ListThreatApiResponse.newBuilder().addAllApis(apis).setTotal(apis.size()).build(); + } + + public ThreatCategoryWiseCountResponse getSubCategoryWiseCount( + String accountId, ThreatCategoryWiseCountRequest req) { + MongoCollection coll = + this.mongoClient + .getDatabase(accountId) + .getCollection(MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS, Document.class); + + List pipeline = new ArrayList<>(); + pipeline.add( + new Document("$sort", new Document("category", 1).append("detectedAt", -1))); // sort + pipeline.add( + new Document( + "$group", + new Document( + "_id", + new Document("category", "$category").append("subCategory", "$subCategory")) + .append("count", new Document("$sum", 1)))); + + pipeline.add( + new Document( + "$sort", + new Document("category", -1).append("subCategory", -1).append("count", -1))); // sort + + List categoryWiseCounts = new ArrayList<>(); + + try (MongoCursor cursor = coll.aggregate(pipeline).cursor()) { + while (cursor.hasNext()) { + Document doc = cursor.next(); + Document agg = (Document) doc.get("_id"); + categoryWiseCounts.add( + ThreatCategoryWiseCountResponse.SubCategoryCount.newBuilder() + .setCategory(agg.getString("category")) + .setSubCategory(agg.getString("subCategory")) + .setCount(doc.getInteger("count", 0)) + .build()); + } + } + + return ThreatCategoryWiseCountResponse.newBuilder() + .addAllCategoryWiseCounts(categoryWiseCounts) + .build(); + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/tasks/FlushMessagesToDB.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/tasks/FlushMessagesToDB.java new file mode 100644 index 0000000000..abcb98452d --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/tasks/FlushMessagesToDB.java @@ -0,0 +1,120 @@ +package com.akto.threat.backend.tasks; + +import com.akto.kafka.KafkaConfig; +import com.akto.runtime.utils.Utils; +import com.akto.threat.backend.constants.KafkaTopic; +import com.akto.threat.backend.constants.MongoDBCollection; +import com.akto.threat.backend.db.AggregateSampleMaliciousEventModel; +import com.akto.threat.backend.db.MaliciousEventModel; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.mongodb.client.MongoClient; +import com.mongodb.client.model.BulkWriteOptions; +import com.mongodb.client.model.InsertOneModel; +import com.mongodb.client.model.WriteModel; +import java.time.Duration; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; + +public class FlushMessagesToDB { + + private final KafkaConsumer kafkaConsumer; + private final KafkaConfig kafkaConfig; + private final MongoClient mClient; + + private static final ObjectMapper mapper = new ObjectMapper(); + private static final Gson gson = new Gson(); + + public FlushMessagesToDB(KafkaConfig kafkaConfig, MongoClient mongoClient) { + String kafkaBrokerUrl = kafkaConfig.getBootstrapServers(); + String groupId = kafkaConfig.getGroupId(); + + Properties properties = + Utils.configProperties( + kafkaBrokerUrl, groupId, kafkaConfig.getConsumerConfig().getMaxPollRecords()); + this.kafkaConsumer = new KafkaConsumer<>(properties); + this.kafkaConfig = kafkaConfig; + + this.mClient = mongoClient; + } + + public void run() { + ExecutorService pollingExecutor = Executors.newSingleThreadExecutor(); + this.kafkaConsumer.subscribe( + Collections.singletonList(KafkaTopic.ThreatDetection.INTERNAL_DB_MESSAGES)); + + pollingExecutor.execute( + () -> { + // Poll data from Kafka topic + while (true) { + ConsumerRecords records = + kafkaConsumer.poll( + Duration.ofMillis(this.kafkaConfig.getConsumerConfig().getPollDurationMilli())); + if (records.isEmpty()) { + continue; + } + + processRecords(records); + + if (!records.isEmpty()) { + kafkaConsumer.commitSync(); + } + } + }); + } + + private void processRecords(ConsumerRecords records) { + records.forEach( + r -> { + try { + String message = r.value(); + writeMessage(message); + } catch (JsonProcessingException e) { + System.out.println("Error while parsing message" + e); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + } + + private void writeMessage(String message) throws JsonProcessingException { + Map json = gson.fromJson(message, Map.class); + String eventType = (String) json.get("eventType"); + String payload = (String) json.get("payload"); + String accountId = (String) json.get("accountId"); + + switch (eventType) { + case MongoDBCollection.ThreatDetection.AGGREGATE_SAMPLE_MALICIOUS_REQUESTS: + List> bulkUpdates = new ArrayList<>(); + List events = + mapper.readValue( + payload, new TypeReference>() {}); + events.forEach( + event -> { + bulkUpdates.add(new InsertOneModel<>(event)); + }); + + this.mClient + .getDatabase(accountId + "") + .getCollection(eventType, AggregateSampleMaliciousEventModel.class) + .bulkWrite(bulkUpdates, new BulkWriteOptions().ordered(false)); + break; + + case MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS: + MaliciousEventModel event = + mapper.readValue(payload, new TypeReference() {}); + this.mClient + .getDatabase(accountId + "") + .getCollection(eventType, MaliciousEventModel.class) + .insertOne(event); + break; + default: + throw new IllegalArgumentException("Invalid event type"); + } + } +} diff --git a/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/utils/KafkaUtils.java b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/utils/KafkaUtils.java new file mode 100644 index 0000000000..afaefdd802 --- /dev/null +++ b/apps/threat-detection-backend/src/main/java/com/akto/threat/backend/utils/KafkaUtils.java @@ -0,0 +1,19 @@ +package com.akto.threat.backend.utils; + +import com.google.gson.Gson; +import com.mongodb.BasicDBObject; + +public class KafkaUtils { + + private static final Gson gson = new Gson(); + + public static String generateMsg(Object writes, String eventType, String accountId) { + BasicDBObject obj = new BasicDBObject(); + obj.put("eventType", eventType); + String payloadStr = gson.toJson(writes); + obj.put("payload", payloadStr); + obj.put("accountId", accountId); + + return obj.toString(); + } +} diff --git a/apps/api-threat-detection/.gitignore b/apps/threat-detection/.gitignore similarity index 100% rename from apps/api-threat-detection/.gitignore rename to apps/threat-detection/.gitignore diff --git a/apps/threat-detection/Dockerfile b/apps/threat-detection/Dockerfile new file mode 100644 index 0000000000..41b66dbbac --- /dev/null +++ b/apps/threat-detection/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk +WORKDIR /app +COPY ./target/threat-detection-1.0-SNAPSHOT-jar-with-dependencies.jar /app/threat-detection-1.0-SNAPSHOT-jar-with-dependencies.jar +CMD "java" "-XX:+ExitOnOutOfMemoryError" "-jar" "/app/threat-detection-1.0-SNAPSHOT-jar-with-dependencies.jar" \ No newline at end of file diff --git a/apps/api-threat-detection/README.md b/apps/threat-detection/README.md similarity index 100% rename from apps/api-threat-detection/README.md rename to apps/threat-detection/README.md diff --git a/apps/threat-detection/pom.xml b/apps/threat-detection/pom.xml new file mode 100644 index 0000000000..bd143c2dc5 --- /dev/null +++ b/apps/threat-detection/pom.xml @@ -0,0 +1,260 @@ + + + 4.0.0 + + + com.akto.apps + apps + ${revision} + + + com.akto.apps.threat-detection + threat-detection + jar + + + + confluent + https://packages.confluent.io/maven/ + + + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + com.akto.libs.dao + dao + ${project.version} + + + com.akto.libs.utils + utils + ${project.version} + + + com.akto.apps.mini-runtime + mini-runtime + ${project.version} + + + com.akto.apps.testing + testing + ${project.version} + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + org.jetbrains + annotations + RELEASE + compile + + + org.junit.jupiter + junit-jupiter-api + 5.4.2 + test + + + org.apache.kafka + kafka-clients + 3.0.0 + + + com.akto.libs.utils + utils + test-jar + ${project.version} + test + + + io.confluent + kafka-protobuf-serializer + 7.5.0 + + + + com.akto.libs.protobuf + protobuf + 1.0-SNAPSHOT + compile + + + + io.lettuce + lettuce-core + 6.4.0.RELEASE + + + + com.github.ben-manes.caffeine + caffeine + 2.9.3 + + + com.fasterxml.jackson.core + jackson-databind + 2.16.1 + compile + + + + org.postgresql + postgresql + 42.7.4 + + + + org.flywaydb + flyway-core + 9.22.3 + + + + org.hibernate + hibernate-core + 5.6.15.Final + + + + org.apache.logging.log4j + log4j-core + 2.24.2 + + + + org.apache.logging.log4j + log4j-api + 2.24.2 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 8 + 8 + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.1 + + + copy-dependencies + package + + copy-dependencies + + + + + + + src/main/java + src/test/java + + + src/main/resources + false + + + + + + + + normal + + true + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + + + com.akto.threat.detection.Main + + + + + jar-with-dependencies + + + + + + + + + + + devcontainer + + + + org.apache.maven.plugins + maven-jar-plugin + + threat-detection-1.0-SNAPSHOT-jar-with-dependencies + + + true + com.akto.threat.detection.Main + dependency-jars/ + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory}/dependency-jars/ + + + + + + + + + + \ No newline at end of file diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/Main.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/Main.java new file mode 100644 index 0000000000..1d1b061d83 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/Main.java @@ -0,0 +1,82 @@ +package com.akto.threat.detection; + +import com.akto.DaoInit; +import com.akto.kafka.KafkaConfig; +import com.akto.kafka.KafkaConsumerConfig; +import com.akto.kafka.KafkaProducerConfig; +import com.akto.threat.detection.constants.KafkaTopic; +import com.akto.threat.detection.session_factory.SessionFactoryUtils; +import com.akto.threat.detection.tasks.CleanupTask; +import com.akto.threat.detection.tasks.FlushSampleDataTask; +import com.akto.threat.detection.tasks.MaliciousTrafficDetectorTask; +import com.akto.threat.detection.tasks.SendMaliciousEventsToBackend; +import com.mongodb.ConnectionString; +import io.lettuce.core.RedisClient; +import org.flywaydb.core.Flyway; +import org.hibernate.SessionFactory; + +public class Main { + + private static final String CONSUMER_GROUP_ID = "akto.threat_detection"; + + public static void main(String[] args) throws Exception { + runMigrations(); + + SessionFactory sessionFactory = SessionFactoryUtils.createFactory(); + + // TODO: Remove this before merging. Will be using cyborg for fetching templates + DaoInit.init(new ConnectionString(System.getenv("AKTO_MONGO_CONN"))); + KafkaConfig trafficKafka = + KafkaConfig.newBuilder() + .setGroupId(CONSUMER_GROUP_ID) + .setBootstrapServers(System.getenv("AKTO_TRAFFIC_KAFKA_BOOTSTRAP_SERVER")) + .setConsumerConfig( + KafkaConsumerConfig.newBuilder() + .setMaxPollRecords(100) + .setPollDurationMilli(100) + .build()) + .setProducerConfig( + KafkaProducerConfig.newBuilder().setBatchSize(100).setLingerMs(100).build()) + .build(); + + KafkaConfig internalKafka = + KafkaConfig.newBuilder() + .setGroupId(CONSUMER_GROUP_ID) + .setBootstrapServers(System.getenv("AKTO_INTERNAL_KAFKA_BOOTSTRAP_SERVER")) + .setConsumerConfig( + KafkaConsumerConfig.newBuilder() + .setMaxPollRecords(100) + .setPollDurationMilli(100) + .build()) + .setProducerConfig( + KafkaProducerConfig.newBuilder().setBatchSize(100).setLingerMs(100).build()) + .build(); + + new MaliciousTrafficDetectorTask(trafficKafka, internalKafka, createRedisClient()).run(); + new FlushSampleDataTask( + sessionFactory, internalKafka, KafkaTopic.ThreatDetection.MALICIOUS_EVENTS) + .run(); + new SendMaliciousEventsToBackend( + sessionFactory, internalKafka, KafkaTopic.ThreatDetection.ALERTS) + .run(); + new CleanupTask(sessionFactory).run(); + } + + public static RedisClient createRedisClient() { + return RedisClient.create(System.getenv("AKTO_THREAT_DETECTION_REDIS_URI")); + } + + public static void runMigrations() { + String url = System.getenv("AKTO_THREAT_DETECTION_POSTGRES"); + String user = System.getenv("AKTO_THREAT_DETECTION_POSTGRES_USER"); + String password = System.getenv("AKTO_THREAT_DETECTION_POSTGRES_PASSWORD"); + Flyway flyway = + Flyway.configure() + .dataSource(url, user, password) + .locations("classpath:db/migration") + .schemas("flyway") + .load(); + + flyway.migrate(); + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/actor/ActorGenerator.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/actor/ActorGenerator.java new file mode 100644 index 0000000000..9f27be49bc --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/actor/ActorGenerator.java @@ -0,0 +1,10 @@ +package com.akto.threat.detection.actor; + +import com.akto.dto.HttpResponseParams; + +import java.util.Optional; + +public interface ActorGenerator { + + Optional generate(HttpResponseParams responseParams); +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/actor/SourceIPActorGenerator.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/actor/SourceIPActorGenerator.java new file mode 100644 index 0000000000..ebe444a2f1 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/actor/SourceIPActorGenerator.java @@ -0,0 +1,24 @@ +package com.akto.threat.detection.actor; + +import com.akto.dto.HttpResponseParams; +import com.akto.runtime.policies.ApiAccessTypePolicy; + +import java.util.List; +import java.util.Optional; + +public class SourceIPActorGenerator implements ActorGenerator { + + private SourceIPActorGenerator() {} + + public static SourceIPActorGenerator instance = new SourceIPActorGenerator(); + + @Override + public Optional generate(HttpResponseParams responseParams) { + List sourceIPs = ApiAccessTypePolicy.getSourceIps(responseParams); + if (sourceIPs.isEmpty()) { + return Optional.of(responseParams.getSourceIP()); + } + + return Optional.of(sourceIPs.get(0)); + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/CounterCache.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/CounterCache.java new file mode 100644 index 0000000000..f1eaeffa90 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/CounterCache.java @@ -0,0 +1,14 @@ +package com.akto.threat.detection.cache; + +public interface CounterCache { + + void incrementBy(String key, long val); + + void increment(String key); + + long get(String key); + + boolean exists(String key); + + void clear(String key); +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/LongValueCodec.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/LongValueCodec.java new file mode 100644 index 0000000000..54879be184 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/LongValueCodec.java @@ -0,0 +1,32 @@ +package com.akto.threat.detection.cache; + +import io.lettuce.core.codec.RedisCodec; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class LongValueCodec implements RedisCodec { + + @Override + public String decodeKey(ByteBuffer bytes) { + return StandardCharsets.UTF_8.decode(bytes).toString(); + } + + @Override + public Long decodeValue(ByteBuffer bytes) { + if (!bytes.hasRemaining()) return null; + return bytes.getLong(); + } + + @Override + public ByteBuffer encodeKey(String key) { + return StandardCharsets.UTF_8.encode(key); + } + + @Override + public ByteBuffer encodeValue(Long value) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); + buffer.putLong(value); + buffer.flip(); + return buffer; + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/RedisBackedCounterCache.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/RedisBackedCounterCache.java new file mode 100644 index 0000000000..2182be09c6 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/cache/RedisBackedCounterCache.java @@ -0,0 +1,126 @@ +package com.akto.threat.detection.cache; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import io.lettuce.core.ExpireArgs; +import io.lettuce.core.RedisClient; +import io.lettuce.core.api.StatefulRedisConnection; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.*; + +public class RedisBackedCounterCache implements CounterCache { + + static class Op { + private final String key; + private final long value; + + public Op(String key, long value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public long getValue() { + return value; + } + } + + private final StatefulRedisConnection redis; + + private final Cache localCache; + + private final ConcurrentLinkedQueue pendingIncOps; + private final ConcurrentMap deletedKeys; + private final String prefix; + + public RedisBackedCounterCache(RedisClient redisClient, String prefix) { + this.prefix = prefix; + this.redis = redisClient.connect(new LongValueCodec()); + this.localCache = Caffeine.newBuilder().maximumSize(100000).expireAfterWrite(3, TimeUnit.HOURS).build(); + + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + executor.scheduleAtFixedRate(this::syncToRedis, 60, 5, TimeUnit.SECONDS); + + this.pendingIncOps = new ConcurrentLinkedQueue<>(); + this.deletedKeys = new ConcurrentHashMap<>(); + } + + private String addPrefixToKey(String key) { + return new StringBuilder().append(prefix).append("|").append(key).toString(); + } + + @Override + public void increment(String key) { + incrementBy(key, 1); + } + + @Override + public void incrementBy(String key, long val) { + String _key = addPrefixToKey(key); + localCache.asMap().merge(_key, val, Long::sum); + pendingIncOps.add(new Op(_key, val)); + } + + @Override + public long get(String key) { + return Optional.ofNullable(this.localCache.getIfPresent(addPrefixToKey(key))).orElse(0L); + } + + @Override + public boolean exists(String key) { + return localCache.asMap().containsKey(addPrefixToKey(key)); + } + + @Override + public void clear(String key) { + String _key = addPrefixToKey(key); + localCache.invalidate(_key); + this.deletedKeys.put(_key, true); + redis.async().del(_key); + } + + private void setExpiryIfNotSet(String key, long seconds) { + // We only set expiry for redis entry. For local cache we have lower expiry for + // all entries. + ExpireArgs args = ExpireArgs.Builder.nx(); + redis.async().expire(addPrefixToKey(key), seconds, args); + } + + private void syncToRedis() { + Set _keys = new HashSet<>(); + while (!pendingIncOps.isEmpty()) { + Op op = pendingIncOps.poll(); + String key = op.getKey(); + long val = op.getValue(); + + if (this.deletedKeys.containsKey(key)) { + continue; + } + + redis + .async() + .incrby(key, val) + .whenComplete( + (result, ex) -> { + if (ex != null) { + ex.printStackTrace(); + } + + _keys.add(key); + + if (result != null) { + localCache.asMap().put(key, result); + } + }); + } + + _keys.forEach(key -> setExpiryIfNotSet(key, 3 * 60 * 60)); + + this.deletedKeys.clear(); + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/constants/KafkaTopic.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/constants/KafkaTopic.java new file mode 100644 index 0000000000..7c13df8d87 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/constants/KafkaTopic.java @@ -0,0 +1,8 @@ +package com.akto.threat.detection.constants; + +public class KafkaTopic { + public static class ThreatDetection { + public static final String MALICIOUS_EVENTS = "akto.threat_detection.malicious_events"; + public static final String ALERTS = "akto.threat_detection.alerts"; + } +} \ No newline at end of file diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/db/entity/MaliciousEventEntity.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/db/entity/MaliciousEventEntity.java new file mode 100644 index 0000000000..41bf2422ee --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/db/entity/MaliciousEventEntity.java @@ -0,0 +1,209 @@ +package com.akto.threat.detection.db.entity; + +import com.akto.dto.type.URLMethods; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.PrePersist; +import javax.persistence.Table; +import org.hibernate.annotations.GenericGenerator; + +@Entity +@Table(name = "malicious_event", schema = "threat_detection") +public class MaliciousEventEntity { + + @Id + @GeneratedValue(generator = "UUID") + @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator") + private UUID id; + + @Column(name = "actor") + private String actor; + + @Column(name = "filter_id") + private String filterId; + + @Column(name = "url") + private String url; + + @Column(name = "method") + @Enumerated(EnumType.STRING) + private URLMethods.Method method; + + @Column(name = "timestamp") + private long timestamp; + + @Column(name = "orig") + private String orig; + + // Geo location data + @Column(name = "ip") + private String ip; + + @Column(name = "api_collection_id") + private int apiCollectionId; + + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @Column(name = "_alerted_to_backend") + private boolean alertedToBackend; + + public MaliciousEventEntity() {} + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(ZoneOffset.UTC); + } + + public MaliciousEventEntity(Builder builder) { + this.actor = builder.actorId; + this.filterId = builder.filterId; + this.url = builder.url; + this.method = builder.method; + this.timestamp = builder.timestamp; + this.orig = builder.orig; + this.ip = builder.ip; + this.apiCollectionId = builder.apiCollectionId; + } + + public static class Builder { + private String actorId; + private String filterId; + private String url; + private URLMethods.Method method; + private long timestamp; + private String orig; + private String ip; + private int apiCollectionId; + + public Builder setActor(String actorId) { + this.actorId = actorId; + return this; + } + + public Builder setFilterId(String filterId) { + this.filterId = filterId; + return this; + } + + public Builder setUrl(String url) { + this.url = url; + return this; + } + + public Builder setMethod(URLMethods.Method method) { + this.method = method; + return this; + } + + public Builder setTimestamp(long timestamp) { + this.timestamp = timestamp; + return this; + } + + public Builder setOrig(String orig) { + this.orig = orig; + return this; + } + + public Builder setIp(String ip) { + this.ip = ip; + return this; + } + + public Builder setApiCollectionId(int apiCollectionId) { + this.apiCollectionId = apiCollectionId; + return this; + } + + public MaliciousEventEntity build() { + return new MaliciousEventEntity(this); + } + } + + public static Builder newBuilder() { + return new Builder(); + } + + public UUID getId() { + return id; + } + + public String getActor() { + return actor; + } + + public String getFilterId() { + return filterId; + } + + public String getUrl() { + return url; + } + + public URLMethods.Method getMethod() { + return method; + } + + public long getTimestamp() { + return timestamp; + } + + public String getOrig() { + return orig; + } + + public String getIp() { + return ip; + } + + public int getApiCollectionId() { + return apiCollectionId; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public boolean isAlertedToBackend() { + return alertedToBackend; + } + + @Override + public String toString() { + return "MaliciousEventEntity{" + + "createdAt=" + + createdAt + + ", apiCollectionId=" + + apiCollectionId + + ", ip='" + + ip + + '\'' + + ", orig='" + + orig + + '\'' + + ", timestamp=" + + timestamp + + ", method=" + + method + + ", url='" + + url + + '\'' + + ", filterId='" + + filterId + + '\'' + + ", actor='" + + actor + + '\'' + + ", id=" + + id + + '}'; + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/dto/MessageEnvelope.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/dto/MessageEnvelope.java new file mode 100644 index 0000000000..06fe644be4 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/dto/MessageEnvelope.java @@ -0,0 +1,78 @@ +package com.akto.threat.detection.dto; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import com.google.protobuf.util.JsonFormat; +import java.util.Optional; + +// Kafka Message Wrapper for suspect data +public class MessageEnvelope { + private String accountId; + private String data; + private String actor; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public MessageEnvelope() {} + + public MessageEnvelope(String accountId, String actor, String data) { + this.accountId = accountId; + this.actor = actor; + this.data = data; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public Optional marshal() { + try { + return Optional.ofNullable(objectMapper.writeValueAsString(this)); + } catch (Exception e) { + e.printStackTrace(); + } + + return Optional.empty(); + } + + public static Optional unmarshal(String message) { + try { + return Optional.ofNullable(objectMapper.readValue(message, MessageEnvelope.class)); + } catch (Exception e) { + e.printStackTrace(); + } + + return Optional.empty(); + } + + public static MessageEnvelope generateEnvelope(String accountId, String actor, Message msg) + throws InvalidProtocolBufferException { + String data = JsonFormat.printer().print(msg); + return new MessageEnvelope(accountId, actor, data); + } + + public String getActor() { + return actor; + } + + public void setActor(String actor) { + this.actor = actor; + } + + public static ObjectMapper getObjectmapper() { + return objectMapper; + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/kafka/KafkaProtoProducer.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/kafka/KafkaProtoProducer.java new file mode 100644 index 0000000000..cfd51ace83 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/kafka/KafkaProtoProducer.java @@ -0,0 +1,48 @@ +package com.akto.threat.detection.kafka; + +import com.akto.kafka.KafkaConfig; +import com.google.protobuf.Message; +import java.time.Duration; +import java.util.Properties; +import org.apache.kafka.clients.producer.*; +import org.apache.kafka.common.serialization.StringSerializer; + +public class KafkaProtoProducer { + private KafkaProducer producer; + public boolean producerReady; + + public KafkaProtoProducer(KafkaConfig kafkaConfig) { + this.producer = generateProducer( + kafkaConfig.getBootstrapServers(), + kafkaConfig.getProducerConfig().getLingerMs(), + kafkaConfig.getProducerConfig().getBatchSize()); + } + + public void send(String topic, Message message) { + byte[] messageBytes = message.toByteArray(); + this.producer.send(new ProducerRecord<>(topic, messageBytes)); + } + + public void close() { + this.producerReady = false; + producer.close(Duration.ofMillis(0)); // close immediately + } + + private KafkaProducer generateProducer(String brokerIP, int lingerMS, int batchSize) { + if (producer != null) + close(); // close existing producer connection + + int requestTimeoutMs = 5000; + Properties kafkaProps = new Properties(); + kafkaProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokerIP); + kafkaProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, + "org.apache.kafka.common.serialization.ByteArraySerializer"); + kafkaProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + kafkaProps.put(ProducerConfig.BATCH_SIZE_CONFIG, batchSize); + kafkaProps.put(ProducerConfig.LINGER_MS_CONFIG, lingerMS); + kafkaProps.put(ProducerConfig.RETRIES_CONFIG, 0); + kafkaProps.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, requestTimeoutMs); + kafkaProps.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, lingerMS + requestTimeoutMs); + return new KafkaProducer(kafkaProps); + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/session_factory/SessionFactoryUtils.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/session_factory/SessionFactoryUtils.java new file mode 100644 index 0000000000..7bf80f0f7b --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/session_factory/SessionFactoryUtils.java @@ -0,0 +1,29 @@ +package com.akto.threat.detection.session_factory; + +import com.akto.threat.detection.db.entity.MaliciousEventEntity; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; + +public class SessionFactoryUtils { + + public static SessionFactory createFactory() { + final String url = System.getenv("AKTO_THREAT_DETECTION_POSTGRES"); + final String user = System.getenv("AKTO_THREAT_DETECTION_POSTGRES_USER"); + final String password = System.getenv("AKTO_THREAT_DETECTION_POSTGRES_PASSWORD"); + + final Configuration cfg = new Configuration(); + cfg.setProperty("hibernate.connection.url", url); + cfg.setProperty("hibernate.connection.user", user); + cfg.setProperty("hibernate.connection.password", password); + cfg.setProperty("dialect", "org.hibernate.dialect.PostgreSQL92Dialect"); + cfg.setProperty("connection.driver_class", "org.postgresql.Driver"); + cfg.setProperty("show_sql", "false"); + cfg.setProperty("format_sql", "false"); + + cfg.addAnnotatedClass(MaliciousEventEntity.class); + + return cfg.buildSessionFactory( + new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build()); + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/Bin.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/Bin.java new file mode 100644 index 0000000000..fa1202f2dd --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/Bin.java @@ -0,0 +1,19 @@ +package com.akto.threat.detection.smart_event_detector.window_based; + +public class Bin { + int binId; + long count; + + public Bin(int binId, long count) { + this.binId = binId; + this.count = count; + } + + public int getBinId() { + return binId; + } + + public long getCount() { + return count; + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/Data.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/Data.java new file mode 100644 index 0000000000..43f928a6ab --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/Data.java @@ -0,0 +1,49 @@ +package com.akto.threat.detection.smart_event_detector.window_based; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +public class Data { + @JsonProperty("ln") + public long lastNotifiedAt = 0; + + @JsonProperty("rq") + public List requests = new ArrayList<>(); + + public static class Request { + private long receivedAt; + + public Request() {} + + public Request(long receivedAt) { + this.receivedAt = receivedAt; + } + + public long getReceivedAt() { + return receivedAt; + } + + public void setReceivedAt(long receivedAt) { + this.receivedAt = receivedAt; + } + } + + public Data() {} + + public long getLastNotifiedAt() { + return lastNotifiedAt; + } + + public void setLastNotifiedAt(long lastNotifiedAt) { + this.lastNotifiedAt = lastNotifiedAt; + } + + public List getRequests() { + return requests; + } + + public void setRequests(List requests) { + this.requests = requests; + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/WindowBasedThresholdNotifier.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/WindowBasedThresholdNotifier.java new file mode 100644 index 0000000000..01d3b531a7 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/smart_event_detector/window_based/WindowBasedThresholdNotifier.java @@ -0,0 +1,90 @@ +package com.akto.threat.detection.smart_event_detector.window_based; + +import com.akto.dto.api_protection_parse_layer.Rule; +import com.akto.proto.generated.threat_detection.message.sample_request.v1.SampleMaliciousRequest; +import com.akto.threat.detection.cache.CounterCache; +import java.util.ArrayList; +import java.util.List; + +public class WindowBasedThresholdNotifier { + + private final Config config; + + public static class Config { + private final int threshold; + private final int windowSizeInMinutes; + private int notificationCooldownInSeconds = 60 * 30; // 30 mins + + public Config(int threshold, int windowInSeconds) { + this.threshold = threshold; + this.windowSizeInMinutes = windowInSeconds; + } + + public int getThreshold() { + return threshold; + } + + public int getWindowSizeInMinutes() { + return windowSizeInMinutes; + } + + public int getNotificationCooldownInSeconds() { + return notificationCooldownInSeconds; + } + } + + public static class Result { + private final boolean shouldNotify; + + public Result(boolean shouldNotify) { + this.shouldNotify = shouldNotify; + } + + public boolean shouldNotify() { + return shouldNotify; + } + } + + public Config getConfig() { + return config; + } + + private final CounterCache cache; + + public WindowBasedThresholdNotifier(CounterCache cache, Config config) { + this.cache = cache; + this.config = config; + } + + public Result shouldNotify(String aggKey, SampleMaliciousRequest maliciousEvent, Rule rule) { + int binId = (int) maliciousEvent.getTimestamp() / 60; + String cacheKey = aggKey + "|" + binId; + this.cache.increment(cacheKey); + + long windowCount = 0L; + List bins = getBins(aggKey, binId - rule.getCondition().getWindowThreshold() + 1, binId); + for (Bin data : bins) { + windowCount += data.getCount(); + } + + boolean thresholdBreached = windowCount >= rule.getCondition().getMatchCount(); + + if (thresholdBreached) { + this.cache.clear(cacheKey); + } + + return new Result(thresholdBreached); + } + + public List getBins(String aggKey, int binStart, int binEnd) { + List binData = new ArrayList<>(); + for (int i = binStart; i <= binEnd; i++) { + String key = aggKey + "|" + i; + if (!this.cache.exists(key)) { + continue; + } + binData.add(new Bin(i, this.cache.get(key))); + } + return binData; + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/AbstractKafkaConsumerTask.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/AbstractKafkaConsumerTask.java new file mode 100644 index 0000000000..4a0a731523 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/AbstractKafkaConsumerTask.java @@ -0,0 +1,72 @@ +package com.akto.threat.detection.tasks; + +import com.akto.kafka.KafkaConfig; +import com.akto.runtime.utils.Utils; +import java.time.Duration; +import java.util.Collections; +import java.util.Properties; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; + +public abstract class AbstractKafkaConsumerTask implements Task { + + protected Consumer kafkaConsumer; + protected KafkaConfig kafkaConfig; + protected String kafkaTopic; + + public AbstractKafkaConsumerTask(KafkaConfig kafkaConfig, String kafkaTopic) { + this.kafkaTopic = kafkaTopic; + this.kafkaConfig = kafkaConfig; + + String kafkaBrokerUrl = kafkaConfig.getBootstrapServers(); + String groupId = kafkaConfig.getGroupId(); + + Properties properties = new Properties(); + properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBrokerUrl); + properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, + "org.apache.kafka.common.serialization.ByteArrayDeserializer"); + properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, kafkaConfig.getConsumerConfig().getMaxPollRecords()); + properties.put(ConsumerConfig.GROUP_ID_CONFIG, kafkaConfig.getGroupId()); + properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); + + this.kafkaConsumer = new KafkaConsumer<>(properties); + } + + @Override + public void run() { + this.kafkaConsumer.subscribe(Collections.singletonList(this.kafkaTopic)); + + ExecutorService pollingExecutor = Executors.newSingleThreadExecutor(); + + pollingExecutor.execute( + () -> { + // Poll data from Kafka topic + while (true) { + ConsumerRecords records = kafkaConsumer.poll( + Duration.ofMillis(kafkaConfig.getConsumerConfig().getPollDurationMilli())); + if (records.isEmpty()) { + continue; + } + + try { + processRecords(records); + + if (!records.isEmpty()) { + kafkaConsumer.commitSync(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }); + } + + abstract void processRecords(ConsumerRecords records); +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/CleanupTask.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/CleanupTask.java new file mode 100644 index 0000000000..93a6d7c906 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/CleanupTask.java @@ -0,0 +1,39 @@ +package com.akto.threat.detection.tasks; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +public class CleanupTask implements Task { + + private final SessionFactory sessionFactory; + + public CleanupTask(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public void run() { + ScheduledExecutorService cronExecutorService = Executors.newScheduledThreadPool(1); + cronExecutorService.scheduleAtFixedRate(this::cleanup, 5, 30, TimeUnit.MINUTES); + } + + private void cleanup() { + try (Session session = this.sessionFactory.openSession()) { + Transaction txn = session.beginTransaction(); + int deletedCount = + session + .createQuery("delete from MaliciousEventEntity m where m.createdAt < :startDate") + .setParameter("startDate", LocalDateTime.now(ZoneOffset.UTC).minusDays(7)) + .executeUpdate(); + + txn.commit(); + System.out.println("Number of rows deleted: " + deletedCount); + } + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/FlushSampleDataTask.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/FlushSampleDataTask.java new file mode 100644 index 0000000000..4b857c389e --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/FlushSampleDataTask.java @@ -0,0 +1,76 @@ +package com.akto.threat.detection.tasks; + +import com.akto.dto.type.URLMethods; +import com.akto.kafka.KafkaConfig; +import com.akto.proto.generated.threat_detection.message.sample_request.v1.SampleMaliciousRequest; +import com.akto.proto.generated.threat_detection.message.sample_request.v1.SampleRequestKafkaEnvelope; +import com.akto.threat.detection.db.entity.MaliciousEventEntity; +import com.akto.threat.detection.dto.MessageEnvelope; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; +import java.util.ArrayList; +import java.util.List; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +/* +This will read sample malicious data from kafka topic and save it to DB. + */ +public class FlushSampleDataTask extends AbstractKafkaConsumerTask { + + private final SessionFactory sessionFactory; + + public FlushSampleDataTask( + SessionFactory sessionFactory, KafkaConfig trafficConfig, String topic) { + super(trafficConfig, topic); + this.sessionFactory = sessionFactory; + } + + protected void processRecords(ConsumerRecords records) { + List events = new ArrayList<>(); + records.forEach( + r -> { + SampleRequestKafkaEnvelope envelope; + try { + envelope = SampleRequestKafkaEnvelope.parseFrom(r.value()); + SampleMaliciousRequest evt = envelope.getMaliciousRequest(); + + events.add( + MaliciousEventEntity.newBuilder() + .setActor(envelope.getActor()) + .setFilterId(evt.getFilterId()) + .setUrl(evt.getUrl()) + .setMethod(URLMethods.Method.fromString(evt.getMethod())) + .setTimestamp(evt.getTimestamp()) + .setOrig(evt.getPayload()) + .setApiCollectionId(evt.getApiCollectionId()) + .setIp(evt.getIp()) + .build()); + } catch (InvalidProtocolBufferException e) { + e.printStackTrace(); + } + }); + + Session session = this.sessionFactory.openSession(); + Transaction txn = session.beginTransaction(); + try { + // Commit these events in 2 batches + for (int i = 0; i < events.size(); i++) { + session.persist(events.get(i)); + if (i % 50 == 0) { + session.flush(); + session.clear(); + } + } + + txn.commit(); + } catch (Exception e) { + e.printStackTrace(); + txn.rollback(); + } finally { + session.close(); + } + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/MaliciousTrafficDetectorTask.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/MaliciousTrafficDetectorTask.java new file mode 100644 index 0000000000..a10aa3ef0d --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/MaliciousTrafficDetectorTask.java @@ -0,0 +1,353 @@ +package com.akto.threat.detection.tasks; + +import com.akto.dao.context.Context; +import com.akto.dao.monitoring.FilterYamlTemplateDao; +import com.akto.data_actor.DataActor; +import com.akto.data_actor.DataActorFactory; +import com.akto.dto.ApiInfo; +import com.akto.dto.HttpRequestParams; +import com.akto.dto.HttpResponseParams; +import com.akto.dto.OriginalHttpRequest; +import com.akto.dto.RawApi; +import com.akto.dto.api_protection_parse_layer.AggregationRules; +import com.akto.dto.api_protection_parse_layer.Condition; +import com.akto.dto.api_protection_parse_layer.Rule; +import com.akto.dto.monitoring.FilterConfig; +import com.akto.dto.test_editor.YamlTemplate; +import com.akto.dto.type.URLMethods; +import com.akto.hybrid_parsers.HttpCallParser; +import com.akto.kafka.KafkaConfig; +import com.akto.proto.generated.threat_detection.message.malicious_event.event_type.v1.EventType; +import com.akto.proto.generated.threat_detection.message.malicious_event.v1.MaliciousEventKafkaEnvelope; +import com.akto.proto.generated.threat_detection.message.malicious_event.v1.MaliciousEventMessage; +import com.akto.proto.generated.threat_detection.message.sample_request.v1.SampleMaliciousRequest; +import com.akto.proto.generated.threat_detection.message.sample_request.v1.SampleRequestKafkaEnvelope; +import com.akto.proto.http_response_param.v1.HttpResponseParam; +import com.akto.proto.http_response_param.v1.HttpResponseParamProto; +import com.akto.rules.TestPlugin; +import com.akto.runtime.utils.Utils; +import com.akto.test_editor.execution.VariableResolver; +import com.akto.test_editor.filter.data_operands_impl.ValidationResult; +import com.akto.threat.detection.actor.SourceIPActorGenerator; +import com.akto.threat.detection.cache.RedisBackedCounterCache; +import com.akto.threat.detection.constants.KafkaTopic; +import com.akto.threat.detection.dto.MessageEnvelope; +import com.akto.threat.detection.kafka.KafkaProtoProducer; +import com.akto.threat.detection.smart_event_detector.window_based.WindowBasedThresholdNotifier; +import com.akto.util.HttpRequestResponseUtils; +import com.akto.util.JSONUtils; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.ListValue; +import com.google.protobuf.util.JsonFormat; + +import io.lettuce.core.RedisClient; + +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; + +/* +Class is responsible for consuming traffic data from the Kafka topic. +Pass data through filters and identify malicious traffic. + */ +public class MaliciousTrafficDetectorTask implements Task { + + private final Consumer kafkaConsumer; + private final KafkaConfig kafkaConfig; + private final HttpCallParser httpCallParser; + private final WindowBasedThresholdNotifier windowBasedThresholdNotifier; + + private Map apiFilters; + private int filterLastUpdatedAt = 0; + private int filterUpdateIntervalSec = 900; + + private final KafkaProtoProducer internalKafka; + + private static final DataActor dataActor = DataActorFactory.fetchInstance(); + + public MaliciousTrafficDetectorTask( + KafkaConfig trafficConfig, KafkaConfig internalConfig, RedisClient redisClient) { + this.kafkaConfig = trafficConfig; + + String kafkaBrokerUrl = trafficConfig.getBootstrapServers(); + String groupId = trafficConfig.getGroupId(); + + this.kafkaConsumer = + new KafkaConsumer<>( + Utils.configProperties( + kafkaBrokerUrl, groupId, trafficConfig.getConsumerConfig().getMaxPollRecords())); + + this.httpCallParser = new HttpCallParser(120, 1000); + + this.windowBasedThresholdNotifier = + new WindowBasedThresholdNotifier( + new RedisBackedCounterCache(redisClient, "wbt"), + new WindowBasedThresholdNotifier.Config(100, 10 * 60)); + + this.internalKafka = new KafkaProtoProducer(internalConfig); + } + + public void run() { + this.kafkaConsumer.subscribe(Collections.singletonList("akto.api.logs")); + ExecutorService pollingExecutor = Executors.newSingleThreadExecutor(); + pollingExecutor.execute( + () -> { + // Poll data from Kafka topic + while (true) { + ConsumerRecords records = + kafkaConsumer.poll( + Duration.ofMillis(kafkaConfig.getConsumerConfig().getPollDurationMilli())); + + try { + for (ConsumerRecord record : records) { + HttpResponseParam httpResponseParam = HttpResponseParam.parseFrom(record.value()); + processRecord(httpResponseParam); + } + + if (!records.isEmpty()) { + // Should we commit even if there are no records ? + kafkaConsumer.commitSync(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + private Map getFilters() { + int now = (int) (System.currentTimeMillis() / 1000); + if (now - filterLastUpdatedAt < filterUpdateIntervalSec) { + return apiFilters; + } + + List templates = dataActor.fetchFilterYamlTemplates(); + apiFilters = FilterYamlTemplateDao.fetchFilterConfig(false, templates, false); + this.filterLastUpdatedAt = now; + return apiFilters; + } + + private boolean validateFilterForRequest( + FilterConfig apiFilter, RawApi rawApi, ApiInfo.ApiInfoKey apiInfoKey, String message) { + try { + System.out.println("using buildFromMessageNew func"); + + Map varMap = apiFilter.resolveVarMap(); + VariableResolver.resolveWordList( + varMap, + new HashMap>() { + { + put(apiInfoKey, Collections.singletonList(message)); + } + }, + apiInfoKey); + + String filterExecutionLogId = UUID.randomUUID().toString(); + ValidationResult res = + TestPlugin.validateFilter( + apiFilter.getFilter().getNode(), rawApi, apiInfoKey, varMap, filterExecutionLogId); + + return res.getIsValid(); + } catch (Exception e) { + e.printStackTrace(); + } + + return false; + } + + private void processRecord(HttpResponseParam record) throws Exception { + System.out.println("Kafka record: found - "); + + HttpResponseParams responseParam = buildHttpResponseParam(record); + + Context.accountId.set(Integer.parseInt(responseParam.getAccountId())); + Map filters = this.getFilters(); + if (filters.isEmpty()) { + System.out.println("No filters found"); + return; + } + + List maliciousMessages = new ArrayList<>(); + + System.out.println("Total number of filters: " + filters.size()); + + String message = responseParam.getOrig(); + RawApi rawApi = RawApi.buildFromMessageNew(responseParam); + int apiCollectionId = httpCallParser.createApiCollectionId(responseParam); + responseParam.requestParams.setApiCollectionId(apiCollectionId); + String url = responseParam.getRequestParams().getURL(); + URLMethods.Method method = + URLMethods.Method.fromString(responseParam.getRequestParams().getMethod()); + ApiInfo.ApiInfoKey apiInfoKey = new ApiInfo.ApiInfoKey(apiCollectionId, url, method); + + for (FilterConfig apiFilter : apiFilters.values()) { + boolean hasPassedFilter = validateFilterForRequest(apiFilter, rawApi, apiInfoKey, message); + + // If a request passes any of the filter, then it's a malicious request, + // and so we push it to kafka + if (hasPassedFilter) { + // Later we will also add aggregation support + // Eg: 100 4xx requests in last 10 minutes. + // But regardless of whether request falls in aggregation or not, + // we still push malicious requests to kafka + + System.out.println("Filter passed: " + apiFilter.getId()); + + // todo: modify fetch yaml and read aggregate rules from it + List rules = new ArrayList<>(); + rules.add(new Rule("Lfi Rule 1", new Condition(10, 10))); + AggregationRules aggRules = new AggregationRules(); + aggRules.setRule(rules); + + boolean isAggFilter = aggRules != null && !aggRules.getRule().isEmpty(); + + SourceIPActorGenerator.instance + .generate(responseParam) + .ifPresent( + actor -> { + String groupKey = apiFilter.getId(); + String aggKey = actor + "|" + groupKey; + + SampleMaliciousRequest maliciousReq = + SampleMaliciousRequest.newBuilder() + .setUrl(responseParam.getRequestParams().getURL()) + .setMethod(responseParam.getRequestParams().getMethod()) + .setPayload(responseParam.getOrig()) + .setIp(actor) // For now using actor as IP + .setApiCollectionId(responseParam.getRequestParams().getApiCollectionId()) + .setTimestamp(responseParam.getTime()) + .setFilterId(apiFilter.getId()) + .build(); + + maliciousMessages.add( + SampleRequestKafkaEnvelope.newBuilder() + .setActor(actor) + .setAccountId(responseParam.getAccountId()) + .setMaliciousRequest(maliciousReq) + .build()); + + if (!isAggFilter) { + generateAndPushMaliciousEventRequest( + apiFilter, actor, responseParam, maliciousReq, EventType.EVENT_TYPE_SINGLE); + return; + } + + // Aggregation rules + for (Rule rule : aggRules.getRule()) { + WindowBasedThresholdNotifier.Result result = + this.windowBasedThresholdNotifier.shouldNotify(aggKey, maliciousReq, rule); + + if (result.shouldNotify()) { + System.out.print("Notifying for aggregation rule: " + rule); + generateAndPushMaliciousEventRequest( + apiFilter, + actor, + responseParam, + maliciousReq, + EventType.EVENT_TYPE_AGGREGATED); + } + } + }); + } + } + + // Should we push all the messages in one go + // or call kafka.send for each HttpRequestParams + try { + maliciousMessages.forEach( + sample -> { + internalKafka.send(KafkaTopic.ThreatDetection.MALICIOUS_EVENTS, sample); + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void generateAndPushMaliciousEventRequest( + FilterConfig apiFilter, + String actor, + HttpResponseParams responseParam, + SampleMaliciousRequest maliciousReq, + EventType eventType) { + MaliciousEventMessage maliciousEvent = + MaliciousEventMessage.newBuilder() + .setFilterId(apiFilter.getId()) + .setActor(actor) + .setDetectedAt(responseParam.getTime()) + .setEventType(eventType) + .setLatestApiCollectionId(maliciousReq.getApiCollectionId()) + .setLatestApiIp(maliciousReq.getIp()) + .setLatestApiPayload(maliciousReq.getPayload()) + .setLatestApiMethod(maliciousReq.getMethod()) + .setDetectedAt(responseParam.getTime()) + .build(); + MaliciousEventKafkaEnvelope envelope = + MaliciousEventKafkaEnvelope.newBuilder() + .setActor(actor) + .setAccountId(responseParam.getAccountId()) + .setMaliciousEvent(maliciousEvent) + .build(); + internalKafka.send(KafkaTopic.ThreatDetection.ALERTS, envelope); + } + + public static HttpResponseParams buildHttpResponseParam(HttpResponseParam httpResponseParamProto) { + + String apiCollectionIdStr = httpResponseParamProto.getAktoVxlanId(); + int apiCollectionId = 0; + if (NumberUtils.isDigits(apiCollectionIdStr)) { + apiCollectionId = NumberUtils.toInt(apiCollectionIdStr, 0); + } + + String requestPayload = HttpRequestResponseUtils.rawToJsonString(httpResponseParamProto.getRequestPayload(), null); + + Map> reqHeaders = (Map) httpResponseParamProto.getRequestHeadersMap(); + + // for (Map.Entry entry : httpResponseParamProto.getRequestHeadersMap().entrySet()) { + // ArrayList list = new ArrayList<>(entry.getValue().getValuesList()); + // reqHeaders.put(entry.getKey(), list); + // } + + HttpRequestParams requestParams = + new HttpRequestParams(httpResponseParamProto.getMethod(), httpResponseParamProto.getPath(), httpResponseParamProto.getType(), + reqHeaders, requestPayload, apiCollectionId); + + String responsePayload = HttpRequestResponseUtils.rawToJsonString(httpResponseParamProto.getResponsePayload(), null); + + String sourceStr = httpResponseParamProto.getSource(); + if (sourceStr == null || sourceStr == "") { + sourceStr = HttpResponseParams.Source.OTHER.name(); + } + + HttpResponseParams.Source source = HttpResponseParams.Source.valueOf(sourceStr); + Map> respHeaders = (Map) httpResponseParamProto.getResponseHeadersMap(); + + // for (Map.Entry entry : httpResponseParamProto.getResponseHeadersMap().entrySet()) { + // ArrayList list = new ArrayList<>(entry.getValue().getValuesList()); + // respHeaders.put(entry.getKey(), list); + // } + + return new HttpResponseParams( + httpResponseParamProto.getType(), + httpResponseParamProto.getStatusCode(), + httpResponseParamProto.getStatus(), + respHeaders, + responsePayload, + requestParams, + httpResponseParamProto.getTime(), + httpResponseParamProto.getAktoAccountId(), + httpResponseParamProto.getIsPending(), + source, + "", + httpResponseParamProto.getIp(), + httpResponseParamProto.getDestIp(), + httpResponseParamProto.getDirection()); + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/SendMaliciousEventsToBackend.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/SendMaliciousEventsToBackend.java new file mode 100644 index 0000000000..2ee173f1a0 --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/SendMaliciousEventsToBackend.java @@ -0,0 +1,158 @@ +package com.akto.threat.detection.tasks; + +import com.akto.kafka.KafkaConfig; +import com.akto.proto.generated.threat_detection.message.malicious_event.event_type.v1.EventType; +import com.akto.proto.generated.threat_detection.message.malicious_event.v1.MaliciousEventKafkaEnvelope; +import com.akto.proto.generated.threat_detection.message.malicious_event.v1.MaliciousEventMessage; +import com.akto.proto.generated.threat_detection.message.sample_request.v1.SampleMaliciousRequest; +import com.akto.proto.generated.threat_detection.service.malicious_alert_service.v1.RecordMaliciousEventRequest; +import com.akto.proto.utils.ProtoMessageUtils; +import com.akto.threat.detection.db.entity.MaliciousEventEntity; +import com.akto.threat.detection.dto.MessageEnvelope; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +/* +This will send alerts to threat detection backend + */ +public class SendMaliciousEventsToBackend extends AbstractKafkaConsumerTask { + + private final SessionFactory sessionFactory; + private final CloseableHttpClient httpClient; + + public SendMaliciousEventsToBackend( + SessionFactory sessionFactory, KafkaConfig trafficConfig, String topic) { + super(trafficConfig, topic); + this.sessionFactory = sessionFactory; + this.httpClient = HttpClients.createDefault(); + } + + private void markSampleDataAsSent(List ids) { + Session session = this.sessionFactory.openSession(); + Transaction txn = session.beginTransaction(); + try { + session + .createQuery( + "update MaliciousEventEntity m set m.alertedToBackend = true where m.id in :ids") + .setParameterList("ids", ids) + .executeUpdate(); + } catch (Exception ex) { + ex.printStackTrace(); + txn.rollback(); + } finally { + txn.commit(); + session.close(); + } + } + + private List getSampleMaliciousRequests(String actor, String filterId) { + Session session = this.sessionFactory.openSession(); + Transaction txn = session.beginTransaction(); + try { + return session + .createQuery( + "from MaliciousEventEntity m where m.actor = :actor and m.filterId = :filterId and" + + " m.alertedToBackend = false order by m.createdAt desc", + MaliciousEventEntity.class) + .setParameter("actor", actor) + .setParameter("filterId", filterId) + .setMaxResults(50) + .getResultList(); + } catch (Exception ex) { + ex.printStackTrace(); + txn.rollback(); + } finally { + txn.commit(); + session.close(); + } + + return Collections.emptyList(); + } + + protected void processRecords(ConsumerRecords records) { + records.forEach( + r -> { + MaliciousEventKafkaEnvelope envelope; + try { + envelope = MaliciousEventKafkaEnvelope.parseFrom(r.value()); + } catch (InvalidProtocolBufferException e) { + e.printStackTrace(); + return; + } + + if (envelope == null) { + return; + } + + try { + MaliciousEventMessage evt = envelope.getMaliciousEvent(); + + // Get sample data from postgres for this alert + List sampleData = this.getSampleMaliciousRequests(evt.getActor(), + evt.getFilterId()); + RecordMaliciousEventRequest.Builder reqBuilder = RecordMaliciousEventRequest.newBuilder() + .setMaliciousEvent(evt); + if (EventType.EVENT_TYPE_AGGREGATED.equals(evt.getEventType())) { + sampleData = this.getSampleMaliciousRequests(evt.getActor(), evt.getFilterId()); + + reqBuilder.addAllSampleRequests( + sampleData.stream() + .map( + d -> SampleMaliciousRequest.newBuilder() + .setUrl(d.getUrl()) + .setMethod(d.getMethod().name()) + .setTimestamp(d.getTimestamp()) + .setPayload(d.getOrig()) + .setIp(d.getIp()) + .setApiCollectionId(d.getApiCollectionId()) + .build()) + .collect(Collectors.toList())); + } + + List sampleIds = sampleData.stream().map(MaliciousEventEntity::getId) + .collect(Collectors.toList()); + + RecordMaliciousEventRequest maliciousEventRequest = reqBuilder.build(); + String url = System.getenv("AKTO_THREAT_PROTECTION_BACKEND_URL"); + String token = System.getenv("AKTO_THREAT_PROTECTION_BACKEND_TOKEN"); + ProtoMessageUtils.toString(maliciousEventRequest) + .ifPresent( + msg -> { + StringEntity requestEntity = new StringEntity(msg, + ContentType.APPLICATION_JSON); + HttpPost req = new HttpPost( + String.format("%s/api/threat_detection/record_malicious_event", + url)); + req.addHeader("Authorization", "Bearer " + token); + req.setEntity(requestEntity); + try { + System.out.println("Sending request to backend: " + msg); + this.httpClient.execute(req); + } catch (IOException e) { + e.printStackTrace(); + } + + if (!sampleIds.isEmpty()) { + markSampleDataAsSent(sampleIds); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } +} diff --git a/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/Task.java b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/Task.java new file mode 100644 index 0000000000..1156ccbd8b --- /dev/null +++ b/apps/threat-detection/src/main/java/com/akto/threat/detection/tasks/Task.java @@ -0,0 +1,6 @@ +package com.akto.threat.detection.tasks; + +public interface Task { + + void run(); +} diff --git a/apps/threat-detection/src/main/resources/db/migration/V1__enable_uuid.sql b/apps/threat-detection/src/main/resources/db/migration/V1__enable_uuid.sql new file mode 100644 index 0000000000..e5c340505a --- /dev/null +++ b/apps/threat-detection/src/main/resources/db/migration/V1__enable_uuid.sql @@ -0,0 +1,2 @@ +-- enabling uuid extension +create extension if not exists "uuid-ossp"; \ No newline at end of file diff --git a/apps/threat-detection/src/main/resources/db/migration/V2__create_malicious_event_table.sql b/apps/threat-detection/src/main/resources/db/migration/V2__create_malicious_event_table.sql new file mode 100644 index 0000000000..17e1b9d80c --- /dev/null +++ b/apps/threat-detection/src/main/resources/db/migration/V2__create_malicious_event_table.sql @@ -0,0 +1,17 @@ +-- create schema and table for malicious events +create schema if not exists threat_detection; +create table if not exists threat_detection.malicious_event ( + id uuid primary key default uuid_generate_v4(), + actor varchar(255) not null, + filter_id varchar(255) not null, + url varchar(1024), + ip varchar(255), + method varchar(255), + timestamp bigint not null, + orig text not null, + api_collection_id int not null, + created_at timestamp default (timezone('utc', now())) +); + +-- add index on actor and filter_id and sort data by timestamp +create index malicious_events_actor_filter_id_timestamp_idx on threat_detection.malicious_event(actor, filter_id, timestamp desc); diff --git a/apps/threat-detection/src/main/resources/db/migration/V3__add_alert_to_backend_column.sql b/apps/threat-detection/src/main/resources/db/migration/V3__add_alert_to_backend_column.sql new file mode 100644 index 0000000000..756815e5b0 --- /dev/null +++ b/apps/threat-detection/src/main/resources/db/migration/V3__add_alert_to_backend_column.sql @@ -0,0 +1,4 @@ +alter table threat_detection.malicious_event add column _alerted_to_backend boolean default false; + +-- set all existing rows to false +update threat_detection.malicious_event set _alerted_to_backend = false; diff --git a/apps/threat-detection/src/main/resources/log4j2.xml b/apps/threat-detection/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..133e6bdd7e --- /dev/null +++ b/apps/threat-detection/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/api-threat-detection/src/main/resources/version.txt b/apps/threat-detection/src/main/resources/version.txt similarity index 100% rename from apps/api-threat-detection/src/main/resources/version.txt rename to apps/threat-detection/src/main/resources/version.txt diff --git a/libs/dao/src/main/java/com/akto/DaoInit.java b/libs/dao/src/main/java/com/akto/DaoInit.java index 7e4ea5a2fe..04ced65abf 100644 --- a/libs/dao/src/main/java/com/akto/DaoInit.java +++ b/libs/dao/src/main/java/com/akto/DaoInit.java @@ -72,6 +72,8 @@ import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; import com.mongodb.ReadPreference; +import com.mongodb.client.MongoClient; +import com.mongodb.WriteConcern; import com.mongodb.WriteConcern; import com.mongodb.client.MongoClients; @@ -88,327 +90,471 @@ public class DaoInit { - private static final Logger logger = LoggerFactory.getLogger(DaoInit.class); + private static final Logger logger = LoggerFactory.getLogger(DaoInit.class); - public static CodecRegistry createCodecRegistry(){ - ClassModel configClassModel = ClassModel.builder(Config.class).enableDiscriminator(true).build(); - ClassModel signupInfoClassModel = ClassModel.builder(SignupInfo.class).enableDiscriminator(true) - .build(); - ClassModel apiAuthClassModel = ClassModel.builder(APIAuth.class).enableDiscriminator(true).build(); - ClassModel attempResultModel = ClassModel.builder(AttemptResult.class).enableDiscriminator(true) - .build(); - ClassModel urlTemplateModel = ClassModel.builder(URLTemplate.class).enableDiscriminator(true) - .build(); - ClassModel pendingInviteCodeClassModel = ClassModel.builder(PendingInviteCode.class) - .enableDiscriminator(true).build(); - ClassModel rbacClassModel = ClassModel.builder(RBAC.class).enableDiscriminator(true).build(); - ClassModel singleTypeInfoClassModel = ClassModel.builder(SingleTypeInfo.class) - .enableDiscriminator(true).build(); - ClassModel kafkaHealthMetricClassModel = ClassModel.builder(KafkaHealthMetric.class) - .enableDiscriminator(true).build(); - ClassModel thirdPartyAccessClassModel = ClassModel.builder(ThirdPartyAccess.class) - .enableDiscriminator(true).build(); - ClassModel credentialClassModel = ClassModel.builder(Credential.class).enableDiscriminator(true) - .build(); - ClassModel apiTokenClassModel = ClassModel.builder(ApiToken.class).enableDiscriminator(true).build(); - ClassModel apiInfoClassModel = ClassModel.builder(ApiInfo.class).enableDiscriminator(true).build(); - ClassModel apiInfoKeyClassModel = ClassModel.builder(ApiInfo.ApiInfoKey.class) - .enableDiscriminator(true).build(); - ClassModel customFilterClassModel = ClassModel.builder(CustomFilter.class) - .enableDiscriminator(true).build(); - ClassModel fieldExistsFilterClassModel = ClassModel.builder(FieldExistsFilter.class) - .enableDiscriminator(true).build(); - ClassModel responseCodeRuntimeFilterClassModel = ClassModel - .builder(ResponseCodeRuntimeFilter.class).enableDiscriminator(true).build(); - ; - ClassModel runtimeFilterClassModel = ClassModel.builder(RuntimeFilter.class) - .enableDiscriminator(true).build(); - ClassModel filterSampleDataClassModel = ClassModel.builder(FilterSampleData.class) - .enableDiscriminator(true).build(); - ClassModel accountSettingsClassModel = ClassModel.builder(AccountSettings.class) - .enableDiscriminator(true).build(); - ClassModel predicateClassModel = ClassModel.builder(Predicate.class).enableDiscriminator(true) - .build(); - ClassModel regexPredicateClassModel = ClassModel.builder(RegexPredicate.class) - .enableDiscriminator(true).build(); - ClassModel startsWithPredicateClassModel = ClassModel.builder(StartsWithPredicate.class) - .enableDiscriminator(true).build(); - ClassModel endsWithPredicateClassModel = ClassModel.builder(EndsWithPredicate.class) - .enableDiscriminator(true).build(); - ClassModel equalsToPredicateClassModel = ClassModel.builder(EqualsToPredicate.class) - .enableDiscriminator(true).build(); - ClassModel isNumberPredicateClassModel = ClassModel.builder(IsNumberPredicate.class) - .enableDiscriminator(true).build(); - ClassModel conditionsClassModel = ClassModel.builder(Conditions.class).enableDiscriminator(true) - .build(); - ClassModel cappedListClassModel = ClassModel.builder(CappedList.class).enableDiscriminator(true) - .build(); - ClassModel testingRunClassModel = ClassModel.builder(TestingRun.class).enableDiscriminator(true) - .build(); - ClassModel testingRunResultClassModel = ClassModel.builder(TestingRunResult.class) - .enableDiscriminator(true).build(); - ClassModel testResultClassModel = ClassModel.builder(TestResult.class).enableDiscriminator(true) - .build(); - ClassModel multiExecTestResultClassModel = ClassModel.builder(MultiExecTestResult.class).enableDiscriminator(true) - .build(); - ClassModel genericTestResultClassModel = ClassModel.builder(GenericTestResult.class).enableDiscriminator(true) - .build(); - ClassModel authMechanismClassModel = ClassModel.builder(AuthMechanism.class) - .enableDiscriminator(true).build(); - ClassModel setupClassModel = ClassModel.builder(Setup.class) - .enableDiscriminator(true).build(); - ClassModel authParamClassModel = ClassModel.builder(AuthParam.class).enableDiscriminator(true) - .build(); - ClassModel hardcodedAuthParamClassModel = ClassModel.builder(HardcodedAuthParam.class) - .enableDiscriminator(true).build(); - ClassModel loginReqAuthParamClassModel = ClassModel.builder(LoginRequestAuthParam.class) - .enableDiscriminator(true).build(); - ClassModel testingEndpointsClassModel = ClassModel.builder(TestingEndpoints.class) - .enableDiscriminator(true).build(); - ClassModel customTestingEndpointsClassModel = ClassModel - .builder(CustomTestingEndpoints.class).enableDiscriminator(true).build(); - ClassModel allTestingEndpointsClassModel = ClassModel - .builder(AllTestingEndpoints.class).enableDiscriminator(true).build(); - ClassModel collectionWiseTestingEndpointsClassModel = ClassModel - .builder(CollectionWiseTestingEndpoints.class).enableDiscriminator(true).build(); - ClassModel workflowTestingEndpointsClassModel = ClassModel - .builder(WorkflowTestingEndpoints.class).enableDiscriminator(true).build(); - ClassModel workflowTestResultClassModel = ClassModel.builder(WorkflowTestResult.class) - .enableDiscriminator(true).build(); - ClassModel workflowTestClassModel = ClassModel.builder(WorkflowTest.class) - .enableDiscriminator(true).build(); - ClassModel cappedSetClassModel = ClassModel.builder(CappedSet.class).enableDiscriminator(true) - .build(); - ClassModel CustomWebhookClassModel = ClassModel.builder(CustomWebhook.class) - .enableDiscriminator(true).build(); - ClassModel WorkflowNodeDetailsClassModel = ClassModel.builder(WorkflowNodeDetails.class) - .enableDiscriminator(true).build(); - ClassModel CustomWebhookResultClassModel = ClassModel.builder(CustomWebhookResult.class) - .enableDiscriminator(true).build(); - ClassModel nodeResultClassModel = ClassModel - .builder(WorkflowTestResult.NodeResult.class).enableDiscriminator(true).build(); - ClassModel testingRunIssuesClassModel = ClassModel - .builder(TestingRunIssues.class).enableDiscriminator(true).build(); - ClassModel testingIssuesIdClassModel = ClassModel - .builder(TestingIssuesId.class).enableDiscriminator(true).build(); - ClassModel testSourceConfigClassModel = ClassModel - .builder(TestSourceConfig.class).enableDiscriminator(true).build(); - ClassModel endpointLogicalGroupClassModel = ClassModel - .builder(EndpointLogicalGroup.class).enableDiscriminator(true).build(); - ClassModel testRolesClassModel = ClassModel - .builder(TestRoles.class).enableDiscriminator(true).build(); - ClassModel logicalGroupTestingEndpointClassModel = ClassModel - .builder(LogicalGroupTestingEndpoint.class).enableDiscriminator(true).build(); - ClassModel customAuthTypeModel = ClassModel - .builder(CustomAuthType.class).enableDiscriminator(true).build(); - ClassModel containsPredicateClassModel = ClassModel - .builder(ContainsPredicate.class).enableDiscriminator(true).build(); - ClassModel notBelongsToPredicateClassModel = ClassModel - .builder(NotBelongsToPredicate.class).enableDiscriminator(true).build(); - ClassModel belongsToPredicateClassModel = ClassModel - .builder(BelongsToPredicate.class).enableDiscriminator(true).build(); - ClassModel yamlNodeDetails = ClassModel - .builder(YamlNodeDetails.class).enableDiscriminator(true).build(); - ClassModel unauthenticatedEndpointsClassModel = ClassModel - .builder(UnauthenticatedEndpoint.class).enableDiscriminator(true).build(); - ClassModel eventsExampleClassModel = ClassModel - .builder(EventsExample.class).enableDiscriminator(true).build(); - // ClassModel awsResourceModel = - // ClassModel.builder(AwsResource.class).enableDiscriminator(true) - // .build(); - ClassModel awsResourcesModel = ClassModel.builder(AwsResources.class).enableDiscriminator(true) - .build(); - ClassModel AktoDataTypeClassModel = ClassModel.builder(AktoDataType.class).enableDiscriminator(true).build(); - ClassModel testInfoClassModel = ClassModel.builder(TestInfo.class).enableDiscriminator(true).build(); - ClassModel bflaTestInfoClassModel = ClassModel.builder(BFLATestInfo.class).enableDiscriminator(true).build(); - ClassModel accessMatrixUrlToRoleClassModel = ClassModel.builder(AccessMatrixUrlToRole.class).enableDiscriminator(true).build(); - ClassModel accessMatrixTaskInfoClassModel = ClassModel.builder(AccessMatrixTaskInfo.class).enableDiscriminator(true).build(); - ClassModel loaderClassModel = ClassModel.builder(Loader.class).enableDiscriminator(true).build(); - ClassModel normalLoaderClassModel = ClassModel.builder(NormalLoader.class).enableDiscriminator(true).build(); - ClassModel postmanUploadLoaderClassModel = ClassModel.builder(PostmanUploadLoader.class).enableDiscriminator(true).build(); - ClassModel aktoGptConfigClassModel = ClassModel.builder(AktoGptConfig.class).enableDiscriminator(true).build(); + public static CodecRegistry createCodecRegistry() { + ClassModel configClassModel = + ClassModel.builder(Config.class).enableDiscriminator(true).build(); + ClassModel signupInfoClassModel = + ClassModel.builder(SignupInfo.class).enableDiscriminator(true).build(); + ClassModel apiAuthClassModel = + ClassModel.builder(APIAuth.class).enableDiscriminator(true).build(); + ClassModel attempResultModel = + ClassModel.builder(AttemptResult.class).enableDiscriminator(true).build(); + ClassModel urlTemplateModel = + ClassModel.builder(URLTemplate.class).enableDiscriminator(true).build(); + ClassModel pendingInviteCodeClassModel = + ClassModel.builder(PendingInviteCode.class).enableDiscriminator(true).build(); + ClassModel rbacClassModel = + ClassModel.builder(RBAC.class).enableDiscriminator(true).build(); + ClassModel singleTypeInfoClassModel = + ClassModel.builder(SingleTypeInfo.class).enableDiscriminator(true).build(); + ClassModel kafkaHealthMetricClassModel = + ClassModel.builder(KafkaHealthMetric.class).enableDiscriminator(true).build(); + ClassModel thirdPartyAccessClassModel = + ClassModel.builder(ThirdPartyAccess.class).enableDiscriminator(true).build(); + ClassModel credentialClassModel = + ClassModel.builder(Credential.class).enableDiscriminator(true).build(); + ClassModel apiTokenClassModel = + ClassModel.builder(ApiToken.class).enableDiscriminator(true).build(); + ClassModel apiInfoClassModel = + ClassModel.builder(ApiInfo.class).enableDiscriminator(true).build(); + ClassModel apiInfoKeyClassModel = + ClassModel.builder(ApiInfo.ApiInfoKey.class).enableDiscriminator(true).build(); + ClassModel customFilterClassModel = + ClassModel.builder(CustomFilter.class).enableDiscriminator(true).build(); + ClassModel fieldExistsFilterClassModel = + ClassModel.builder(FieldExistsFilter.class).enableDiscriminator(true).build(); + ClassModel responseCodeRuntimeFilterClassModel = + ClassModel.builder(ResponseCodeRuntimeFilter.class).enableDiscriminator(true).build(); + ; + ClassModel runtimeFilterClassModel = + ClassModel.builder(RuntimeFilter.class).enableDiscriminator(true).build(); + ClassModel filterSampleDataClassModel = + ClassModel.builder(FilterSampleData.class).enableDiscriminator(true).build(); + ClassModel accountSettingsClassModel = + ClassModel.builder(AccountSettings.class).enableDiscriminator(true).build(); + ClassModel predicateClassModel = + ClassModel.builder(Predicate.class).enableDiscriminator(true).build(); + ClassModel regexPredicateClassModel = + ClassModel.builder(RegexPredicate.class).enableDiscriminator(true).build(); + ClassModel startsWithPredicateClassModel = + ClassModel.builder(StartsWithPredicate.class).enableDiscriminator(true).build(); + ClassModel endsWithPredicateClassModel = + ClassModel.builder(EndsWithPredicate.class).enableDiscriminator(true).build(); + ClassModel equalsToPredicateClassModel = + ClassModel.builder(EqualsToPredicate.class).enableDiscriminator(true).build(); + ClassModel isNumberPredicateClassModel = + ClassModel.builder(IsNumberPredicate.class).enableDiscriminator(true).build(); + ClassModel conditionsClassModel = + ClassModel.builder(Conditions.class).enableDiscriminator(true).build(); + ClassModel cappedListClassModel = + ClassModel.builder(CappedList.class).enableDiscriminator(true).build(); + ClassModel testingRunClassModel = + ClassModel.builder(TestingRun.class).enableDiscriminator(true).build(); + ClassModel testingRunResultClassModel = + ClassModel.builder(TestingRunResult.class).enableDiscriminator(true).build(); + ClassModel testResultClassModel = + ClassModel.builder(TestResult.class).enableDiscriminator(true).build(); + ClassModel multiExecTestResultClassModel = + ClassModel.builder(MultiExecTestResult.class).enableDiscriminator(true).build(); + ClassModel genericTestResultClassModel = + ClassModel.builder(GenericTestResult.class).enableDiscriminator(true).build(); + ClassModel authMechanismClassModel = + ClassModel.builder(AuthMechanism.class).enableDiscriminator(true).build(); + ClassModel setupClassModel = + ClassModel.builder(Setup.class).enableDiscriminator(true).build(); + ClassModel authParamClassModel = + ClassModel.builder(AuthParam.class).enableDiscriminator(true).build(); + ClassModel hardcodedAuthParamClassModel = + ClassModel.builder(HardcodedAuthParam.class).enableDiscriminator(true).build(); + ClassModel loginReqAuthParamClassModel = + ClassModel.builder(LoginRequestAuthParam.class).enableDiscriminator(true).build(); + ClassModel testingEndpointsClassModel = + ClassModel.builder(TestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel customTestingEndpointsClassModel = + ClassModel.builder(CustomTestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel allTestingEndpointsClassModel = + ClassModel.builder(AllTestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel collectionWiseTestingEndpointsClassModel = + ClassModel.builder(CollectionWiseTestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel workflowTestingEndpointsClassModel = + ClassModel.builder(WorkflowTestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel workflowTestResultClassModel = + ClassModel.builder(WorkflowTestResult.class).enableDiscriminator(true).build(); + ClassModel workflowTestClassModel = + ClassModel.builder(WorkflowTest.class).enableDiscriminator(true).build(); + ClassModel cappedSetClassModel = + ClassModel.builder(CappedSet.class).enableDiscriminator(true).build(); + ClassModel CustomWebhookClassModel = + ClassModel.builder(CustomWebhook.class).enableDiscriminator(true).build(); + ClassModel WorkflowNodeDetailsClassModel = + ClassModel.builder(WorkflowNodeDetails.class).enableDiscriminator(true).build(); + ClassModel CustomWebhookResultClassModel = + ClassModel.builder(CustomWebhookResult.class).enableDiscriminator(true).build(); + ClassModel nodeResultClassModel = + ClassModel.builder(WorkflowTestResult.NodeResult.class).enableDiscriminator(true).build(); + ClassModel testingRunIssuesClassModel = + ClassModel.builder(TestingRunIssues.class).enableDiscriminator(true).build(); + ClassModel testingIssuesIdClassModel = + ClassModel.builder(TestingIssuesId.class).enableDiscriminator(true).build(); + ClassModel testSourceConfigClassModel = + ClassModel.builder(TestSourceConfig.class).enableDiscriminator(true).build(); + ClassModel endpointLogicalGroupClassModel = + ClassModel.builder(EndpointLogicalGroup.class).enableDiscriminator(true).build(); + ClassModel testRolesClassModel = + ClassModel.builder(TestRoles.class).enableDiscriminator(true).build(); + ClassModel logicalGroupTestingEndpointClassModel = + ClassModel.builder(LogicalGroupTestingEndpoint.class).enableDiscriminator(true).build(); + ClassModel customAuthTypeModel = + ClassModel.builder(CustomAuthType.class).enableDiscriminator(true).build(); + ClassModel containsPredicateClassModel = + ClassModel.builder(ContainsPredicate.class).enableDiscriminator(true).build(); + ClassModel notBelongsToPredicateClassModel = + ClassModel.builder(NotBelongsToPredicate.class).enableDiscriminator(true).build(); + ClassModel belongsToPredicateClassModel = + ClassModel.builder(BelongsToPredicate.class).enableDiscriminator(true).build(); + ClassModel yamlNodeDetails = + ClassModel.builder(YamlNodeDetails.class).enableDiscriminator(true).build(); + ClassModel unauthenticatedEndpointsClassModel = + ClassModel.builder(UnauthenticatedEndpoint.class).enableDiscriminator(true).build(); + ClassModel eventsExampleClassModel = + ClassModel.builder(EventsExample.class).enableDiscriminator(true).build(); + // ClassModel awsResourceModel = + // ClassModel.builder(AwsResource.class).enableDiscriminator(true) + // .build(); + ClassModel awsResourcesModel = + ClassModel.builder(AwsResources.class).enableDiscriminator(true).build(); + ClassModel AktoDataTypeClassModel = + ClassModel.builder(AktoDataType.class).enableDiscriminator(true).build(); + ClassModel testInfoClassModel = + ClassModel.builder(TestInfo.class).enableDiscriminator(true).build(); + ClassModel bflaTestInfoClassModel = + ClassModel.builder(BFLATestInfo.class).enableDiscriminator(true).build(); + ClassModel accessMatrixUrlToRoleClassModel = + ClassModel.builder(AccessMatrixUrlToRole.class).enableDiscriminator(true).build(); + ClassModel accessMatrixTaskInfoClassModel = + ClassModel.builder(AccessMatrixTaskInfo.class).enableDiscriminator(true).build(); + ClassModel loaderClassModel = + ClassModel.builder(Loader.class).enableDiscriminator(true).build(); + ClassModel normalLoaderClassModel = + ClassModel.builder(NormalLoader.class).enableDiscriminator(true).build(); + ClassModel postmanUploadLoaderClassModel = + ClassModel.builder(PostmanUploadLoader.class).enableDiscriminator(true).build(); + ClassModel aktoGptConfigClassModel = + ClassModel.builder(AktoGptConfig.class).enableDiscriminator(true).build(); - ClassModel loginFlowStepsData = ClassModel.builder(LoginFlowStepsData.class) - .enableDiscriminator(true).build(); - ClassModel vulnerableRequestForTemplateClassModel = ClassModel.builder(VulnerableRequestForTemplate.class).enableDiscriminator(true).build(); - ClassModel trafficMetricsAlertClassModel = ClassModel.builder(TrafficMetricsAlert.class).enableDiscriminator(true).build(); - ClassModel jiraintegrationClassModel = ClassModel.builder(JiraIntegration.class).enableDiscriminator(true).build(); - ClassModel methodConditionClassModel = ClassModel.builder(MethodCondition.class).enableDiscriminator(true).build(); - ClassModel regexTestingEndpointsClassModel = ClassModel.builder(RegexTestingEndpoints.class).enableDiscriminator(true).build(); - ClassModel hostRegexTestingEndpointsClassModel = ClassModel.builder(HostRegexTestingEndpoints.class).enableDiscriminator(true).build(); - ClassModel dependencyNodeClassModel = ClassModel.builder(DependencyNode.class).enableDiscriminator(true).build(); - ClassModel paramInfoClassModel = ClassModel.builder(ParamInfo.class).enableDiscriminator(true).build(); - ClassModel nodeClassModel = ClassModel.builder(Node.class).enableDiscriminator(true).build(); - ClassModel connectionClassModel = ClassModel.builder(Connection.class).enableDiscriminator(true).build(); - ClassModel edgeClassModel = ClassModel.builder(Edge.class).enableDiscriminator(true).build(); - ClassModel cronTimersClassModel = ClassModel.builder(LastCronRunInfo.class) - .enableDiscriminator(true).build(); - ClassModel connectionInfoClassModel = ClassModel.builder(ConnectionInfo.class) - .enableDiscriminator(true).build(); - ClassModel testLibraryClassModel = ClassModel.builder(TestLibrary.class).enableDiscriminator(true).build(); + ClassModel loginFlowStepsData = + ClassModel.builder(LoginFlowStepsData.class).enableDiscriminator(true).build(); + ClassModel vulnerableRequestForTemplateClassModel = + ClassModel.builder(VulnerableRequestForTemplate.class).enableDiscriminator(true).build(); + ClassModel trafficMetricsAlertClassModel = + ClassModel.builder(TrafficMetricsAlert.class).enableDiscriminator(true).build(); + ClassModel jiraintegrationClassModel = + ClassModel.builder(JiraIntegration.class).enableDiscriminator(true).build(); + ClassModel methodConditionClassModel = + ClassModel.builder(MethodCondition.class).enableDiscriminator(true).build(); + ClassModel regexTestingEndpointsClassModel = + ClassModel.builder(RegexTestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel hostRegexTestingEndpointsClassModel = + ClassModel.builder(HostRegexTestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel dependencyNodeClassModel = + ClassModel.builder(DependencyNode.class).enableDiscriminator(true).build(); + ClassModel paramInfoClassModel = + ClassModel.builder(ParamInfo.class).enableDiscriminator(true).build(); + ClassModel nodeClassModel = + ClassModel.builder(Node.class).enableDiscriminator(true).build(); + ClassModel connectionClassModel = + ClassModel.builder(Connection.class).enableDiscriminator(true).build(); + ClassModel edgeClassModel = + ClassModel.builder(Edge.class).enableDiscriminator(true).build(); + ClassModel cronTimersClassModel = + ClassModel.builder(LastCronRunInfo.class).enableDiscriminator(true).build(); + ClassModel connectionInfoClassModel = + ClassModel.builder(ConnectionInfo.class).enableDiscriminator(true).build(); + ClassModel testLibraryClassModel = + ClassModel.builder(TestLibrary.class).enableDiscriminator(true).build(); - ClassModel UsageMetricClassModel = ClassModel.builder(UsageMetric.class).enableDiscriminator(true).build(); - ClassModel UsageMetricInfoClassModel = ClassModel.builder(UsageMetricInfo.class).enableDiscriminator(true).build(); - ClassModel UsageSyncClassModel = ClassModel.builder(UsageSync.class).enableDiscriminator(true).build(); - ClassModel OrganizationClassModel = ClassModel.builder(Organization.class).enableDiscriminator(true).build(); - ClassModel replaceDetailClassModel = ClassModel.builder(ReplaceDetail.class).enableDiscriminator(true).build(); - ClassModel modifyHostDetailClassModel = ClassModel.builder(ModifyHostDetail.class).enableDiscriminator(true).build(); - ClassModel fileUploadClassModel = ClassModel.builder(FileUpload.class).enableDiscriminator(true).build(); - ClassModel fileUploadLogClassModel = ClassModel.builder(FileUploadLog.class).enableDiscriminator(true).build(); - ClassModel codeAnalysisCollectionClassModel = ClassModel.builder(CodeAnalysisCollection.class).enableDiscriminator(true).build(); - ClassModel codeAnalysisApiLocationClassModel = ClassModel.builder(CodeAnalysisApiLocation.class).enableDiscriminator(true).build(); - ClassModel codeAnalysisApiInfoClassModel = ClassModel.builder(CodeAnalysisApiInfo.class).enableDiscriminator(true).build(); - ClassModel codeAnalysisApiInfoKeyClassModel = ClassModel.builder(CodeAnalysisApiInfo.CodeAnalysisApiInfoKey.class).enableDiscriminator(true).build(); - ClassModel riskScoreTestingEndpointsClassModel = ClassModel.builder(RiskScoreTestingEndpoints.class).enableDiscriminator(true).build(); - ClassModel OrganizationFlagsClassModel = ClassModel.builder(OrganizationFlags.class).enableDiscriminator(true).build(); - ClassModel sensitiveDataEndpointsClassModel = ClassModel.builder(SensitiveDataEndpoints.class).enableDiscriminator(true).build(); - ClassModel allApisGroupClassModel = ClassModel.builder(AllAPIsGroup.class).enableDiscriminator(true).build(); + ClassModel UsageMetricClassModel = + ClassModel.builder(UsageMetric.class).enableDiscriminator(true).build(); + ClassModel UsageMetricInfoClassModel = + ClassModel.builder(UsageMetricInfo.class).enableDiscriminator(true).build(); + ClassModel UsageSyncClassModel = + ClassModel.builder(UsageSync.class).enableDiscriminator(true).build(); + ClassModel OrganizationClassModel = + ClassModel.builder(Organization.class).enableDiscriminator(true).build(); + ClassModel replaceDetailClassModel = + ClassModel.builder(ReplaceDetail.class).enableDiscriminator(true).build(); + ClassModel modifyHostDetailClassModel = + ClassModel.builder(ModifyHostDetail.class).enableDiscriminator(true).build(); + ClassModel fileUploadClassModel = + ClassModel.builder(FileUpload.class).enableDiscriminator(true).build(); + ClassModel fileUploadLogClassModel = + ClassModel.builder(FileUploadLog.class).enableDiscriminator(true).build(); + ClassModel codeAnalysisCollectionClassModel = + ClassModel.builder(CodeAnalysisCollection.class).enableDiscriminator(true).build(); + ClassModel codeAnalysisApiLocationClassModel = + ClassModel.builder(CodeAnalysisApiLocation.class).enableDiscriminator(true).build(); + ClassModel codeAnalysisApiInfoClassModel = + ClassModel.builder(CodeAnalysisApiInfo.class).enableDiscriminator(true).build(); + ClassModel codeAnalysisApiInfoKeyClassModel = + ClassModel.builder(CodeAnalysisApiInfo.CodeAnalysisApiInfoKey.class) + .enableDiscriminator(true) + .build(); + ClassModel riskScoreTestingEndpointsClassModel = + ClassModel.builder(RiskScoreTestingEndpoints.class).enableDiscriminator(true).build(); + ClassModel OrganizationFlagsClassModel = + ClassModel.builder(OrganizationFlags.class).enableDiscriminator(true).build(); + ClassModel sensitiveDataEndpointsClassModel = + ClassModel.builder(SensitiveDataEndpoints.class).enableDiscriminator(true).build(); + ClassModel allApisGroupClassModel = + ClassModel.builder(AllAPIsGroup.class).enableDiscriminator(true).build(); - ClassModel RuntimeMetricsClassModel = ClassModel.builder(RuntimeMetrics.class).enableDiscriminator(true).build(); - ClassModel codeAnalysisApiModel = ClassModel.builder(CodeAnalysisApi.class).enableDiscriminator(true).build(); - ClassModel codeAnalysisRepoModel = ClassModel.builder(CodeAnalysisRepo.class).enableDiscriminator(true).build(); - ClassModel historicalDataClassModel = ClassModel.builder(HistoricalData.class).enableDiscriminator(true).build(); - ClassModel configSettingClassModel = ClassModel.builder(TestConfigsAdvancedSettings.class).enableDiscriminator(true).build(); - ClassModel configSettingsConditionTypeClassModel = ClassModel.builder(ConditionsType.class).enableDiscriminator(true).build(); - CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().register( - configClassModel, signupInfoClassModel, apiAuthClassModel, attempResultModel, urlTemplateModel, - pendingInviteCodeClassModel, rbacClassModel, kafkaHealthMetricClassModel, singleTypeInfoClassModel, - thirdPartyAccessClassModel, credentialClassModel, apiTokenClassModel, apiInfoClassModel, - apiInfoKeyClassModel, customFilterClassModel, runtimeFilterClassModel, filterSampleDataClassModel, - predicateClassModel, conditionsClassModel, regexPredicateClassModel, startsWithPredicateClassModel, - endsWithPredicateClassModel, - fieldExistsFilterClassModel, accountSettingsClassModel, responseCodeRuntimeFilterClassModel, - cappedListClassModel, - equalsToPredicateClassModel, isNumberPredicateClassModel, testingRunClassModel, - testingRunResultClassModel, testResultClassModel, genericTestResultClassModel, - authMechanismClassModel, authParamClassModel, hardcodedAuthParamClassModel, loginReqAuthParamClassModel, - testingEndpointsClassModel, customTestingEndpointsClassModel, collectionWiseTestingEndpointsClassModel, - workflowTestingEndpointsClassModel, workflowTestResultClassModel, - cappedSetClassModel, CustomWebhookClassModel, WorkflowNodeDetailsClassModel, CustomWebhookResultClassModel, - nodeResultClassModel, awsResourcesModel, AktoDataTypeClassModel, testingRunIssuesClassModel, - testingIssuesIdClassModel, testSourceConfigClassModel, endpointLogicalGroupClassModel, testRolesClassModel, - logicalGroupTestingEndpointClassModel, testInfoClassModel, bflaTestInfoClassModel, customAuthTypeModel, - containsPredicateClassModel, notBelongsToPredicateClassModel, belongsToPredicateClassModel, loginFlowStepsData, - accessMatrixUrlToRoleClassModel, accessMatrixTaskInfoClassModel, - loaderClassModel, normalLoaderClassModel, postmanUploadLoaderClassModel, aktoGptConfigClassModel, - vulnerableRequestForTemplateClassModel, trafficMetricsAlertClassModel,jiraintegrationClassModel, setupClassModel, - cronTimersClassModel, connectionInfoClassModel, testLibraryClassModel, - methodConditionClassModel, regexTestingEndpointsClassModel, hostRegexTestingEndpointsClassModel, allTestingEndpointsClassModel, - UsageMetricClassModel, UsageMetricInfoClassModel, UsageSyncClassModel, OrganizationClassModel, - yamlNodeDetails, multiExecTestResultClassModel, workflowTestClassModel, dependencyNodeClassModel, paramInfoClassModel, - nodeClassModel, connectionClassModel, edgeClassModel, replaceDetailClassModel, modifyHostDetailClassModel, fileUploadClassModel - ,fileUploadLogClassModel, codeAnalysisCollectionClassModel, codeAnalysisApiLocationClassModel, codeAnalysisApiInfoClassModel, codeAnalysisApiInfoKeyClassModel, - riskScoreTestingEndpointsClassModel, OrganizationFlagsClassModel, sensitiveDataEndpointsClassModel, unauthenticatedEndpointsClassModel, allApisGroupClassModel, - eventsExampleClassModel, RuntimeMetricsClassModel, codeAnalysisRepoModel, codeAnalysisApiModel, historicalDataClassModel, configSettingClassModel, configSettingsConditionTypeClassModel).automatic(true).build()); + ClassModel RuntimeMetricsClassModel = + ClassModel.builder(RuntimeMetrics.class).enableDiscriminator(true).build(); + ClassModel codeAnalysisApiModel = + ClassModel.builder(CodeAnalysisApi.class).enableDiscriminator(true).build(); + ClassModel codeAnalysisRepoModel = + ClassModel.builder(CodeAnalysisRepo.class).enableDiscriminator(true).build(); + ClassModel historicalDataClassModel = + ClassModel.builder(HistoricalData.class).enableDiscriminator(true).build(); + ClassModel configSettingClassModel = + ClassModel.builder(TestConfigsAdvancedSettings.class).enableDiscriminator(true).build(); + ClassModel configSettingsConditionTypeClassModel = + ClassModel.builder(ConditionsType.class).enableDiscriminator(true).build(); + CodecRegistry pojoCodecRegistry = + fromProviders( + PojoCodecProvider.builder() + .register( + configClassModel, + signupInfoClassModel, + apiAuthClassModel, + attempResultModel, + urlTemplateModel, + pendingInviteCodeClassModel, + rbacClassModel, + kafkaHealthMetricClassModel, + singleTypeInfoClassModel, + thirdPartyAccessClassModel, + credentialClassModel, + apiTokenClassModel, + apiInfoClassModel, + apiInfoKeyClassModel, + customFilterClassModel, + runtimeFilterClassModel, + filterSampleDataClassModel, + predicateClassModel, + conditionsClassModel, + regexPredicateClassModel, + startsWithPredicateClassModel, + endsWithPredicateClassModel, + fieldExistsFilterClassModel, + accountSettingsClassModel, + responseCodeRuntimeFilterClassModel, + cappedListClassModel, + equalsToPredicateClassModel, + isNumberPredicateClassModel, + testingRunClassModel, + testingRunResultClassModel, + testResultClassModel, + genericTestResultClassModel, + authMechanismClassModel, + authParamClassModel, + hardcodedAuthParamClassModel, + loginReqAuthParamClassModel, + testingEndpointsClassModel, + customTestingEndpointsClassModel, + collectionWiseTestingEndpointsClassModel, + workflowTestingEndpointsClassModel, + workflowTestResultClassModel, + cappedSetClassModel, + CustomWebhookClassModel, + WorkflowNodeDetailsClassModel, + CustomWebhookResultClassModel, + nodeResultClassModel, + awsResourcesModel, + AktoDataTypeClassModel, + testingRunIssuesClassModel, + testingIssuesIdClassModel, + testSourceConfigClassModel, + endpointLogicalGroupClassModel, + testRolesClassModel, + logicalGroupTestingEndpointClassModel, + testInfoClassModel, + bflaTestInfoClassModel, + customAuthTypeModel, + containsPredicateClassModel, + notBelongsToPredicateClassModel, + belongsToPredicateClassModel, + loginFlowStepsData, + accessMatrixUrlToRoleClassModel, + accessMatrixTaskInfoClassModel, + loaderClassModel, + normalLoaderClassModel, + postmanUploadLoaderClassModel, + aktoGptConfigClassModel, + vulnerableRequestForTemplateClassModel, + trafficMetricsAlertClassModel, + jiraintegrationClassModel, + setupClassModel, + cronTimersClassModel, + connectionInfoClassModel, + testLibraryClassModel, + methodConditionClassModel, + regexTestingEndpointsClassModel, + hostRegexTestingEndpointsClassModel, + allTestingEndpointsClassModel, + UsageMetricClassModel, + UsageMetricInfoClassModel, + UsageSyncClassModel, + OrganizationClassModel, + yamlNodeDetails, + multiExecTestResultClassModel, + workflowTestClassModel, + dependencyNodeClassModel, + paramInfoClassModel, + nodeClassModel, + connectionClassModel, + edgeClassModel, + replaceDetailClassModel, + modifyHostDetailClassModel, + fileUploadClassModel, + fileUploadLogClassModel, + codeAnalysisCollectionClassModel, + codeAnalysisApiLocationClassModel, + codeAnalysisApiInfoClassModel, + codeAnalysisApiInfoKeyClassModel, + riskScoreTestingEndpointsClassModel, + OrganizationFlagsClassModel, + sensitiveDataEndpointsClassModel, + unauthenticatedEndpointsClassModel, + allApisGroupClassModel, + eventsExampleClassModel, + RuntimeMetricsClassModel, + codeAnalysisRepoModel, + codeAnalysisApiModel, + historicalDataClassModel, + configSettingClassModel, + configSettingsConditionTypeClassModel) + .automatic(true) + .build()); - final CodecRegistry customEnumCodecs = CodecRegistries.fromCodecs( - new EnumCodec<>(Conditions.Operator.class), - new EnumCodec<>(SingleTypeInfo.SuperType.class), - new EnumCodec<>(Method.class), - new EnumCodec<>(RBAC.Role.class), - new EnumCodec<>(Credential.Type.class), - new EnumCodec<>(ApiToken.Utility.class), - new EnumCodec<>(ApiInfo.AuthType.class), - new EnumCodec<>(ApiInfo.ApiAccessType.class), - new EnumCodec<>(TestResult.TestError.class), - new EnumCodec<>(AuthParam.Location.class), - new EnumCodec<>(TestingEndpoints.Type.class), - new EnumCodec<>(TestingRun.State.class), - new EnumCodec<>(AccountSettings.SetupType.class), - new EnumCodec<>(WorkflowNodeDetails.Type.class), - new EnumCodec<>(SingleTypeInfo.Domain.class), - new EnumCodec<>(CustomWebhook.ActiveStatus.class), - new EnumCodec<>(TestResult.Confidence.class), - new EnumCodec<>(SingleTypeInfo.Position.class), - new EnumCodec<>(TestResult.Confidence.class), - new EnumCodec<>(GlobalEnums.TestRunIssueStatus.class), - new EnumCodec<>(GlobalEnums.TestErrorSource.class), - new EnumCodec<>(GlobalEnums.TestCategory.class), - new EnumCodec<>(GlobalEnums.IssueTags.class), - new EnumCodec<>(GlobalEnums.Severity.class), - new EnumCodec<>(TrafficMetrics.Name.class), - new EnumCodec<>(Loader.Type.class), - new EnumCodec<>(CustomWebhook.WebhookOptions.class), - new EnumCodec<>(GlobalEnums.YamlTemplateSource.class), - new EnumCodec<>(AktoGptConfigState.class), - new EnumCodec<>(CustomWebhook.WebhookOptions.class), - new EnumCodec<>(TestingEndpoints.Operator.class), - new EnumCodec<>(MetricTypes.class), - new EnumCodec<>(User.AktoUIMode.class), - new EnumCodec<>(TrafficMetricsAlert.FilterType.class), - new EnumCodec<>(KVPair.KVType.class), - new EnumCodec<>(ApiCollection.ENV_TYPE.class), - new EnumCodec<>(FileUpload.UploadType.class), - new EnumCodec<>(FileUpload.UploadStatus.class), - new EnumCodec<>(FileUploadLog.UploadLogStatus.class), - new EnumCodec<>(TestCollectionProperty.Id.class), - new EnumCodec<>(CustomAuthType.TypeOfToken.class), - new EnumCodec<>(TrafficAlerts.ALERT_TYPE.class), - new EnumCodec<>(ApiInfo.ApiType.class), - new EnumCodec<>(CodeAnalysisRepo.SourceCodeType.class) - ); + final CodecRegistry customEnumCodecs = + CodecRegistries.fromCodecs( + new EnumCodec<>(Conditions.Operator.class), + new EnumCodec<>(SingleTypeInfo.SuperType.class), + new EnumCodec<>(Method.class), + new EnumCodec<>(RBAC.Role.class), + new EnumCodec<>(Credential.Type.class), + new EnumCodec<>(ApiToken.Utility.class), + new EnumCodec<>(ApiInfo.AuthType.class), + new EnumCodec<>(ApiInfo.ApiAccessType.class), + new EnumCodec<>(TestResult.TestError.class), + new EnumCodec<>(AuthParam.Location.class), + new EnumCodec<>(TestingEndpoints.Type.class), + new EnumCodec<>(TestingRun.State.class), + new EnumCodec<>(AccountSettings.SetupType.class), + new EnumCodec<>(WorkflowNodeDetails.Type.class), + new EnumCodec<>(SingleTypeInfo.Domain.class), + new EnumCodec<>(CustomWebhook.ActiveStatus.class), + new EnumCodec<>(TestResult.Confidence.class), + new EnumCodec<>(SingleTypeInfo.Position.class), + new EnumCodec<>(TestResult.Confidence.class), + new EnumCodec<>(GlobalEnums.TestRunIssueStatus.class), + new EnumCodec<>(GlobalEnums.TestErrorSource.class), + new EnumCodec<>(GlobalEnums.TestCategory.class), + new EnumCodec<>(GlobalEnums.IssueTags.class), + new EnumCodec<>(GlobalEnums.Severity.class), + new EnumCodec<>(TrafficMetrics.Name.class), + new EnumCodec<>(Loader.Type.class), + new EnumCodec<>(CustomWebhook.WebhookOptions.class), + new EnumCodec<>(GlobalEnums.YamlTemplateSource.class), + new EnumCodec<>(AktoGptConfigState.class), + new EnumCodec<>(CustomWebhook.WebhookOptions.class), + new EnumCodec<>(TestingEndpoints.Operator.class), + new EnumCodec<>(MetricTypes.class), + new EnumCodec<>(User.AktoUIMode.class), + new EnumCodec<>(TrafficMetricsAlert.FilterType.class), + new EnumCodec<>(KVPair.KVType.class), + new EnumCodec<>(ApiCollection.ENV_TYPE.class), + new EnumCodec<>(FileUpload.UploadType.class), + new EnumCodec<>(FileUpload.UploadStatus.class), + new EnumCodec<>(FileUploadLog.UploadLogStatus.class), + new EnumCodec<>(TestCollectionProperty.Id.class), + new EnumCodec<>(CustomAuthType.TypeOfToken.class), + new EnumCodec<>(TrafficAlerts.ALERT_TYPE.class), + new EnumCodec<>(ApiInfo.ApiType.class), + new EnumCodec<>(CodeAnalysisRepo.SourceCodeType.class)); - return fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry, - customEnumCodecs); - } + return fromRegistries( + MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry, customEnumCodecs); + } - public static void init(ConnectionString connectionString, ReadPreference readPreference, WriteConcern writeConcern) { - DbMode.refreshDbType(connectionString.getConnectionString()); - logger.info("DB type: {}", DbMode.dbType); - DbMode.refreshSetupType(connectionString); - logger.info("DB setup type: {}", DbMode.setupType); + public static MongoClient createMongoClient( + ConnectionString connectionString, ReadPreference readPreference, WriteConcern writeConcern) { + DbMode.refreshDbType(connectionString.getConnectionString()); + logger.info("DB type: {}", DbMode.dbType); + DbMode.refreshSetupType(connectionString); + logger.info("DB setup type: {}", DbMode.setupType); - CodecRegistry codecRegistry = createCodecRegistry(); + CodecRegistry codecRegistry = createCodecRegistry(); - MongoClientSettings clientSettings = MongoClientSettings.builder() - .readPreference(readPreference) - .writeConcern(writeConcern) - .applyConnectionString(connectionString) - .codecRegistry(codecRegistry) - .build(); + MongoClientSettings clientSettings = + MongoClientSettings.builder() + .readPreference(readPreference) + .writeConcern(writeConcern) + .applyConnectionString(connectionString) + .codecRegistry(codecRegistry) + .build(); - clients[0] = MongoClients.create(clientSettings); - } - public static void init(ConnectionString connectionString) { - init(connectionString, ReadPreference.secondary(), WriteConcern.ACKNOWLEDGED); - } + return MongoClients.create(clientSettings); + } - public static void createIndices() { - try { - TestingRunResultDao.instance.convertToCappedCollection(); - } catch (Exception e) { - logger.error("Error while converting TestingRunResults to capped collection: " + e.getMessage()); - } + public static void init( + ConnectionString connectionString, ReadPreference readPreference, WriteConcern writeConcern) { + clients[0] = createMongoClient(connectionString, readPreference, writeConcern); + } - OrganizationsDao.createIndexIfAbsent(); - UsageMetricsDao.createIndexIfAbsent(); - SingleTypeInfoDao.instance.createIndicesIfAbsent(); - TrafficMetricsDao.instance.createIndicesIfAbsent(); - TestRolesDao.instance.createIndicesIfAbsent(); - UsersDao.instance.createIndicesIfAbsent(); - AccountsDao.instance.createIndexIfAbsent(); + public static void init(ConnectionString connectionString) { + init(connectionString, ReadPreference.secondary(), WriteConcern.ACKNOWLEDGED); + } - ApiInfoDao.instance.createIndicesIfAbsent(); - RuntimeLogsDao.instance.createIndicesIfAbsent(); - LogsDao.instance.createIndicesIfAbsent(); - DashboardLogsDao.instance.createIndicesIfAbsent(); - AnalyserLogsDao.instance.createIndicesIfAbsent(); - SampleDataDao.instance.createIndicesIfAbsent(); - LoadersDao.instance.createIndicesIfAbsent(); - TestingRunResultDao.instance.createIndicesIfAbsent(); - TestingRunResultSummariesDao.instance.createIndicesIfAbsent(); - TestingRunDao.instance.createIndicesIfAbsent(); - TestingRunIssuesDao.instance.createIndicesIfAbsent(); - ApiCollectionsDao.instance.createIndicesIfAbsent(); - ActivitiesDao.instance.createIndicesIfAbsent(); - DependencyNodeDao.instance.createIndicesIfAbsent(); - DependencyFlowNodesDao.instance.createIndicesIfAbsent(); - CodeAnalysisCollectionDao.instance.createIndicesIfAbsent(); - CodeAnalysisApiInfoDao.instance.createIndicesIfAbsent(); - RBACDao.instance.createIndicesIfAbsent(); - TrafficAlertsDao.instance.createIndicesIfAbsent(); - RuntimeMetricsDao.instance.createIndicesIfAbsent(); - ApiAuditLogsDao.instance.createIndicesIfAbsent(); + public static void createIndices() { + try { + TestingRunResultDao.instance.convertToCappedCollection(); + } catch (Exception e) { + logger.error( + "Error while converting TestingRunResults to capped collection: " + e.getMessage()); } + OrganizationsDao.createIndexIfAbsent(); + UsageMetricsDao.createIndexIfAbsent(); + SingleTypeInfoDao.instance.createIndicesIfAbsent(); + TrafficMetricsDao.instance.createIndicesIfAbsent(); + TestRolesDao.instance.createIndicesIfAbsent(); + UsersDao.instance.createIndicesIfAbsent(); + AccountsDao.instance.createIndexIfAbsent(); + + ApiInfoDao.instance.createIndicesIfAbsent(); + RuntimeLogsDao.instance.createIndicesIfAbsent(); + LogsDao.instance.createIndicesIfAbsent(); + DashboardLogsDao.instance.createIndicesIfAbsent(); + AnalyserLogsDao.instance.createIndicesIfAbsent(); + SampleDataDao.instance.createIndicesIfAbsent(); + LoadersDao.instance.createIndicesIfAbsent(); + TestingRunResultDao.instance.createIndicesIfAbsent(); + TestingRunResultSummariesDao.instance.createIndicesIfAbsent(); + TestingRunDao.instance.createIndicesIfAbsent(); + TestingRunIssuesDao.instance.createIndicesIfAbsent(); + ApiCollectionsDao.instance.createIndicesIfAbsent(); + ActivitiesDao.instance.createIndicesIfAbsent(); + DependencyNodeDao.instance.createIndicesIfAbsent(); + DependencyFlowNodesDao.instance.createIndicesIfAbsent(); + CodeAnalysisCollectionDao.instance.createIndicesIfAbsent(); + CodeAnalysisApiInfoDao.instance.createIndicesIfAbsent(); + RBACDao.instance.createIndicesIfAbsent(); + TrafficAlertsDao.instance.createIndicesIfAbsent(); + RuntimeMetricsDao.instance.createIndicesIfAbsent(); + ApiAuditLogsDao.instance.createIndicesIfAbsent(); + } } diff --git a/libs/dao/src/main/java/com/akto/dao/api_protection_parse_layer/AggregationLayerParser.java b/libs/dao/src/main/java/com/akto/dao/api_protection_parse_layer/AggregationLayerParser.java new file mode 100644 index 0000000000..90af26affe --- /dev/null +++ b/libs/dao/src/main/java/com/akto/dao/api_protection_parse_layer/AggregationLayerParser.java @@ -0,0 +1,37 @@ +package com.akto.dao.api_protection_parse_layer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.akto.dto.api_protection_parse_layer.AggregationRules; +import com.akto.dto.api_protection_parse_layer.Rule; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class AggregationLayerParser { + + ObjectMapper objectMapper = new ObjectMapper(); + + public AggregationLayerParser() { + } + + public AggregationRules parse(Map aggregationRules) throws Exception { + + List rules = new ArrayList<>(); + AggregationRules aggRules = new AggregationRules(rules); + + try { + for (Object aggObj: (List) aggregationRules.get("aggregation_rules")) { + Map aggObjMap = (Map) aggObj; + Rule rule = objectMapper.convertValue(aggObjMap.get("rule"), Rule.class); + rules.add(rule); + } + aggRules.setRule(rules); + } catch (Exception e) { + throw e; + } + + return aggRules; + } + +} diff --git a/libs/dao/src/main/java/com/akto/dao/monitoring/FilterYamlTemplateDao.java b/libs/dao/src/main/java/com/akto/dao/monitoring/FilterYamlTemplateDao.java index 8a898c387c..1e6ad20238 100644 --- a/libs/dao/src/main/java/com/akto/dao/monitoring/FilterYamlTemplateDao.java +++ b/libs/dao/src/main/java/com/akto/dao/monitoring/FilterYamlTemplateDao.java @@ -13,17 +13,23 @@ public class FilterYamlTemplateDao extends AccountsContextDao { public static final FilterYamlTemplateDao instance = new FilterYamlTemplateDao(); - public Map fetchFilterConfig(boolean includeYamlContent, boolean shouldParseExecutor) { + public Map fetchFilterConfig( + boolean includeYamlContent, boolean shouldParseExecutor) { List yamlTemplates = FilterYamlTemplateDao.instance.findAll(Filters.empty()); return fetchFilterConfig(includeYamlContent, yamlTemplates, shouldParseExecutor); } - public Map fetchFilterConfig(boolean includeYamlContent, List yamlTemplates, boolean shouldParseExecutor) { + public static Map fetchFilterConfig( + boolean includeYamlContent, + List yamlTemplates, + boolean shouldParseExecutor) { Map filterConfigMap = new HashMap<>(); for (YamlTemplate yamlTemplate : yamlTemplates) { try { if (yamlTemplate != null) { - FilterConfig filterConfig = FilterConfigYamlParser.parseTemplate(yamlTemplate.getContent(), shouldParseExecutor); + FilterConfig filterConfig = + FilterConfigYamlParser.parseTemplate( + yamlTemplate.getContent(), shouldParseExecutor); filterConfig.setAuthor(yamlTemplate.getAuthor()); filterConfig.setCreatedAt(yamlTemplate.getCreatedAt()); filterConfig.setUpdatedAt(yamlTemplate.getUpdatedAt()); diff --git a/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java b/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java index f6c85ebc52..952469ac4b 100644 --- a/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java +++ b/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java @@ -83,6 +83,24 @@ public void buildFromSampleMessage(String message) { this.headers = buildHeadersMap(json, "requestHeaders"); } + public void buildFromSampleMessageNew(HttpResponseParams responseParam) { + String rawUrl = responseParam.getRequestParams().getURL(); + String[] rawUrlArr = rawUrl.split("\\?"); + this.url = rawUrlArr[0]; + if (rawUrlArr.length > 1) { + this.queryParams = rawUrlArr[1]; + } + + this.type = responseParam.getRequestParams().type; + + this.method = responseParam.getRequestParams().getMethod(); + + String requestPayload = responseParam.getRequestParams().getPayload(); + this.body = requestPayload.trim(); + + this.headers = responseParam.getRequestParams().getHeaders(); + } + public String getJsonRequestBody() { return HttpRequestResponseUtils.rawToJsonString(this.body, this.headers); } diff --git a/libs/dao/src/main/java/com/akto/dto/OriginalHttpResponse.java b/libs/dao/src/main/java/com/akto/dto/OriginalHttpResponse.java index 1d011082a2..5a058ac5a9 100644 --- a/libs/dao/src/main/java/com/akto/dto/OriginalHttpResponse.java +++ b/libs/dao/src/main/java/com/akto/dto/OriginalHttpResponse.java @@ -1,6 +1,8 @@ package com.akto.dto; import com.akto.util.HttpRequestResponseUtils; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import com.google.gson.Gson; import org.apache.commons.lang3.math.NumberUtils; @@ -43,6 +45,13 @@ public void buildFromSampleMessage(String message) { this.statusCode = Integer.parseInt(obj.toString()); } + public void buildFromSampleMessageNew(HttpResponseParams responseParam) { + String responsePayload = responseParam.getPayload(); + this.body = responsePayload != null ? responsePayload.trim() : null; + this.headers = responseParam.getHeaders(); + this.statusCode = responseParam.getStatusCode(); + } + public void addHeaderFromLine(String line) { if (this.headers == null || this.headers.isEmpty()) { this.headers = new HashMap<>(); diff --git a/libs/dao/src/main/java/com/akto/dto/RawApi.java b/libs/dao/src/main/java/com/akto/dto/RawApi.java index bbc8b9488c..b76ecbd93b 100644 --- a/libs/dao/src/main/java/com/akto/dto/RawApi.java +++ b/libs/dao/src/main/java/com/akto/dto/RawApi.java @@ -7,6 +7,8 @@ import java.util.Map; import com.akto.dto.type.RequestTemplate; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import com.mongodb.BasicDBList; import com.fasterxml.jackson.databind.ObjectMapper; import com.mongodb.BasicDBObject; @@ -55,6 +57,16 @@ public static RawApi buildFromMessage(String message) { return new RawApi(request, response, message); } + public static RawApi buildFromMessageNew(HttpResponseParams responseParam) { + OriginalHttpRequest request = new OriginalHttpRequest(); + request.buildFromSampleMessageNew(responseParam); + + OriginalHttpResponse response = new OriginalHttpResponse(); + response.buildFromSampleMessageNew(responseParam); + + return new RawApi(request, response, ""); + } + public BasicDBObject fetchReqPayload() { OriginalHttpRequest req = this.getRequest(); String reqBody = req.getBody(); diff --git a/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/AggregationRules.java b/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/AggregationRules.java new file mode 100644 index 0000000000..18a8602009 --- /dev/null +++ b/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/AggregationRules.java @@ -0,0 +1,24 @@ +package com.akto.dto.api_protection_parse_layer; + +import java.util.List; + +public class AggregationRules { + + private List rule; + + public AggregationRules() { + } + + public AggregationRules(List rule) { + this.rule = rule; + } + + public List getRule() { + return rule; + } + + public void setRule(List rule) { + this.rule = rule; + } + +} diff --git a/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/Condition.java b/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/Condition.java new file mode 100644 index 0000000000..bcb7a906e4 --- /dev/null +++ b/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/Condition.java @@ -0,0 +1,31 @@ +package com.akto.dto.api_protection_parse_layer; + +public class Condition { + + private int matchCount; + private int windowThreshold; + // private String operation; + // private float value; + + public Condition() { + } + + public Condition(int matchCount, int windowThreshold) { + this.matchCount = matchCount; + this.windowThreshold = windowThreshold; + } + + public int getMatchCount() { + return matchCount; + } + public void setMatchCount(int matchCount) { + this.matchCount = matchCount; + } + public int getWindowThreshold() { + return windowThreshold; + } + public void setWindowThreshold(int windowThreshold) { + this.windowThreshold = windowThreshold; + } + // private List actions; +} diff --git a/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/Rule.java b/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/Rule.java new file mode 100644 index 0000000000..50fc2422a8 --- /dev/null +++ b/libs/dao/src/main/java/com/akto/dto/api_protection_parse_layer/Rule.java @@ -0,0 +1,31 @@ +package com.akto.dto.api_protection_parse_layer; + +public class Rule { + + String name; + Condition condition; + + public Rule() { + } + + public Rule(String name, Condition condition) { + this.name = name; + this.condition = condition; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public Condition getCondition() { + return condition; + } + public void setCondition(Condition condition) { + this.condition = condition; + } + + + +} diff --git a/libs/dao/src/main/java/com/akto/dto/bulk_updates/BulkUpdates.java b/libs/dao/src/main/java/com/akto/dto/bulk_updates/BulkUpdates.java index 256c9fbd04..06c4230190 100644 --- a/libs/dao/src/main/java/com/akto/dto/bulk_updates/BulkUpdates.java +++ b/libs/dao/src/main/java/com/akto/dto/bulk_updates/BulkUpdates.java @@ -4,34 +4,31 @@ import java.util.List; import java.util.Map; - public class BulkUpdates { private Map filters; - private ArrayList updates; + private List updates; - public BulkUpdates() { - } + public BulkUpdates() {} - public BulkUpdates(Map filters, ArrayList updates) { + public BulkUpdates(Map filters, List updates) { this.filters = filters; this.updates = updates; } - public Map getFilters() { + public Map getFilters() { return this.filters; } - public void setFilters(Map filters) { + public void setFilters(Map filters) { this.filters = filters; } - public ArrayList getUpdates() { + public List getUpdates() { return this.updates; } public void setUpdates(ArrayList updates) { this.updates = updates; } - -} \ No newline at end of file +} diff --git a/libs/dao/src/main/java/com/akto/dto/traffic/SuspectSampleData.java b/libs/dao/src/main/java/com/akto/dto/traffic/SuspectSampleData.java index accfc5b398..c8d4253039 100644 --- a/libs/dao/src/main/java/com/akto/dto/traffic/SuspectSampleData.java +++ b/libs/dao/src/main/java/com/akto/dto/traffic/SuspectSampleData.java @@ -23,7 +23,7 @@ public class SuspectSampleData { * we retrospectively match all sus-samples' url * with the urls present in the db to match them. */ - public final static String MATCHING_URL = "matchingUrl"; + public static final String MATCHING_URL = "matchingUrl"; String matchingUrl; /* @@ -31,11 +31,16 @@ public class SuspectSampleData { */ String filterId; - public SuspectSampleData() { - } + public SuspectSampleData() {} - public SuspectSampleData(List sourceIPs, int apiCollectionId, String url, Method method, String sample, - int discovered, String filterId) { + public SuspectSampleData( + List sourceIPs, + int apiCollectionId, + String url, + Method method, + String sample, + int discovered, + String filterId) { this.sourceIPs = sourceIPs; this.apiCollectionId = apiCollectionId; this.url = url; @@ -123,16 +128,30 @@ public void setFilterId(String filterId) { @Override public String toString() { - return "{" + - " \"apiCollectionId\":\"" + getApiCollectionId() + "\"" + - ", \"url\":\"" + getUrl() + "\"" + - ", \"method\":\"" + getMethod() + "\"" + - ", \"matchingUrl\":\"" + (getMatchingUrl() != null ? getMatchingUrl() : "/") + "\"" + - ", \"discovered\":\"" + getDiscovered() + "\"" + - ", \"filter\":\"" + getFilterId() + "\"" + - ", \"IPs\":\"" + (getSourceIPs() !=null ? getSourceIPs() : "[]" )+ "\"" + - ", \"sample\":" + getSample() + - "}"; - } - -} \ No newline at end of file + return "{" + + " \"apiCollectionId\":\"" + + getApiCollectionId() + + "\"" + + ", \"url\":\"" + + getUrl() + + "\"" + + ", \"method\":\"" + + getMethod() + + "\"" + + ", \"matchingUrl\":\"" + + (getMatchingUrl() != null ? getMatchingUrl() : "/") + + "\"" + + ", \"discovered\":\"" + + getDiscovered() + + "\"" + + ", \"filter\":\"" + + getFilterId() + + "\"" + + ", \"IPs\":\"" + + (getSourceIPs() != null ? getSourceIPs() : "[]") + + "\"" + + ", \"sample\":" + + getSample() + + "}"; + } +} diff --git a/libs/protobuf/.gitignore b/libs/protobuf/.gitignore index 9b21cfdc49..7589473dd1 100644 --- a/libs/protobuf/.gitignore +++ b/libs/protobuf/.gitignore @@ -1,2 +1 @@ src/main/java/com/akto/proto/generated - diff --git a/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParam.java b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParam.java new file mode 100644 index 0000000000..92b9d62ac1 --- /dev/null +++ b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParam.java @@ -0,0 +1,2846 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: threat_detection/message/http_response_param/v1/http_response_param.proto +// Protobuf Java Version: 4.28.3 + +package com.akto.proto.http_response_param.v1; + +/** + * Protobuf type {@code threat_detection.message.http_response_param.v1.HttpResponseParam} + */ +public final class HttpResponseParam extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:threat_detection.message.http_response_param.v1.HttpResponseParam) + HttpResponseParamOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 28, + /* patch= */ 3, + /* suffix= */ "", + HttpResponseParam.class.getName()); + } + // Use HttpResponseParam.newBuilder() to construct. + private HttpResponseParam(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private HttpResponseParam() { + method_ = ""; + path_ = ""; + type_ = ""; + requestPayload_ = ""; + status_ = ""; + responsePayload_ = ""; + aktoAccountId_ = ""; + ip_ = ""; + destIp_ = ""; + direction_ = ""; + source_ = ""; + aktoVxlanId_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 4: + return internalGetRequestHeaders(); + case 9: + return internalGetResponseHeaders(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.akto.proto.http_response_param.v1.HttpResponseParam.class, com.akto.proto.http_response_param.v1.HttpResponseParam.Builder.class); + } + + public static final int METHOD_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object method_ = ""; + /** + * string method = 1 [json_name = "method"]; + * @return The method. + */ + @java.lang.Override + public java.lang.String getMethod() { + java.lang.Object ref = method_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + method_ = s; + return s; + } + } + /** + * string method = 1 [json_name = "method"]; + * @return The bytes for method. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getMethodBytes() { + java.lang.Object ref = method_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + method_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PATH_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object path_ = ""; + /** + * string path = 2 [json_name = "path"]; + * @return The path. + */ + @java.lang.Override + public java.lang.String getPath() { + java.lang.Object ref = path_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + path_ = s; + return s; + } + } + /** + * string path = 2 [json_name = "path"]; + * @return The bytes for path. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getPathBytes() { + java.lang.Object ref = path_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + path_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TYPE_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object type_ = ""; + /** + * string type = 3 [json_name = "type"]; + * @return The type. + */ + @java.lang.Override + public java.lang.String getType() { + java.lang.Object ref = type_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + type_ = s; + return s; + } + } + /** + * string type = 3 [json_name = "type"]; + * @return The bytes for type. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTypeBytes() { + java.lang.Object ref = type_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + type_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REQUEST_HEADERS_FIELD_NUMBER = 4; + private static final class RequestHeadersDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, com.akto.proto.http_response_param.v1.StringList> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_RequestHeadersEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.MESSAGE, + com.akto.proto.http_response_param.v1.StringList.getDefaultInstance()); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, com.akto.proto.http_response_param.v1.StringList> requestHeaders_; + private com.google.protobuf.MapField + internalGetRequestHeaders() { + if (requestHeaders_ == null) { + return com.google.protobuf.MapField.emptyMapField( + RequestHeadersDefaultEntryHolder.defaultEntry); + } + return requestHeaders_; + } + public int getRequestHeadersCount() { + return internalGetRequestHeaders().getMap().size(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public boolean containsRequestHeaders( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetRequestHeaders().getMap().containsKey(key); + } + /** + * Use {@link #getRequestHeadersMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getRequestHeaders() { + return getRequestHeadersMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public java.util.Map getRequestHeadersMap() { + return internalGetRequestHeaders().getMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public /* nullable */ +com.akto.proto.http_response_param.v1.StringList getRequestHeadersOrDefault( + java.lang.String key, + /* nullable */ +com.akto.proto.http_response_param.v1.StringList defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetRequestHeaders().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList getRequestHeadersOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetRequestHeaders().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + public static final int REQUEST_PAYLOAD_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private volatile java.lang.Object requestPayload_ = ""; + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @return The requestPayload. + */ + @java.lang.Override + public java.lang.String getRequestPayload() { + java.lang.Object ref = requestPayload_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + requestPayload_ = s; + return s; + } + } + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @return The bytes for requestPayload. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRequestPayloadBytes() { + java.lang.Object ref = requestPayload_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + requestPayload_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int API_COLLECTION_ID_FIELD_NUMBER = 6; + private int apiCollectionId_ = 0; + /** + * int32 api_collection_id = 6 [json_name = "apiCollectionId"]; + * @return The apiCollectionId. + */ + @java.lang.Override + public int getApiCollectionId() { + return apiCollectionId_; + } + + public static final int STATUS_CODE_FIELD_NUMBER = 7; + private int statusCode_ = 0; + /** + * int32 status_code = 7 [json_name = "statusCode"]; + * @return The statusCode. + */ + @java.lang.Override + public int getStatusCode() { + return statusCode_; + } + + public static final int STATUS_FIELD_NUMBER = 8; + @SuppressWarnings("serial") + private volatile java.lang.Object status_ = ""; + /** + * string status = 8 [json_name = "status"]; + * @return The status. + */ + @java.lang.Override + public java.lang.String getStatus() { + java.lang.Object ref = status_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + status_ = s; + return s; + } + } + /** + * string status = 8 [json_name = "status"]; + * @return The bytes for status. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getStatusBytes() { + java.lang.Object ref = status_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + status_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int RESPONSE_HEADERS_FIELD_NUMBER = 9; + private static final class ResponseHeadersDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, com.akto.proto.http_response_param.v1.StringList> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_ResponseHeadersEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.MESSAGE, + com.akto.proto.http_response_param.v1.StringList.getDefaultInstance()); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, com.akto.proto.http_response_param.v1.StringList> responseHeaders_; + private com.google.protobuf.MapField + internalGetResponseHeaders() { + if (responseHeaders_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ResponseHeadersDefaultEntryHolder.defaultEntry); + } + return responseHeaders_; + } + public int getResponseHeadersCount() { + return internalGetResponseHeaders().getMap().size(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public boolean containsResponseHeaders( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetResponseHeaders().getMap().containsKey(key); + } + /** + * Use {@link #getResponseHeadersMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getResponseHeaders() { + return getResponseHeadersMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public java.util.Map getResponseHeadersMap() { + return internalGetResponseHeaders().getMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public /* nullable */ +com.akto.proto.http_response_param.v1.StringList getResponseHeadersOrDefault( + java.lang.String key, + /* nullable */ +com.akto.proto.http_response_param.v1.StringList defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetResponseHeaders().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList getResponseHeadersOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetResponseHeaders().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + public static final int RESPONSE_PAYLOAD_FIELD_NUMBER = 10; + @SuppressWarnings("serial") + private volatile java.lang.Object responsePayload_ = ""; + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @return The responsePayload. + */ + @java.lang.Override + public java.lang.String getResponsePayload() { + java.lang.Object ref = responsePayload_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + responsePayload_ = s; + return s; + } + } + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @return The bytes for responsePayload. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getResponsePayloadBytes() { + java.lang.Object ref = responsePayload_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + responsePayload_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TIME_FIELD_NUMBER = 11; + private int time_ = 0; + /** + * int32 time = 11 [json_name = "time"]; + * @return The time. + */ + @java.lang.Override + public int getTime() { + return time_; + } + + public static final int AKTO_ACCOUNT_ID_FIELD_NUMBER = 12; + @SuppressWarnings("serial") + private volatile java.lang.Object aktoAccountId_ = ""; + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @return The aktoAccountId. + */ + @java.lang.Override + public java.lang.String getAktoAccountId() { + java.lang.Object ref = aktoAccountId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + aktoAccountId_ = s; + return s; + } + } + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @return The bytes for aktoAccountId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getAktoAccountIdBytes() { + java.lang.Object ref = aktoAccountId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + aktoAccountId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int IP_FIELD_NUMBER = 13; + @SuppressWarnings("serial") + private volatile java.lang.Object ip_ = ""; + /** + * string ip = 13 [json_name = "ip"]; + * @return The ip. + */ + @java.lang.Override + public java.lang.String getIp() { + java.lang.Object ref = ip_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + ip_ = s; + return s; + } + } + /** + * string ip = 13 [json_name = "ip"]; + * @return The bytes for ip. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIpBytes() { + java.lang.Object ref = ip_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + ip_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DEST_IP_FIELD_NUMBER = 14; + @SuppressWarnings("serial") + private volatile java.lang.Object destIp_ = ""; + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @return The destIp. + */ + @java.lang.Override + public java.lang.String getDestIp() { + java.lang.Object ref = destIp_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + destIp_ = s; + return s; + } + } + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @return The bytes for destIp. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDestIpBytes() { + java.lang.Object ref = destIp_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + destIp_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DIRECTION_FIELD_NUMBER = 15; + @SuppressWarnings("serial") + private volatile java.lang.Object direction_ = ""; + /** + * string direction = 15 [json_name = "direction"]; + * @return The direction. + */ + @java.lang.Override + public java.lang.String getDirection() { + java.lang.Object ref = direction_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + direction_ = s; + return s; + } + } + /** + * string direction = 15 [json_name = "direction"]; + * @return The bytes for direction. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDirectionBytes() { + java.lang.Object ref = direction_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + direction_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int IS_PENDING_FIELD_NUMBER = 16; + private boolean isPending_ = false; + /** + * bool is_pending = 16 [json_name = "isPending"]; + * @return The isPending. + */ + @java.lang.Override + public boolean getIsPending() { + return isPending_; + } + + public static final int SOURCE_FIELD_NUMBER = 17; + @SuppressWarnings("serial") + private volatile java.lang.Object source_ = ""; + /** + * string source = 17 [json_name = "source"]; + * @return The source. + */ + @java.lang.Override + public java.lang.String getSource() { + java.lang.Object ref = source_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + source_ = s; + return s; + } + } + /** + * string source = 17 [json_name = "source"]; + * @return The bytes for source. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getSourceBytes() { + java.lang.Object ref = source_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + source_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int AKTO_VXLAN_ID_FIELD_NUMBER = 18; + @SuppressWarnings("serial") + private volatile java.lang.Object aktoVxlanId_ = ""; + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @return The aktoVxlanId. + */ + @java.lang.Override + public java.lang.String getAktoVxlanId() { + java.lang.Object ref = aktoVxlanId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + aktoVxlanId_ = s; + return s; + } + } + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @return The bytes for aktoVxlanId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getAktoVxlanIdBytes() { + java.lang.Object ref = aktoVxlanId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + aktoVxlanId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(method_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, method_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(path_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, path_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(type_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, type_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetRequestHeaders(), + RequestHeadersDefaultEntryHolder.defaultEntry, + 4); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(requestPayload_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 5, requestPayload_); + } + if (apiCollectionId_ != 0) { + output.writeInt32(6, apiCollectionId_); + } + if (statusCode_ != 0) { + output.writeInt32(7, statusCode_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(status_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 8, status_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetResponseHeaders(), + ResponseHeadersDefaultEntryHolder.defaultEntry, + 9); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(responsePayload_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 10, responsePayload_); + } + if (time_ != 0) { + output.writeInt32(11, time_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(aktoAccountId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 12, aktoAccountId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(ip_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 13, ip_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(destIp_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 14, destIp_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(direction_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 15, direction_); + } + if (isPending_ != false) { + output.writeBool(16, isPending_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(source_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 17, source_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(aktoVxlanId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 18, aktoVxlanId_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(method_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, method_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(path_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, path_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(type_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, type_); + } + for (java.util.Map.Entry entry + : internalGetRequestHeaders().getMap().entrySet()) { + com.google.protobuf.MapEntry + requestHeaders__ = RequestHeadersDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, requestHeaders__); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(requestPayload_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(5, requestPayload_); + } + if (apiCollectionId_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(6, apiCollectionId_); + } + if (statusCode_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(7, statusCode_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(status_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(8, status_); + } + for (java.util.Map.Entry entry + : internalGetResponseHeaders().getMap().entrySet()) { + com.google.protobuf.MapEntry + responseHeaders__ = ResponseHeadersDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, responseHeaders__); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(responsePayload_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(10, responsePayload_); + } + if (time_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(11, time_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(aktoAccountId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(12, aktoAccountId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(ip_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(13, ip_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(destIp_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(14, destIp_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(direction_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(15, direction_); + } + if (isPending_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(16, isPending_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(source_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(17, source_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(aktoVxlanId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(18, aktoVxlanId_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.akto.proto.http_response_param.v1.HttpResponseParam)) { + return super.equals(obj); + } + com.akto.proto.http_response_param.v1.HttpResponseParam other = (com.akto.proto.http_response_param.v1.HttpResponseParam) obj; + + if (!getMethod() + .equals(other.getMethod())) return false; + if (!getPath() + .equals(other.getPath())) return false; + if (!getType() + .equals(other.getType())) return false; + if (!internalGetRequestHeaders().equals( + other.internalGetRequestHeaders())) return false; + if (!getRequestPayload() + .equals(other.getRequestPayload())) return false; + if (getApiCollectionId() + != other.getApiCollectionId()) return false; + if (getStatusCode() + != other.getStatusCode()) return false; + if (!getStatus() + .equals(other.getStatus())) return false; + if (!internalGetResponseHeaders().equals( + other.internalGetResponseHeaders())) return false; + if (!getResponsePayload() + .equals(other.getResponsePayload())) return false; + if (getTime() + != other.getTime()) return false; + if (!getAktoAccountId() + .equals(other.getAktoAccountId())) return false; + if (!getIp() + .equals(other.getIp())) return false; + if (!getDestIp() + .equals(other.getDestIp())) return false; + if (!getDirection() + .equals(other.getDirection())) return false; + if (getIsPending() + != other.getIsPending()) return false; + if (!getSource() + .equals(other.getSource())) return false; + if (!getAktoVxlanId() + .equals(other.getAktoVxlanId())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + METHOD_FIELD_NUMBER; + hash = (53 * hash) + getMethod().hashCode(); + hash = (37 * hash) + PATH_FIELD_NUMBER; + hash = (53 * hash) + getPath().hashCode(); + hash = (37 * hash) + TYPE_FIELD_NUMBER; + hash = (53 * hash) + getType().hashCode(); + if (!internalGetRequestHeaders().getMap().isEmpty()) { + hash = (37 * hash) + REQUEST_HEADERS_FIELD_NUMBER; + hash = (53 * hash) + internalGetRequestHeaders().hashCode(); + } + hash = (37 * hash) + REQUEST_PAYLOAD_FIELD_NUMBER; + hash = (53 * hash) + getRequestPayload().hashCode(); + hash = (37 * hash) + API_COLLECTION_ID_FIELD_NUMBER; + hash = (53 * hash) + getApiCollectionId(); + hash = (37 * hash) + STATUS_CODE_FIELD_NUMBER; + hash = (53 * hash) + getStatusCode(); + hash = (37 * hash) + STATUS_FIELD_NUMBER; + hash = (53 * hash) + getStatus().hashCode(); + if (!internalGetResponseHeaders().getMap().isEmpty()) { + hash = (37 * hash) + RESPONSE_HEADERS_FIELD_NUMBER; + hash = (53 * hash) + internalGetResponseHeaders().hashCode(); + } + hash = (37 * hash) + RESPONSE_PAYLOAD_FIELD_NUMBER; + hash = (53 * hash) + getResponsePayload().hashCode(); + hash = (37 * hash) + TIME_FIELD_NUMBER; + hash = (53 * hash) + getTime(); + hash = (37 * hash) + AKTO_ACCOUNT_ID_FIELD_NUMBER; + hash = (53 * hash) + getAktoAccountId().hashCode(); + hash = (37 * hash) + IP_FIELD_NUMBER; + hash = (53 * hash) + getIp().hashCode(); + hash = (37 * hash) + DEST_IP_FIELD_NUMBER; + hash = (53 * hash) + getDestIp().hashCode(); + hash = (37 * hash) + DIRECTION_FIELD_NUMBER; + hash = (53 * hash) + getDirection().hashCode(); + hash = (37 * hash) + IS_PENDING_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getIsPending()); + hash = (37 * hash) + SOURCE_FIELD_NUMBER; + hash = (53 * hash) + getSource().hashCode(); + hash = (37 * hash) + AKTO_VXLAN_ID_FIELD_NUMBER; + hash = (53 * hash) + getAktoVxlanId().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static com.akto.proto.http_response_param.v1.HttpResponseParam parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.akto.proto.http_response_param.v1.HttpResponseParam prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code threat_detection.message.http_response_param.v1.HttpResponseParam} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:threat_detection.message.http_response_param.v1.HttpResponseParam) + com.akto.proto.http_response_param.v1.HttpResponseParamOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 4: + return internalGetRequestHeaders(); + case 9: + return internalGetResponseHeaders(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 4: + return internalGetMutableRequestHeaders(); + case 9: + return internalGetMutableResponseHeaders(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.akto.proto.http_response_param.v1.HttpResponseParam.class, com.akto.proto.http_response_param.v1.HttpResponseParam.Builder.class); + } + + // Construct using com.akto.proto.generated.threat_detection.message.http_response_param.v1.HttpResponseParam.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + method_ = ""; + path_ = ""; + type_ = ""; + internalGetMutableRequestHeaders().clear(); + requestPayload_ = ""; + apiCollectionId_ = 0; + statusCode_ = 0; + status_ = ""; + internalGetMutableResponseHeaders().clear(); + responsePayload_ = ""; + time_ = 0; + aktoAccountId_ = ""; + ip_ = ""; + destIp_ = ""; + direction_ = ""; + isPending_ = false; + source_ = ""; + aktoVxlanId_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor; + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.HttpResponseParam getDefaultInstanceForType() { + return com.akto.proto.http_response_param.v1.HttpResponseParam.getDefaultInstance(); + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.HttpResponseParam build() { + com.akto.proto.http_response_param.v1.HttpResponseParam result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.HttpResponseParam buildPartial() { + com.akto.proto.http_response_param.v1.HttpResponseParam result = new com.akto.proto.http_response_param.v1.HttpResponseParam(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(com.akto.proto.http_response_param.v1.HttpResponseParam result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.method_ = method_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.path_ = path_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.type_ = type_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.requestHeaders_ = internalGetRequestHeaders().build(RequestHeadersDefaultEntryHolder.defaultEntry); + } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.requestPayload_ = requestPayload_; + } + if (((from_bitField0_ & 0x00000020) != 0)) { + result.apiCollectionId_ = apiCollectionId_; + } + if (((from_bitField0_ & 0x00000040) != 0)) { + result.statusCode_ = statusCode_; + } + if (((from_bitField0_ & 0x00000080) != 0)) { + result.status_ = status_; + } + if (((from_bitField0_ & 0x00000100) != 0)) { + result.responseHeaders_ = internalGetResponseHeaders().build(ResponseHeadersDefaultEntryHolder.defaultEntry); + } + if (((from_bitField0_ & 0x00000200) != 0)) { + result.responsePayload_ = responsePayload_; + } + if (((from_bitField0_ & 0x00000400) != 0)) { + result.time_ = time_; + } + if (((from_bitField0_ & 0x00000800) != 0)) { + result.aktoAccountId_ = aktoAccountId_; + } + if (((from_bitField0_ & 0x00001000) != 0)) { + result.ip_ = ip_; + } + if (((from_bitField0_ & 0x00002000) != 0)) { + result.destIp_ = destIp_; + } + if (((from_bitField0_ & 0x00004000) != 0)) { + result.direction_ = direction_; + } + if (((from_bitField0_ & 0x00008000) != 0)) { + result.isPending_ = isPending_; + } + if (((from_bitField0_ & 0x00010000) != 0)) { + result.source_ = source_; + } + if (((from_bitField0_ & 0x00020000) != 0)) { + result.aktoVxlanId_ = aktoVxlanId_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.akto.proto.http_response_param.v1.HttpResponseParam) { + return mergeFrom((com.akto.proto.http_response_param.v1.HttpResponseParam)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.akto.proto.http_response_param.v1.HttpResponseParam other) { + if (other == com.akto.proto.http_response_param.v1.HttpResponseParam.getDefaultInstance()) return this; + if (!other.getMethod().isEmpty()) { + method_ = other.method_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getPath().isEmpty()) { + path_ = other.path_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getType().isEmpty()) { + type_ = other.type_; + bitField0_ |= 0x00000004; + onChanged(); + } + internalGetMutableRequestHeaders().mergeFrom( + other.internalGetRequestHeaders()); + bitField0_ |= 0x00000008; + if (!other.getRequestPayload().isEmpty()) { + requestPayload_ = other.requestPayload_; + bitField0_ |= 0x00000010; + onChanged(); + } + if (other.getApiCollectionId() != 0) { + setApiCollectionId(other.getApiCollectionId()); + } + if (other.getStatusCode() != 0) { + setStatusCode(other.getStatusCode()); + } + if (!other.getStatus().isEmpty()) { + status_ = other.status_; + bitField0_ |= 0x00000080; + onChanged(); + } + internalGetMutableResponseHeaders().mergeFrom( + other.internalGetResponseHeaders()); + bitField0_ |= 0x00000100; + if (!other.getResponsePayload().isEmpty()) { + responsePayload_ = other.responsePayload_; + bitField0_ |= 0x00000200; + onChanged(); + } + if (other.getTime() != 0) { + setTime(other.getTime()); + } + if (!other.getAktoAccountId().isEmpty()) { + aktoAccountId_ = other.aktoAccountId_; + bitField0_ |= 0x00000800; + onChanged(); + } + if (!other.getIp().isEmpty()) { + ip_ = other.ip_; + bitField0_ |= 0x00001000; + onChanged(); + } + if (!other.getDestIp().isEmpty()) { + destIp_ = other.destIp_; + bitField0_ |= 0x00002000; + onChanged(); + } + if (!other.getDirection().isEmpty()) { + direction_ = other.direction_; + bitField0_ |= 0x00004000; + onChanged(); + } + if (other.getIsPending() != false) { + setIsPending(other.getIsPending()); + } + if (!other.getSource().isEmpty()) { + source_ = other.source_; + bitField0_ |= 0x00010000; + onChanged(); + } + if (!other.getAktoVxlanId().isEmpty()) { + aktoVxlanId_ = other.aktoVxlanId_; + bitField0_ |= 0x00020000; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + method_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + path_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + type_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { + com.google.protobuf.MapEntry + requestHeaders__ = input.readMessage( + RequestHeadersDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableRequestHeaders().ensureBuilderMap().put( + requestHeaders__.getKey(), requestHeaders__.getValue()); + bitField0_ |= 0x00000008; + break; + } // case 34 + case 42: { + requestPayload_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000010; + break; + } // case 42 + case 48: { + apiCollectionId_ = input.readInt32(); + bitField0_ |= 0x00000020; + break; + } // case 48 + case 56: { + statusCode_ = input.readInt32(); + bitField0_ |= 0x00000040; + break; + } // case 56 + case 66: { + status_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000080; + break; + } // case 66 + case 74: { + com.google.protobuf.MapEntry + responseHeaders__ = input.readMessage( + ResponseHeadersDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableResponseHeaders().ensureBuilderMap().put( + responseHeaders__.getKey(), responseHeaders__.getValue()); + bitField0_ |= 0x00000100; + break; + } // case 74 + case 82: { + responsePayload_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000200; + break; + } // case 82 + case 88: { + time_ = input.readInt32(); + bitField0_ |= 0x00000400; + break; + } // case 88 + case 98: { + aktoAccountId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000800; + break; + } // case 98 + case 106: { + ip_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00001000; + break; + } // case 106 + case 114: { + destIp_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00002000; + break; + } // case 114 + case 122: { + direction_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00004000; + break; + } // case 122 + case 128: { + isPending_ = input.readBool(); + bitField0_ |= 0x00008000; + break; + } // case 128 + case 138: { + source_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00010000; + break; + } // case 138 + case 146: { + aktoVxlanId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00020000; + break; + } // case 146 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object method_ = ""; + /** + * string method = 1 [json_name = "method"]; + * @return The method. + */ + public java.lang.String getMethod() { + java.lang.Object ref = method_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + method_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string method = 1 [json_name = "method"]; + * @return The bytes for method. + */ + public com.google.protobuf.ByteString + getMethodBytes() { + java.lang.Object ref = method_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + method_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string method = 1 [json_name = "method"]; + * @param value The method to set. + * @return This builder for chaining. + */ + public Builder setMethod( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + method_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * string method = 1 [json_name = "method"]; + * @return This builder for chaining. + */ + public Builder clearMethod() { + method_ = getDefaultInstance().getMethod(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + * string method = 1 [json_name = "method"]; + * @param value The bytes for method to set. + * @return This builder for chaining. + */ + public Builder setMethodBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + method_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object path_ = ""; + /** + * string path = 2 [json_name = "path"]; + * @return The path. + */ + public java.lang.String getPath() { + java.lang.Object ref = path_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + path_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string path = 2 [json_name = "path"]; + * @return The bytes for path. + */ + public com.google.protobuf.ByteString + getPathBytes() { + java.lang.Object ref = path_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + path_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string path = 2 [json_name = "path"]; + * @param value The path to set. + * @return This builder for chaining. + */ + public Builder setPath( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + path_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * string path = 2 [json_name = "path"]; + * @return This builder for chaining. + */ + public Builder clearPath() { + path_ = getDefaultInstance().getPath(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * string path = 2 [json_name = "path"]; + * @param value The bytes for path to set. + * @return This builder for chaining. + */ + public Builder setPathBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + path_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object type_ = ""; + /** + * string type = 3 [json_name = "type"]; + * @return The type. + */ + public java.lang.String getType() { + java.lang.Object ref = type_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + type_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string type = 3 [json_name = "type"]; + * @return The bytes for type. + */ + public com.google.protobuf.ByteString + getTypeBytes() { + java.lang.Object ref = type_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + type_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string type = 3 [json_name = "type"]; + * @param value The type to set. + * @return This builder for chaining. + */ + public Builder setType( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + type_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * string type = 3 [json_name = "type"]; + * @return This builder for chaining. + */ + public Builder clearType() { + type_ = getDefaultInstance().getType(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + * string type = 3 [json_name = "type"]; + * @param value The bytes for type to set. + * @return This builder for chaining. + */ + public Builder setTypeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + type_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private static final class RequestHeadersConverter implements com.google.protobuf.MapFieldBuilder.Converter { + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList build(com.akto.proto.http_response_param.v1.StringListOrBuilder val) { + if (val instanceof com.akto.proto.http_response_param.v1.StringList) { return (com.akto.proto.http_response_param.v1.StringList) val; } + return ((com.akto.proto.http_response_param.v1.StringList.Builder) val).build(); + } + + @java.lang.Override + public com.google.protobuf.MapEntry defaultEntry() { + return RequestHeadersDefaultEntryHolder.defaultEntry; + } + }; + private static final RequestHeadersConverter requestHeadersConverter = new RequestHeadersConverter(); + + private com.google.protobuf.MapFieldBuilder< + java.lang.String, com.akto.proto.http_response_param.v1.StringListOrBuilder, com.akto.proto.http_response_param.v1.StringList, com.akto.proto.http_response_param.v1.StringList.Builder> requestHeaders_; + private com.google.protobuf.MapFieldBuilder + internalGetRequestHeaders() { + if (requestHeaders_ == null) { + return new com.google.protobuf.MapFieldBuilder<>(requestHeadersConverter); + } + return requestHeaders_; + } + private com.google.protobuf.MapFieldBuilder + internalGetMutableRequestHeaders() { + if (requestHeaders_ == null) { + requestHeaders_ = new com.google.protobuf.MapFieldBuilder<>(requestHeadersConverter); + } + bitField0_ |= 0x00000008; + onChanged(); + return requestHeaders_; + } + public int getRequestHeadersCount() { + return internalGetRequestHeaders().ensureBuilderMap().size(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public boolean containsRequestHeaders( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetRequestHeaders().ensureBuilderMap().containsKey(key); + } + /** + * Use {@link #getRequestHeadersMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getRequestHeaders() { + return getRequestHeadersMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public java.util.Map getRequestHeadersMap() { + return internalGetRequestHeaders().getImmutableMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public /* nullable */ +com.akto.proto.http_response_param.v1.StringList getRequestHeadersOrDefault( + java.lang.String key, + /* nullable */ +com.akto.proto.http_response_param.v1.StringList defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableRequestHeaders().ensureBuilderMap(); + return map.containsKey(key) ? requestHeadersConverter.build(map.get(key)) : defaultValue; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList getRequestHeadersOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableRequestHeaders().ensureBuilderMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return requestHeadersConverter.build(map.get(key)); + } + public Builder clearRequestHeaders() { + bitField0_ = (bitField0_ & ~0x00000008); + internalGetMutableRequestHeaders().clear(); + return this; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + public Builder removeRequestHeaders( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableRequestHeaders().ensureBuilderMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableRequestHeaders() { + bitField0_ |= 0x00000008; + return internalGetMutableRequestHeaders().ensureMessageMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + public Builder putRequestHeaders( + java.lang.String key, + com.akto.proto.http_response_param.v1.StringList value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableRequestHeaders().ensureBuilderMap() + .put(key, value); + bitField0_ |= 0x00000008; + return this; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + public Builder putAllRequestHeaders( + java.util.Map values) { + for (java.util.Map.Entry e : values.entrySet()) { + if (e.getKey() == null || e.getValue() == null) { + throw new NullPointerException(); + } + } + internalGetMutableRequestHeaders().ensureBuilderMap() + .putAll(values); + bitField0_ |= 0x00000008; + return this; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + public com.akto.proto.http_response_param.v1.StringList.Builder putRequestHeadersBuilderIfAbsent( + java.lang.String key) { + java.util.Map builderMap = internalGetMutableRequestHeaders().ensureBuilderMap(); + com.akto.proto.http_response_param.v1.StringListOrBuilder entry = builderMap.get(key); + if (entry == null) { + entry = com.akto.proto.http_response_param.v1.StringList.newBuilder(); + builderMap.put(key, entry); + } + if (entry instanceof com.akto.proto.http_response_param.v1.StringList) { + entry = ((com.akto.proto.http_response_param.v1.StringList) entry).toBuilder(); + builderMap.put(key, entry); + } + return (com.akto.proto.http_response_param.v1.StringList.Builder) entry; + } + + private java.lang.Object requestPayload_ = ""; + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @return The requestPayload. + */ + public java.lang.String getRequestPayload() { + java.lang.Object ref = requestPayload_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + requestPayload_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @return The bytes for requestPayload. + */ + public com.google.protobuf.ByteString + getRequestPayloadBytes() { + java.lang.Object ref = requestPayload_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + requestPayload_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @param value The requestPayload to set. + * @return This builder for chaining. + */ + public Builder setRequestPayload( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + requestPayload_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @return This builder for chaining. + */ + public Builder clearRequestPayload() { + requestPayload_ = getDefaultInstance().getRequestPayload(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + return this; + } + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @param value The bytes for requestPayload to set. + * @return This builder for chaining. + */ + public Builder setRequestPayloadBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + requestPayload_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + + private int apiCollectionId_ ; + /** + * int32 api_collection_id = 6 [json_name = "apiCollectionId"]; + * @return The apiCollectionId. + */ + @java.lang.Override + public int getApiCollectionId() { + return apiCollectionId_; + } + /** + * int32 api_collection_id = 6 [json_name = "apiCollectionId"]; + * @param value The apiCollectionId to set. + * @return This builder for chaining. + */ + public Builder setApiCollectionId(int value) { + + apiCollectionId_ = value; + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + * int32 api_collection_id = 6 [json_name = "apiCollectionId"]; + * @return This builder for chaining. + */ + public Builder clearApiCollectionId() { + bitField0_ = (bitField0_ & ~0x00000020); + apiCollectionId_ = 0; + onChanged(); + return this; + } + + private int statusCode_ ; + /** + * int32 status_code = 7 [json_name = "statusCode"]; + * @return The statusCode. + */ + @java.lang.Override + public int getStatusCode() { + return statusCode_; + } + /** + * int32 status_code = 7 [json_name = "statusCode"]; + * @param value The statusCode to set. + * @return This builder for chaining. + */ + public Builder setStatusCode(int value) { + + statusCode_ = value; + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + * int32 status_code = 7 [json_name = "statusCode"]; + * @return This builder for chaining. + */ + public Builder clearStatusCode() { + bitField0_ = (bitField0_ & ~0x00000040); + statusCode_ = 0; + onChanged(); + return this; + } + + private java.lang.Object status_ = ""; + /** + * string status = 8 [json_name = "status"]; + * @return The status. + */ + public java.lang.String getStatus() { + java.lang.Object ref = status_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + status_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string status = 8 [json_name = "status"]; + * @return The bytes for status. + */ + public com.google.protobuf.ByteString + getStatusBytes() { + java.lang.Object ref = status_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + status_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string status = 8 [json_name = "status"]; + * @param value The status to set. + * @return This builder for chaining. + */ + public Builder setStatus( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + status_ = value; + bitField0_ |= 0x00000080; + onChanged(); + return this; + } + /** + * string status = 8 [json_name = "status"]; + * @return This builder for chaining. + */ + public Builder clearStatus() { + status_ = getDefaultInstance().getStatus(); + bitField0_ = (bitField0_ & ~0x00000080); + onChanged(); + return this; + } + /** + * string status = 8 [json_name = "status"]; + * @param value The bytes for status to set. + * @return This builder for chaining. + */ + public Builder setStatusBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + status_ = value; + bitField0_ |= 0x00000080; + onChanged(); + return this; + } + + private static final class ResponseHeadersConverter implements com.google.protobuf.MapFieldBuilder.Converter { + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList build(com.akto.proto.http_response_param.v1.StringListOrBuilder val) { + if (val instanceof com.akto.proto.http_response_param.v1.StringList) { return (com.akto.proto.http_response_param.v1.StringList) val; } + return ((com.akto.proto.http_response_param.v1.StringList.Builder) val).build(); + } + + @java.lang.Override + public com.google.protobuf.MapEntry defaultEntry() { + return ResponseHeadersDefaultEntryHolder.defaultEntry; + } + }; + private static final ResponseHeadersConverter responseHeadersConverter = new ResponseHeadersConverter(); + + private com.google.protobuf.MapFieldBuilder< + java.lang.String, com.akto.proto.http_response_param.v1.StringListOrBuilder, com.akto.proto.http_response_param.v1.StringList, com.akto.proto.http_response_param.v1.StringList.Builder> responseHeaders_; + private com.google.protobuf.MapFieldBuilder + internalGetResponseHeaders() { + if (responseHeaders_ == null) { + return new com.google.protobuf.MapFieldBuilder<>(responseHeadersConverter); + } + return responseHeaders_; + } + private com.google.protobuf.MapFieldBuilder + internalGetMutableResponseHeaders() { + if (responseHeaders_ == null) { + responseHeaders_ = new com.google.protobuf.MapFieldBuilder<>(responseHeadersConverter); + } + bitField0_ |= 0x00000100; + onChanged(); + return responseHeaders_; + } + public int getResponseHeadersCount() { + return internalGetResponseHeaders().ensureBuilderMap().size(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public boolean containsResponseHeaders( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetResponseHeaders().ensureBuilderMap().containsKey(key); + } + /** + * Use {@link #getResponseHeadersMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getResponseHeaders() { + return getResponseHeadersMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public java.util.Map getResponseHeadersMap() { + return internalGetResponseHeaders().getImmutableMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public /* nullable */ +com.akto.proto.http_response_param.v1.StringList getResponseHeadersOrDefault( + java.lang.String key, + /* nullable */ +com.akto.proto.http_response_param.v1.StringList defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableResponseHeaders().ensureBuilderMap(); + return map.containsKey(key) ? responseHeadersConverter.build(map.get(key)) : defaultValue; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList getResponseHeadersOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableResponseHeaders().ensureBuilderMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return responseHeadersConverter.build(map.get(key)); + } + public Builder clearResponseHeaders() { + bitField0_ = (bitField0_ & ~0x00000100); + internalGetMutableResponseHeaders().clear(); + return this; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + public Builder removeResponseHeaders( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableResponseHeaders().ensureBuilderMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableResponseHeaders() { + bitField0_ |= 0x00000100; + return internalGetMutableResponseHeaders().ensureMessageMap(); + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + public Builder putResponseHeaders( + java.lang.String key, + com.akto.proto.http_response_param.v1.StringList value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableResponseHeaders().ensureBuilderMap() + .put(key, value); + bitField0_ |= 0x00000100; + return this; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + public Builder putAllResponseHeaders( + java.util.Map values) { + for (java.util.Map.Entry e : values.entrySet()) { + if (e.getKey() == null || e.getValue() == null) { + throw new NullPointerException(); + } + } + internalGetMutableResponseHeaders().ensureBuilderMap() + .putAll(values); + bitField0_ |= 0x00000100; + return this; + } + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + public com.akto.proto.http_response_param.v1.StringList.Builder putResponseHeadersBuilderIfAbsent( + java.lang.String key) { + java.util.Map builderMap = internalGetMutableResponseHeaders().ensureBuilderMap(); + com.akto.proto.http_response_param.v1.StringListOrBuilder entry = builderMap.get(key); + if (entry == null) { + entry = com.akto.proto.http_response_param.v1.StringList.newBuilder(); + builderMap.put(key, entry); + } + if (entry instanceof com.akto.proto.http_response_param.v1.StringList) { + entry = ((com.akto.proto.http_response_param.v1.StringList) entry).toBuilder(); + builderMap.put(key, entry); + } + return (com.akto.proto.http_response_param.v1.StringList.Builder) entry; + } + + private java.lang.Object responsePayload_ = ""; + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @return The responsePayload. + */ + public java.lang.String getResponsePayload() { + java.lang.Object ref = responsePayload_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + responsePayload_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @return The bytes for responsePayload. + */ + public com.google.protobuf.ByteString + getResponsePayloadBytes() { + java.lang.Object ref = responsePayload_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + responsePayload_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @param value The responsePayload to set. + * @return This builder for chaining. + */ + public Builder setResponsePayload( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + responsePayload_ = value; + bitField0_ |= 0x00000200; + onChanged(); + return this; + } + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @return This builder for chaining. + */ + public Builder clearResponsePayload() { + responsePayload_ = getDefaultInstance().getResponsePayload(); + bitField0_ = (bitField0_ & ~0x00000200); + onChanged(); + return this; + } + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @param value The bytes for responsePayload to set. + * @return This builder for chaining. + */ + public Builder setResponsePayloadBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + responsePayload_ = value; + bitField0_ |= 0x00000200; + onChanged(); + return this; + } + + private int time_ ; + /** + * int32 time = 11 [json_name = "time"]; + * @return The time. + */ + @java.lang.Override + public int getTime() { + return time_; + } + /** + * int32 time = 11 [json_name = "time"]; + * @param value The time to set. + * @return This builder for chaining. + */ + public Builder setTime(int value) { + + time_ = value; + bitField0_ |= 0x00000400; + onChanged(); + return this; + } + /** + * int32 time = 11 [json_name = "time"]; + * @return This builder for chaining. + */ + public Builder clearTime() { + bitField0_ = (bitField0_ & ~0x00000400); + time_ = 0; + onChanged(); + return this; + } + + private java.lang.Object aktoAccountId_ = ""; + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @return The aktoAccountId. + */ + public java.lang.String getAktoAccountId() { + java.lang.Object ref = aktoAccountId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + aktoAccountId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @return The bytes for aktoAccountId. + */ + public com.google.protobuf.ByteString + getAktoAccountIdBytes() { + java.lang.Object ref = aktoAccountId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + aktoAccountId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @param value The aktoAccountId to set. + * @return This builder for chaining. + */ + public Builder setAktoAccountId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + aktoAccountId_ = value; + bitField0_ |= 0x00000800; + onChanged(); + return this; + } + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @return This builder for chaining. + */ + public Builder clearAktoAccountId() { + aktoAccountId_ = getDefaultInstance().getAktoAccountId(); + bitField0_ = (bitField0_ & ~0x00000800); + onChanged(); + return this; + } + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @param value The bytes for aktoAccountId to set. + * @return This builder for chaining. + */ + public Builder setAktoAccountIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + aktoAccountId_ = value; + bitField0_ |= 0x00000800; + onChanged(); + return this; + } + + private java.lang.Object ip_ = ""; + /** + * string ip = 13 [json_name = "ip"]; + * @return The ip. + */ + public java.lang.String getIp() { + java.lang.Object ref = ip_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + ip_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string ip = 13 [json_name = "ip"]; + * @return The bytes for ip. + */ + public com.google.protobuf.ByteString + getIpBytes() { + java.lang.Object ref = ip_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + ip_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string ip = 13 [json_name = "ip"]; + * @param value The ip to set. + * @return This builder for chaining. + */ + public Builder setIp( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ip_ = value; + bitField0_ |= 0x00001000; + onChanged(); + return this; + } + /** + * string ip = 13 [json_name = "ip"]; + * @return This builder for chaining. + */ + public Builder clearIp() { + ip_ = getDefaultInstance().getIp(); + bitField0_ = (bitField0_ & ~0x00001000); + onChanged(); + return this; + } + /** + * string ip = 13 [json_name = "ip"]; + * @param value The bytes for ip to set. + * @return This builder for chaining. + */ + public Builder setIpBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ip_ = value; + bitField0_ |= 0x00001000; + onChanged(); + return this; + } + + private java.lang.Object destIp_ = ""; + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @return The destIp. + */ + public java.lang.String getDestIp() { + java.lang.Object ref = destIp_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + destIp_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @return The bytes for destIp. + */ + public com.google.protobuf.ByteString + getDestIpBytes() { + java.lang.Object ref = destIp_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + destIp_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @param value The destIp to set. + * @return This builder for chaining. + */ + public Builder setDestIp( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + destIp_ = value; + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @return This builder for chaining. + */ + public Builder clearDestIp() { + destIp_ = getDefaultInstance().getDestIp(); + bitField0_ = (bitField0_ & ~0x00002000); + onChanged(); + return this; + } + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @param value The bytes for destIp to set. + * @return This builder for chaining. + */ + public Builder setDestIpBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + destIp_ = value; + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + + private java.lang.Object direction_ = ""; + /** + * string direction = 15 [json_name = "direction"]; + * @return The direction. + */ + public java.lang.String getDirection() { + java.lang.Object ref = direction_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + direction_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string direction = 15 [json_name = "direction"]; + * @return The bytes for direction. + */ + public com.google.protobuf.ByteString + getDirectionBytes() { + java.lang.Object ref = direction_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + direction_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string direction = 15 [json_name = "direction"]; + * @param value The direction to set. + * @return This builder for chaining. + */ + public Builder setDirection( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + direction_ = value; + bitField0_ |= 0x00004000; + onChanged(); + return this; + } + /** + * string direction = 15 [json_name = "direction"]; + * @return This builder for chaining. + */ + public Builder clearDirection() { + direction_ = getDefaultInstance().getDirection(); + bitField0_ = (bitField0_ & ~0x00004000); + onChanged(); + return this; + } + /** + * string direction = 15 [json_name = "direction"]; + * @param value The bytes for direction to set. + * @return This builder for chaining. + */ + public Builder setDirectionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + direction_ = value; + bitField0_ |= 0x00004000; + onChanged(); + return this; + } + + private boolean isPending_ ; + /** + * bool is_pending = 16 [json_name = "isPending"]; + * @return The isPending. + */ + @java.lang.Override + public boolean getIsPending() { + return isPending_; + } + /** + * bool is_pending = 16 [json_name = "isPending"]; + * @param value The isPending to set. + * @return This builder for chaining. + */ + public Builder setIsPending(boolean value) { + + isPending_ = value; + bitField0_ |= 0x00008000; + onChanged(); + return this; + } + /** + * bool is_pending = 16 [json_name = "isPending"]; + * @return This builder for chaining. + */ + public Builder clearIsPending() { + bitField0_ = (bitField0_ & ~0x00008000); + isPending_ = false; + onChanged(); + return this; + } + + private java.lang.Object source_ = ""; + /** + * string source = 17 [json_name = "source"]; + * @return The source. + */ + public java.lang.String getSource() { + java.lang.Object ref = source_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + source_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string source = 17 [json_name = "source"]; + * @return The bytes for source. + */ + public com.google.protobuf.ByteString + getSourceBytes() { + java.lang.Object ref = source_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + source_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string source = 17 [json_name = "source"]; + * @param value The source to set. + * @return This builder for chaining. + */ + public Builder setSource( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + source_ = value; + bitField0_ |= 0x00010000; + onChanged(); + return this; + } + /** + * string source = 17 [json_name = "source"]; + * @return This builder for chaining. + */ + public Builder clearSource() { + source_ = getDefaultInstance().getSource(); + bitField0_ = (bitField0_ & ~0x00010000); + onChanged(); + return this; + } + /** + * string source = 17 [json_name = "source"]; + * @param value The bytes for source to set. + * @return This builder for chaining. + */ + public Builder setSourceBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + source_ = value; + bitField0_ |= 0x00010000; + onChanged(); + return this; + } + + private java.lang.Object aktoVxlanId_ = ""; + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @return The aktoVxlanId. + */ + public java.lang.String getAktoVxlanId() { + java.lang.Object ref = aktoVxlanId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + aktoVxlanId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @return The bytes for aktoVxlanId. + */ + public com.google.protobuf.ByteString + getAktoVxlanIdBytes() { + java.lang.Object ref = aktoVxlanId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + aktoVxlanId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @param value The aktoVxlanId to set. + * @return This builder for chaining. + */ + public Builder setAktoVxlanId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + aktoVxlanId_ = value; + bitField0_ |= 0x00020000; + onChanged(); + return this; + } + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @return This builder for chaining. + */ + public Builder clearAktoVxlanId() { + aktoVxlanId_ = getDefaultInstance().getAktoVxlanId(); + bitField0_ = (bitField0_ & ~0x00020000); + onChanged(); + return this; + } + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @param value The bytes for aktoVxlanId to set. + * @return This builder for chaining. + */ + public Builder setAktoVxlanIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + aktoVxlanId_ = value; + bitField0_ |= 0x00020000; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:threat_detection.message.http_response_param.v1.HttpResponseParam) + } + + // @@protoc_insertion_point(class_scope:threat_detection.message.http_response_param.v1.HttpResponseParam) + private static final com.akto.proto.http_response_param.v1.HttpResponseParam DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.akto.proto.http_response_param.v1.HttpResponseParam(); + } + + public static com.akto.proto.http_response_param.v1.HttpResponseParam getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public HttpResponseParam parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.HttpResponseParam getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParamOrBuilder.java b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParamOrBuilder.java new file mode 100644 index 0000000000..1fcc1d632d --- /dev/null +++ b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParamOrBuilder.java @@ -0,0 +1,247 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: threat_detection/message/http_response_param/v1/http_response_param.proto +// Protobuf Java Version: 4.28.3 + +package com.akto.proto.http_response_param.v1; + +public interface HttpResponseParamOrBuilder extends + // @@protoc_insertion_point(interface_extends:threat_detection.message.http_response_param.v1.HttpResponseParam) + com.google.protobuf.MessageOrBuilder { + + /** + * string method = 1 [json_name = "method"]; + * @return The method. + */ + java.lang.String getMethod(); + /** + * string method = 1 [json_name = "method"]; + * @return The bytes for method. + */ + com.google.protobuf.ByteString + getMethodBytes(); + + /** + * string path = 2 [json_name = "path"]; + * @return The path. + */ + java.lang.String getPath(); + /** + * string path = 2 [json_name = "path"]; + * @return The bytes for path. + */ + com.google.protobuf.ByteString + getPathBytes(); + + /** + * string type = 3 [json_name = "type"]; + * @return The type. + */ + java.lang.String getType(); + /** + * string type = 3 [json_name = "type"]; + * @return The bytes for type. + */ + com.google.protobuf.ByteString + getTypeBytes(); + + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + int getRequestHeadersCount(); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + boolean containsRequestHeaders( + java.lang.String key); + /** + * Use {@link #getRequestHeadersMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getRequestHeaders(); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + java.util.Map + getRequestHeadersMap(); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + /* nullable */ +com.akto.proto.http_response_param.v1.StringList getRequestHeadersOrDefault( + java.lang.String key, + /* nullable */ +com.akto.proto.http_response_param.v1.StringList defaultValue); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> request_headers = 4 [json_name = "requestHeaders"]; + */ + com.akto.proto.http_response_param.v1.StringList getRequestHeadersOrThrow( + java.lang.String key); + + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @return The requestPayload. + */ + java.lang.String getRequestPayload(); + /** + * string request_payload = 5 [json_name = "requestPayload"]; + * @return The bytes for requestPayload. + */ + com.google.protobuf.ByteString + getRequestPayloadBytes(); + + /** + * int32 api_collection_id = 6 [json_name = "apiCollectionId"]; + * @return The apiCollectionId. + */ + int getApiCollectionId(); + + /** + * int32 status_code = 7 [json_name = "statusCode"]; + * @return The statusCode. + */ + int getStatusCode(); + + /** + * string status = 8 [json_name = "status"]; + * @return The status. + */ + java.lang.String getStatus(); + /** + * string status = 8 [json_name = "status"]; + * @return The bytes for status. + */ + com.google.protobuf.ByteString + getStatusBytes(); + + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + int getResponseHeadersCount(); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + boolean containsResponseHeaders( + java.lang.String key); + /** + * Use {@link #getResponseHeadersMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getResponseHeaders(); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + java.util.Map + getResponseHeadersMap(); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + /* nullable */ +com.akto.proto.http_response_param.v1.StringList getResponseHeadersOrDefault( + java.lang.String key, + /* nullable */ +com.akto.proto.http_response_param.v1.StringList defaultValue); + /** + * map<string, .threat_detection.message.http_response_param.v1.StringList> response_headers = 9 [json_name = "responseHeaders"]; + */ + com.akto.proto.http_response_param.v1.StringList getResponseHeadersOrThrow( + java.lang.String key); + + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @return The responsePayload. + */ + java.lang.String getResponsePayload(); + /** + * string response_payload = 10 [json_name = "responsePayload"]; + * @return The bytes for responsePayload. + */ + com.google.protobuf.ByteString + getResponsePayloadBytes(); + + /** + * int32 time = 11 [json_name = "time"]; + * @return The time. + */ + int getTime(); + + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @return The aktoAccountId. + */ + java.lang.String getAktoAccountId(); + /** + * string akto_account_id = 12 [json_name = "aktoAccountId"]; + * @return The bytes for aktoAccountId. + */ + com.google.protobuf.ByteString + getAktoAccountIdBytes(); + + /** + * string ip = 13 [json_name = "ip"]; + * @return The ip. + */ + java.lang.String getIp(); + /** + * string ip = 13 [json_name = "ip"]; + * @return The bytes for ip. + */ + com.google.protobuf.ByteString + getIpBytes(); + + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @return The destIp. + */ + java.lang.String getDestIp(); + /** + * string dest_ip = 14 [json_name = "destIp"]; + * @return The bytes for destIp. + */ + com.google.protobuf.ByteString + getDestIpBytes(); + + /** + * string direction = 15 [json_name = "direction"]; + * @return The direction. + */ + java.lang.String getDirection(); + /** + * string direction = 15 [json_name = "direction"]; + * @return The bytes for direction. + */ + com.google.protobuf.ByteString + getDirectionBytes(); + + /** + * bool is_pending = 16 [json_name = "isPending"]; + * @return The isPending. + */ + boolean getIsPending(); + + /** + * string source = 17 [json_name = "source"]; + * @return The source. + */ + java.lang.String getSource(); + /** + * string source = 17 [json_name = "source"]; + * @return The bytes for source. + */ + com.google.protobuf.ByteString + getSourceBytes(); + + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @return The aktoVxlanId. + */ + java.lang.String getAktoVxlanId(); + /** + * string akto_vxlan_id = 18 [json_name = "aktoVxlanId"]; + * @return The bytes for aktoVxlanId. + */ + com.google.protobuf.ByteString + getAktoVxlanIdBytes(); +} diff --git a/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParamProto.java b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParamProto.java new file mode 100644 index 0000000000..6e0a985d01 --- /dev/null +++ b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/HttpResponseParamProto.java @@ -0,0 +1,129 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: threat_detection/message/http_response_param/v1/http_response_param.proto +// Protobuf Java Version: 4.28.3 + +package com.akto.proto.http_response_param.v1; + +public final class HttpResponseParamProto { + private HttpResponseParamProto() {} + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 28, + /* patch= */ 3, + /* suffix= */ "", + HttpResponseParamProto.class.getName()); + } + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_threat_detection_message_http_response_param_v1_StringList_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_threat_detection_message_http_response_param_v1_StringList_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_RequestHeadersEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_RequestHeadersEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_ResponseHeadersEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_ResponseHeadersEntry_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\nIthreat_detection/message/http_response" + + "_param/v1/http_response_param.proto\022/thr" + + "eat_detection.message.http_response_para" + + "m.v1\"$\n\nStringList\022\026\n\006values\030\001 \003(\tR\006valu" + + "es\"\361\007\n\021HttpResponseParam\022\026\n\006method\030\001 \001(\t" + + "R\006method\022\022\n\004path\030\002 \001(\tR\004path\022\022\n\004type\030\003 \001" + + "(\tR\004type\022\177\n\017request_headers\030\004 \003(\0132V.thre" + + "at_detection.message.http_response_param" + + ".v1.HttpResponseParam.RequestHeadersEntr" + + "yR\016requestHeaders\022\'\n\017request_payload\030\005 \001" + + "(\tR\016requestPayload\022*\n\021api_collection_id\030" + + "\006 \001(\005R\017apiCollectionId\022\037\n\013status_code\030\007 " + + "\001(\005R\nstatusCode\022\026\n\006status\030\010 \001(\tR\006status\022" + + "\202\001\n\020response_headers\030\t \003(\0132W.threat_dete" + + "ction.message.http_response_param.v1.Htt" + + "pResponseParam.ResponseHeadersEntryR\017res" + + "ponseHeaders\022)\n\020response_payload\030\n \001(\tR\017" + + "responsePayload\022\022\n\004time\030\013 \001(\005R\004time\022&\n\017a" + + "kto_account_id\030\014 \001(\tR\raktoAccountId\022\016\n\002i" + + "p\030\r \001(\tR\002ip\022\027\n\007dest_ip\030\016 \001(\tR\006destIp\022\034\n\t" + + "direction\030\017 \001(\tR\tdirection\022\035\n\nis_pending" + + "\030\020 \001(\010R\tisPending\022\026\n\006source\030\021 \001(\tR\006sourc" + + "e\022\"\n\rakto_vxlan_id\030\022 \001(\tR\013aktoVxlanId\032~\n" + + "\023RequestHeadersEntry\022\020\n\003key\030\001 \001(\tR\003key\022Q" + + "\n\005value\030\002 \001(\0132;.threat_detection.message" + + ".http_response_param.v1.StringListR\005valu" + + "e:\0028\001\032\177\n\024ResponseHeadersEntry\022\020\n\003key\030\001 \001" + + "(\tR\003key\022Q\n\005value\030\002 \001(\0132;.threat_detectio" + + "n.message.http_response_param.v1.StringL" + + "istR\005value:\0028\001B\331\002\nHcom.akto.proto.genera" + + "ted.threat_detection.message.http_respon" + + "se_param.v1B\026HttpResponseParamProtoP\001Z\"p" + + "rotobuf/traffic_payload;trafficpb\242\002\003TMH\252" + + "\002,ThreatDetection.Message.HttpResponsePa" + + "ram.V1\312\002,ThreatDetection\\Message\\HttpRes" + + "ponseParam\\V1\342\0028ThreatDetection\\Message\\" + + "HttpResponseParam\\V1\\GPBMetadata\352\002/Threa" + + "tDetection::Message::HttpResponseParam::" + + "V1b\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_threat_detection_message_http_response_param_v1_StringList_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_threat_detection_message_http_response_param_v1_StringList_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_threat_detection_message_http_response_param_v1_StringList_descriptor, + new java.lang.String[] { "Values", }); + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor, + new java.lang.String[] { "Method", "Path", "Type", "RequestHeaders", "RequestPayload", "ApiCollectionId", "StatusCode", "Status", "ResponseHeaders", "ResponsePayload", "Time", "AktoAccountId", "Ip", "DestIp", "Direction", "IsPending", "Source", "AktoVxlanId", }); + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_RequestHeadersEntry_descriptor = + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor.getNestedTypes().get(0); + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_RequestHeadersEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_RequestHeadersEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_ResponseHeadersEntry_descriptor = + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_descriptor.getNestedTypes().get(1); + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_ResponseHeadersEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_threat_detection_message_http_response_param_v1_HttpResponseParam_ResponseHeadersEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + descriptor.resolveAllFeaturesImmutable(); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/StringList.java b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/StringList.java new file mode 100644 index 0000000000..4a6ce60a7d --- /dev/null +++ b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/StringList.java @@ -0,0 +1,652 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: threat_detection/message/http_response_param/v1/http_response_param.proto +// Protobuf Java Version: 4.28.3 + +package com.akto.proto.http_response_param.v1; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +/** + * Protobuf type {@code threat_detection.message.http_response_param.v1.StringList} + */ +public final class StringList extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:threat_detection.message.http_response_param.v1.StringList) + StringListOrBuilder, List { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 28, + /* patch= */ 3, + /* suffix= */ "", + StringList.class.getName()); + } + // Use StringList.newBuilder() to construct. + private StringList(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private StringList() { + values_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_StringList_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_StringList_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.akto.proto.http_response_param.v1.StringList.class, com.akto.proto.http_response_param.v1.StringList.Builder.class); + } + + public static final int VALUES_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList values_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + * repeated string values = 1 [json_name = "values"]; + * @return A list containing the values. + */ + public com.google.protobuf.ProtocolStringList + getValuesList() { + return values_; + } + /** + * repeated string values = 1 [json_name = "values"]; + * @return The count of values. + */ + public int getValuesCount() { + return values_.size(); + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param index The index of the element to return. + * @return The values at the given index. + */ + public java.lang.String getValues(int index) { + return values_.get(index); + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param index The index of the value to return. + * @return The bytes of the values at the given index. + */ + public com.google.protobuf.ByteString + getValuesBytes(int index) { + return values_.getByteString(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < values_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, values_.getRaw(i)); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + { + int dataSize = 0; + for (int i = 0; i < values_.size(); i++) { + dataSize += computeStringSizeNoTag(values_.getRaw(i)); + } + size += dataSize; + size += 1 * getValuesList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.akto.proto.http_response_param.v1.StringList)) { + return super.equals(obj); + } + com.akto.proto.http_response_param.v1.StringList other = (com.akto.proto.http_response_param.v1.StringList) obj; + + if (!getValuesList() + .equals(other.getValuesList())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getValuesCount() > 0) { + hash = (37 * hash) + VALUES_FIELD_NUMBER; + hash = (53 * hash) + getValuesList().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static com.akto.proto.http_response_param.v1.StringList parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static com.akto.proto.http_response_param.v1.StringList parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static com.akto.proto.http_response_param.v1.StringList parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.akto.proto.http_response_param.v1.StringList prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code threat_detection.message.http_response_param.v1.StringList} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:threat_detection.message.http_response_param.v1.StringList) + com.akto.proto.http_response_param.v1.StringListOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_StringList_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_StringList_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.akto.proto.http_response_param.v1.StringList.class, com.akto.proto.http_response_param.v1.StringList.Builder.class); + } + + // Construct using com.akto.proto.http_response_param.v1.StringList.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + values_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.akto.proto.http_response_param.v1.HttpResponseParamProto.internal_static_threat_detection_message_http_response_param_v1_StringList_descriptor; + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList getDefaultInstanceForType() { + return com.akto.proto.http_response_param.v1.StringList.getDefaultInstance(); + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList build() { + com.akto.proto.http_response_param.v1.StringList result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList buildPartial() { + com.akto.proto.http_response_param.v1.StringList result = new com.akto.proto.http_response_param.v1.StringList(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(com.akto.proto.http_response_param.v1.StringList result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + values_.makeImmutable(); + result.values_ = values_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.akto.proto.http_response_param.v1.StringList) { + return mergeFrom((com.akto.proto.http_response_param.v1.StringList)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.akto.proto.http_response_param.v1.StringList other) { + if (other == com.akto.proto.http_response_param.v1.StringList.getDefaultInstance()) return this; + if (!other.values_.isEmpty()) { + if (values_.isEmpty()) { + values_ = other.values_; + bitField0_ |= 0x00000001; + } else { + ensureValuesIsMutable(); + values_.addAll(other.values_); + } + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + ensureValuesIsMutable(); + values_.add(s); + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private com.google.protobuf.LazyStringArrayList values_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureValuesIsMutable() { + if (!values_.isModifiable()) { + values_ = new com.google.protobuf.LazyStringArrayList(values_); + } + bitField0_ |= 0x00000001; + } + /** + * repeated string values = 1 [json_name = "values"]; + * @return A list containing the values. + */ + public com.google.protobuf.ProtocolStringList + getValuesList() { + values_.makeImmutable(); + return values_; + } + /** + * repeated string values = 1 [json_name = "values"]; + * @return The count of values. + */ + public int getValuesCount() { + return values_.size(); + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param index The index of the element to return. + * @return The values at the given index. + */ + public java.lang.String getValues(int index) { + return values_.get(index); + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param index The index of the value to return. + * @return The bytes of the values at the given index. + */ + public com.google.protobuf.ByteString + getValuesBytes(int index) { + return values_.getByteString(index); + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param index The index to set the value at. + * @param value The values to set. + * @return This builder for chaining. + */ + public Builder setValues( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureValuesIsMutable(); + values_.set(index, value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param value The values to add. + * @return This builder for chaining. + */ + public Builder addValues( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureValuesIsMutable(); + values_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param values The values to add. + * @return This builder for chaining. + */ + public Builder addAllValues( + java.lang.Iterable values) { + ensureValuesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, values_); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * repeated string values = 1 [json_name = "values"]; + * @return This builder for chaining. + */ + public Builder clearValues() { + values_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001);; + onChanged(); + return this; + } + /** + * repeated string values = 1 [json_name = "values"]; + * @param value The bytes of the values to add. + * @return This builder for chaining. + */ + public Builder addValuesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureValuesIsMutable(); + values_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:threat_detection.message.http_response_param.v1.StringList) + } + + // @@protoc_insertion_point(class_scope:threat_detection.message.http_response_param.v1.StringList) + private static final com.akto.proto.http_response_param.v1.StringList DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.akto.proto.http_response_param.v1.StringList(); + } + + public static com.akto.proto.http_response_param.v1.StringList getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public StringList parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.akto.proto.http_response_param.v1.StringList getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + @Override + public int size() { + return values_.size(); + } + @Override + public boolean isEmpty() { + return values_.isEmpty(); + } + @Override + public boolean contains(Object o) { + return values_.contains(o); + } + @Override + public Iterator iterator() { + return values_.iterator(); + } + @Override + public Object[] toArray() { + return values_.toArray(); + } + @Override + public T[] toArray(T[] a) { + return values_.toArray(a); + } + @Override + public boolean add(String e) { + return values_.add(e); + } + @Override + public boolean remove(Object o) { + return values_.remove(o); + } + @Override + public boolean containsAll(Collection c) { + return values_.containsAll(c); + } + @Override + public boolean addAll(Collection c) { + return values_.addAll(c); + } + @Override + public boolean addAll(int index, Collection c) { + return values_.addAll(index, c); + } + @Override + public boolean removeAll(Collection c) { + return values_.removeAll(c); + } + @Override + public boolean retainAll(Collection c) { + return values_.retainAll(c); + } + @Override + public void clear() { + values_.clear(); + } + @Override + public String get(int index) { + return values_.get(index); + } + @Override + public String set(int index, String element) { + return values_.set(index, element); + } + @Override + public void add(int index, String element) { + values_.add(index, element); + } + @Override + public String remove(int index) { + return values_.remove(index); + } + @Override + public int indexOf(Object o) { + return values_.indexOf(o); + } + @Override + public int lastIndexOf(Object o) { + return values_.lastIndexOf(o); + } + @Override + public ListIterator listIterator() { + return values_.listIterator(); + } + @Override + public ListIterator listIterator(int index) { + return values_.listIterator(index); + } + @Override + public List subList(int fromIndex, int toIndex) { + return values_.subList(fromIndex, toIndex); + } + +} + diff --git a/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/StringListOrBuilder.java b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/StringListOrBuilder.java new file mode 100644 index 0000000000..8304180a84 --- /dev/null +++ b/libs/protobuf/src/main/java/com/akto/proto/http_response_param/v1/StringListOrBuilder.java @@ -0,0 +1,36 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: threat_detection/message/http_response_param/v1/http_response_param.proto +// Protobuf Java Version: 4.28.3 + +package com.akto.proto.http_response_param.v1; + +public interface StringListOrBuilder extends + // @@protoc_insertion_point(interface_extends:threat_detection.message.http_response_param.v1.StringList) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated string values = 1 [json_name = "values"]; + * @return A list containing the values. + */ + java.util.List + getValuesList(); + /** + * repeated string values = 1 [json_name = "values"]; + * @return The count of values. + */ + int getValuesCount(); + /** + * repeated string values = 1 [json_name = "values"]; + * @param index The index of the element to return. + * @return The values at the given index. + */ + java.lang.String getValues(int index); + /** + * repeated string values = 1 [json_name = "values"]; + * @param index The index of the value to return. + * @return The bytes of the values at the given index. + */ + com.google.protobuf.ByteString + getValuesBytes(int index); +} diff --git a/libs/utils/src/main/java/com/akto/kafka/Kafka.java b/libs/utils/src/main/java/com/akto/kafka/Kafka.java index 95a143987c..834782c547 100644 --- a/libs/utils/src/main/java/com/akto/kafka/Kafka.java +++ b/libs/utils/src/main/java/com/akto/kafka/Kafka.java @@ -9,68 +9,72 @@ import java.util.Properties; public class Kafka { - private static final Logger logger = LoggerFactory.getLogger(Kafka.class); - private KafkaProducer producer; - public boolean producerReady; + private static final Logger logger = LoggerFactory.getLogger(Kafka.class); + private KafkaProducer producer; + public boolean producerReady; - public Kafka(String brokerIP, int lingerMS, int batchSize) { - producerReady = false; - try { - setProducer(brokerIP, lingerMS, batchSize); - } catch (Exception e) { - e.printStackTrace(); - } + public Kafka(KafkaConfig kafkaConfig) { + this( + kafkaConfig.getBootstrapServers(), + kafkaConfig.getProducerConfig().getLingerMs(), + kafkaConfig.getProducerConfig().getBatchSize()); + } + + public Kafka(String brokerIP, int lingerMS, int batchSize) { + producerReady = false; + try { + setProducer(brokerIP, lingerMS, batchSize); + } catch (Exception e) { + e.printStackTrace(); } + } - public void send(String message,String topic) { - if (!this.producerReady) return; + public void send(String message, String topic) { + if (!this.producerReady) return; - ProducerRecord record = new ProducerRecord<>(topic,message); - producer.send(record, new DemoProducerCallback()); - } + ProducerRecord record = new ProducerRecord<>(topic, message); + producer.send(record, new DemoProducerCallback()); + } - public void close() { - this.producerReady = false; - producer.close(Duration.ofMillis(0)); // close immediately - } + public void close() { + this.producerReady = false; + producer.close(Duration.ofMillis(0)); // close immediately + } - private void setProducer(String brokerIP, int lingerMS, int batchSize) { - if (producer != null) close(); // close existing producer connection + private void setProducer(String brokerIP, int lingerMS, int batchSize) { + if (producer != null) close(); // close existing producer connection - int requestTimeoutMs = 5000; - Properties kafkaProps = new Properties(); - kafkaProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokerIP); - kafkaProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); - kafkaProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); - kafkaProps.put(ProducerConfig.BATCH_SIZE_CONFIG, batchSize); - kafkaProps.put(ProducerConfig.LINGER_MS_CONFIG, lingerMS); - kafkaProps.put(ProducerConfig.RETRIES_CONFIG, 0); - kafkaProps.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, requestTimeoutMs); - kafkaProps.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, lingerMS + requestTimeoutMs); - producer = new KafkaProducer(kafkaProps); + int requestTimeoutMs = 5000; + Properties kafkaProps = new Properties(); + kafkaProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokerIP); + kafkaProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + kafkaProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + kafkaProps.put(ProducerConfig.BATCH_SIZE_CONFIG, batchSize); + kafkaProps.put(ProducerConfig.LINGER_MS_CONFIG, lingerMS); + kafkaProps.put(ProducerConfig.RETRIES_CONFIG, 0); + kafkaProps.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, requestTimeoutMs); + kafkaProps.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, lingerMS + requestTimeoutMs); + producer = new KafkaProducer(kafkaProps); - // test if connection successful by sending a test message in a blocking way - // calling .get() blocks the thread till we receive a message - // if any error then close the connection - ProducerRecord record = new ProducerRecord<>("akto.misc", "ping"); - try { - producer.send(record).get(); - producerReady = true; - } catch (Exception ignored) { - close(); - } + // test if connection successful by sending a test message in a blocking way + // calling .get() blocks the thread till we receive a message + // if any error then close the connection + ProducerRecord record = new ProducerRecord<>("akto.misc", "ping"); + try { + producer.send(record).get(); + producerReady = true; + } catch (Exception ignored) { + close(); } + } - private class DemoProducerCallback implements Callback { - @Override - public void onCompletion(RecordMetadata recordMetadata, Exception e) { - if (e != null) { - Kafka.this.close(); - logger.error("onCompletion error: " + e.getMessage()); - } - } + private class DemoProducerCallback implements Callback { + @Override + public void onCompletion(RecordMetadata recordMetadata, Exception e) { + if (e != null) { + Kafka.this.close(); + logger.error("onCompletion error: " + e.getMessage()); + } } - + } } - - diff --git a/libs/utils/src/main/java/com/akto/kafka/KafkaConfig.java b/libs/utils/src/main/java/com/akto/kafka/KafkaConfig.java new file mode 100644 index 0000000000..c7209871f3 --- /dev/null +++ b/libs/utils/src/main/java/com/akto/kafka/KafkaConfig.java @@ -0,0 +1,68 @@ +package com.akto.kafka; + +public class KafkaConfig { + private final String bootstrapServers; + private final String groupId; + private final KafkaConsumerConfig consumerConfig; + private final KafkaProducerConfig producerConfig; + + public static class Builder { + private String bootstrapServers; + private String groupId; + private KafkaConsumerConfig consumerConfig; + private KafkaProducerConfig producerConfig; + + private Builder() {} + + public Builder setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + return this; + } + + public Builder setGroupId(String groupId) { + this.groupId = groupId; + return this; + } + + public Builder setConsumerConfig(KafkaConsumerConfig consumerConfig) { + this.consumerConfig = consumerConfig; + return this; + } + + public Builder setProducerConfig(KafkaProducerConfig producerConfig) { + this.producerConfig = producerConfig; + return this; + } + + public KafkaConfig build() { + return new KafkaConfig(this); + } + } + + private KafkaConfig(Builder builder) { + this.bootstrapServers = builder.bootstrapServers; + this.groupId = builder.groupId; + this.consumerConfig = builder.consumerConfig; + this.producerConfig = builder.producerConfig; + } + + public String getBootstrapServers() { + return bootstrapServers; + } + + public String getGroupId() { + return groupId; + } + + public KafkaConsumerConfig getConsumerConfig() { + return consumerConfig; + } + + public KafkaProducerConfig getProducerConfig() { + return producerConfig; + } + + public static Builder newBuilder() { + return new Builder(); + } +} diff --git a/libs/utils/src/main/java/com/akto/kafka/KafkaConsumerConfig.java b/libs/utils/src/main/java/com/akto/kafka/KafkaConsumerConfig.java new file mode 100644 index 0000000000..6feddce794 --- /dev/null +++ b/libs/utils/src/main/java/com/akto/kafka/KafkaConsumerConfig.java @@ -0,0 +1,44 @@ +package com.akto.kafka; + +public class KafkaConsumerConfig { + private final int maxPollRecords; + private final int pollDurationMilli; + + public static class Builder { + private int maxPollRecords; + private int pollDurationMilli; + + private Builder() {} + + public Builder setMaxPollRecords(int maxPollRecords) { + this.maxPollRecords = maxPollRecords; + return this; + } + + public Builder setPollDurationMilli(int pollDurationMilli) { + this.pollDurationMilli = pollDurationMilli; + return this; + } + + public KafkaConsumerConfig build() { + return new KafkaConsumerConfig(this); + } + } + + public KafkaConsumerConfig(Builder builder) { + this.maxPollRecords = builder.maxPollRecords; + this.pollDurationMilli = builder.pollDurationMilli; + } + + public int getMaxPollRecords() { + return maxPollRecords; + } + + public int getPollDurationMilli() { + return pollDurationMilli; + } + + public static Builder newBuilder() { + return new Builder(); + } +} diff --git a/libs/utils/src/main/java/com/akto/kafka/KafkaProducerConfig.java b/libs/utils/src/main/java/com/akto/kafka/KafkaProducerConfig.java new file mode 100644 index 0000000000..ca999ee0a6 --- /dev/null +++ b/libs/utils/src/main/java/com/akto/kafka/KafkaProducerConfig.java @@ -0,0 +1,44 @@ +package com.akto.kafka; + +public class KafkaProducerConfig { + private final int lingerMs; + private final int batchSize; + + public static class Builder { + private int lingerMs; + private int batchSize; + + public Builder() {} + + public Builder setLingerMs(int lingerMs) { + this.lingerMs = lingerMs; + return this; + } + + public Builder setBatchSize(int batchSize) { + this.batchSize = batchSize; + return this; + } + + public KafkaProducerConfig build() { + return new KafkaProducerConfig(this); + } + } + + public static Builder newBuilder() { + return new Builder(); + } + + public int getLingerMs() { + return lingerMs; + } + + public int getBatchSize() { + return batchSize; + } + + public KafkaProducerConfig(Builder builder) { + this.lingerMs = builder.lingerMs; + this.batchSize = builder.batchSize; + } +} diff --git a/libs/utils/src/main/java/com/akto/runtime/utils/Utils.java b/libs/utils/src/main/java/com/akto/runtime/utils/Utils.java index e9b5537fbe..ffba6d1876 100644 --- a/libs/utils/src/main/java/com/akto/runtime/utils/Utils.java +++ b/libs/utils/src/main/java/com/akto/runtime/utils/Utils.java @@ -1,17 +1,7 @@ package com.akto.runtime.utils; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.StringJoiner; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.kafka.clients.consumer.ConsumerConfig; -import org.apache.kafka.common.serialization.StringDeserializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static com.akto.dto.RawApi.convertHeaders; +import static com.akto.util.HttpRequestResponseUtils.GRPC_CONTENT_TYPE; import com.akto.dto.HttpRequestParams; import com.akto.dto.HttpResponseParams; @@ -24,213 +14,243 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.mongodb.BasicDBObject; -import static com.akto.dto.RawApi.convertHeaders; - -import static com.akto.util.HttpRequestResponseUtils.GRPC_CONTENT_TYPE; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.StringJoiner; +import java.util.regex.Pattern; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Utils { - private static final Logger logger = LoggerFactory.getLogger(Utils.class); + private static final Logger logger = LoggerFactory.getLogger(Utils.class); - private static int debugPrintCounter = 500; - public static void printL(Object o) { - if (debugPrintCounter > 0) { - debugPrintCounter--; - logger.info(o.toString()); - } - } + private static int debugPrintCounter = 500; - public static Properties configProperties(String kafkaBrokerUrl, String groupIdConfig, int maxPollRecordsConfig) { - Properties properties = new Properties(); - properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBrokerUrl); - properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); - properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); - properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecordsConfig); - properties.put(ConsumerConfig.GROUP_ID_CONFIG, groupIdConfig); - properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); - properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); - - return properties; + public static void printL(Object o) { + if (debugPrintCounter > 0) { + debugPrintCounter--; + logger.info(o.toString()); } - - public static String convertOriginalReqRespToString(OriginalHttpRequest request, OriginalHttpResponse response, int responseTime) { - BasicDBObject ret = convertOriginalReqRespToStringUtil(request, response); - ret.append("responseTime", responseTime); - return ret.toString(); + } + + public static Properties configProperties( + String kafkaBrokerUrl, String groupIdConfig, int maxPollRecordsConfig) { + Properties properties = new Properties(); + properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBrokerUrl); + properties.put( + ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, + "org.apache.kafka.common.serialization.StringDeserializer"); + properties.put( + ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, + "org.apache.kafka.common.serialization.StringDeserializer"); + properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecordsConfig); + properties.put(ConsumerConfig.GROUP_ID_CONFIG, groupIdConfig); + properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); + + return properties; + } + + public static String convertOriginalReqRespToString( + OriginalHttpRequest request, OriginalHttpResponse response, int responseTime) { + BasicDBObject ret = convertOriginalReqRespToStringUtil(request, response); + ret.append("responseTime", responseTime); + return ret.toString(); + } + + public static String convertOriginalReqRespToString( + OriginalHttpRequest request, OriginalHttpResponse response) { + return convertOriginalReqRespToStringUtil(request, response).toString(); + } + + public static BasicDBObject convertOriginalReqRespToStringUtil( + OriginalHttpRequest request, OriginalHttpResponse response) { + BasicDBObject req = new BasicDBObject(); + if (request != null) { + req.put("url", request.getUrl()); + req.put("method", request.getMethod()); + req.put("type", request.getType()); + req.put("queryParams", request.getQueryParams()); + req.put("body", request.getBody()); + req.put("headers", convertHeaders(request.getHeaders())); } - public static String convertOriginalReqRespToString(OriginalHttpRequest request, OriginalHttpResponse response) { - return convertOriginalReqRespToStringUtil(request, response).toString(); + BasicDBObject resp = new BasicDBObject(); + if (response != null) { + resp.put("statusCode", response.getStatusCode()); + resp.put("body", response.getBody()); + resp.put("headers", convertHeaders(response.getHeaders())); } - public static BasicDBObject convertOriginalReqRespToStringUtil(OriginalHttpRequest request, OriginalHttpResponse response) { - BasicDBObject req = new BasicDBObject(); - if (request != null) { - req.put("url", request.getUrl()); - req.put("method", request.getMethod()); - req.put("type", request.getType()); - req.put("queryParams", request.getQueryParams()); - req.put("body", request.getBody()); - req.put("headers", convertHeaders(request.getHeaders())); - } - - BasicDBObject resp = new BasicDBObject(); - if (response != null) { - resp.put("statusCode", response.getStatusCode()); - resp.put("body", response.getBody()); - resp.put("headers", convertHeaders(response.getHeaders())); - } - - BasicDBObject ret = new BasicDBObject(); - ret.put("request", req); - ret.put("response", resp); - - return ret; + BasicDBObject ret = new BasicDBObject(); + ret.put("request", req); + ret.put("response", resp); + + return ret; + } + + public static String convertToSampleMessage(String message) throws Exception { + JSONObject jsonObject = JSON.parseObject(message); + JSONObject request = (JSONObject) jsonObject.get("request"); + JSONObject response = (JSONObject) jsonObject.get("response"); + + JSONObject sampleMessage = new JSONObject(); + if (request != null) { + if (request.get("body") != null) { + sampleMessage.put("requestPayload", request.get("body")); + } + if (request.get("headers") != null) { + sampleMessage.put("requestHeaders", request.get("headers")); + } + // TODO: add query params to url + if (request.get("url") != null) { + sampleMessage.put("path", request.get("url")); + } + if (request.get("method") != null) { + sampleMessage.put("method", request.get("method")); + } + if (request.get("type") != null) { + sampleMessage.put("type", request.get("type")); + } } - - public static String convertToSampleMessage(String message) throws Exception { - JSONObject jsonObject = JSON.parseObject(message); - JSONObject request = (JSONObject) jsonObject.get("request"); - JSONObject response = (JSONObject) jsonObject.get("response"); - - JSONObject sampleMessage = new JSONObject(); - if(request != null) { - if(request.get("body") != null) { - sampleMessage.put("requestPayload", request.get("body")); - } - if(request.get("headers") != null) { - sampleMessage.put("requestHeaders", request.get("headers")); - } - // TODO: add query params to url - if(request.get("url") != null) { - sampleMessage.put("path", request.get("url")); - } - if(request.get("method") != null) { - sampleMessage.put("method", request.get("method")); - } - if(request.get("type") != null) { - sampleMessage.put("type", request.get("type")); - } - } - if(response != null) { - if(response.get("body") != null) { - sampleMessage.put("responsePayload", response.get("body")); - } - if(response.get("headers") != null) { - sampleMessage.put("responseHeaders", response.get("headers")); - } - if(response.get("statusCode") != null) { - sampleMessage.put("statusCode", (Integer)response.getInteger("statusCode")); - } - - } - return sampleMessage.toJSONString(); + if (response != null) { + if (response.get("body") != null) { + sampleMessage.put("responsePayload", response.get("body")); + } + if (response.get("headers") != null) { + sampleMessage.put("responseHeaders", response.get("headers")); + } + if (response.get("statusCode") != null) { + sampleMessage.put("statusCode", (Integer) response.getInteger("statusCode")); + } } - - public static Map parseCookie(List cookieList){ - Map cookieMap = new HashMap<>(); - if(cookieList==null)return cookieMap; - for (String cookieValues : cookieList) { - String[] cookies = cookieValues.split(";"); - for (String cookie : cookies) { - cookie=cookie.trim(); - String[] cookieFields = cookie.split("="); - boolean twoCookieFields = cookieFields.length == 2; - if (twoCookieFields) { - if(!cookieMap.containsKey(cookieFields[0])){ - cookieMap.put(cookieFields[0], cookieFields[1]); - } - } - } + return sampleMessage.toJSONString(); + } + + public static Map parseCookie(List cookieList) { + Map cookieMap = new HashMap<>(); + if (cookieList == null) return cookieMap; + for (String cookieValues : cookieList) { + String[] cookies = cookieValues.split(";"); + for (String cookie : cookies) { + cookie = cookie.trim(); + String[] cookieFields = cookie.split("="); + boolean twoCookieFields = cookieFields.length == 2; + if (twoCookieFields) { + if (!cookieMap.containsKey(cookieFields[0])) { + cookieMap.put(cookieFields[0], cookieFields[1]); + } } - return cookieMap; + } } + return cookieMap; + } - private static int GRPC_DEBUG_COUNTER = 50; - - public static HttpResponseParams parseKafkaMessage(String message) throws Exception { + private static int GRPC_DEBUG_COUNTER = 50; - //convert java object to JSON format + public static HttpResponseParams parseKafkaMessage(String message) throws Exception { - JSONObject jsonObject = JSON.parseObject(message); + // convert java object to JSON format - String method = jsonObject.getString("method"); - String url = jsonObject.getString("path"); - String type = jsonObject.getString("type"); - Map> requestHeaders = OriginalHttpRequest.buildHeadersMap(jsonObject, "requestHeaders"); + JSONObject jsonObject = JSON.parseObject(message); - String rawRequestPayload = jsonObject.getString("requestPayload"); - String requestPayload = HttpRequestResponseUtils.rawToJsonString(rawRequestPayload,requestHeaders); + String method = jsonObject.getString("method"); + String url = jsonObject.getString("path"); + String type = jsonObject.getString("type"); + Map> requestHeaders = + OriginalHttpRequest.buildHeadersMap(jsonObject, "requestHeaders"); - if (GRPC_DEBUG_COUNTER > 0) { - String acceptableContentType = HttpRequestResponseUtils.getAcceptableContentType(requestHeaders); - if (acceptableContentType != null && rawRequestPayload.length() > 0) { - // only if request payload is of FORM_URL_ENCODED_CONTENT_TYPE we convert it to json - if (acceptableContentType.equals(GRPC_CONTENT_TYPE)) { - logger.info("grpc kafka payload:" + message,LogDb.RUNTIME); - GRPC_DEBUG_COUNTER--; - } - } - } + String rawRequestPayload = jsonObject.getString("requestPayload"); + String requestPayload = + HttpRequestResponseUtils.rawToJsonString(rawRequestPayload, requestHeaders); - String apiCollectionIdStr = jsonObject.getOrDefault("akto_vxlan_id", "0").toString(); - int apiCollectionId = 0; - if (NumberUtils.isDigits(apiCollectionIdStr)) { - apiCollectionId = NumberUtils.toInt(apiCollectionIdStr, 0); + if (GRPC_DEBUG_COUNTER > 0) { + String acceptableContentType = + HttpRequestResponseUtils.getAcceptableContentType(requestHeaders); + if (acceptableContentType != null && rawRequestPayload.length() > 0) { + // only if request payload is of FORM_URL_ENCODED_CONTENT_TYPE we convert it to json + if (acceptableContentType.equals(GRPC_CONTENT_TYPE)) { + logger.info("grpc kafka payload:" + message, LogDb.RUNTIME); + GRPC_DEBUG_COUNTER--; } - - HttpRequestParams requestParams = new HttpRequestParams( - method,url,type, requestHeaders, requestPayload, apiCollectionId - ); - - int statusCode = jsonObject.getInteger("statusCode"); - String status = jsonObject.getString("status"); - Map> responseHeaders = OriginalHttpRequest.buildHeadersMap(jsonObject, "responseHeaders"); - String payload = jsonObject.getString("responsePayload"); - payload = HttpRequestResponseUtils.rawToJsonString(payload, responseHeaders); - payload = JSONUtils.parseIfJsonP(payload); - int time = jsonObject.getInteger("time"); - String accountId = jsonObject.getString("akto_account_id"); - String sourceIP = jsonObject.getString("ip"); - String destIP = jsonObject.getString("destIp"); - String direction = jsonObject.getString("direction"); - - String isPendingStr = (String) jsonObject.getOrDefault("is_pending", "false"); - boolean isPending = !isPendingStr.toLowerCase().equals("false"); - String sourceStr = (String) jsonObject.getOrDefault("source", HttpResponseParams.Source.OTHER.name()); - HttpResponseParams.Source source = HttpResponseParams.Source.valueOf(sourceStr); - - return new HttpResponseParams( - type,statusCode, status, responseHeaders, payload, requestParams, time, accountId, isPending, source, message, sourceIP, destIP, direction - ); + } } - public static Pattern createRegexPatternFromList(List discardedUrlList){ - StringJoiner joiner = new StringJoiner("|", ".*\\.(", ")(\\?.*)?"); - for (String extension : discardedUrlList) { - if(extension.startsWith("CONTENT-TYPE")){ - continue; - } - joiner.add(extension); - } - String regex = joiner.toString(); - - Pattern pattern = Pattern.compile(regex); - return pattern; + String apiCollectionIdStr = jsonObject.getOrDefault("akto_vxlan_id", "0").toString(); + int apiCollectionId = 0; + if (NumberUtils.isDigits(apiCollectionIdStr)) { + apiCollectionId = NumberUtils.toInt(apiCollectionIdStr, 0); } - public static HttpResponseParams convertRawApiToHttpResponseParams(RawApi rawApi, HttpResponseParams originalHttpResponseParams){ + HttpRequestParams requestParams = + new HttpRequestParams(method, url, type, requestHeaders, requestPayload, apiCollectionId); + + int statusCode = jsonObject.getInteger("statusCode"); + String status = jsonObject.getString("status"); + Map> responseHeaders = + OriginalHttpRequest.buildHeadersMap(jsonObject, "responseHeaders"); + String payload = jsonObject.getString("responsePayload"); + payload = HttpRequestResponseUtils.rawToJsonString(payload, responseHeaders); + payload = JSONUtils.parseIfJsonP(payload); + int time = jsonObject.getInteger("time"); + String accountId = jsonObject.getString("akto_account_id"); + String sourceIP = jsonObject.getString("ip"); + String destIP = jsonObject.getString("destIp"); + String direction = jsonObject.getString("direction"); + + String isPendingStr = (String) jsonObject.getOrDefault("is_pending", "false"); + boolean isPending = !isPendingStr.toLowerCase().equals("false"); + String sourceStr = + (String) jsonObject.getOrDefault("source", HttpResponseParams.Source.OTHER.name()); + HttpResponseParams.Source source = HttpResponseParams.Source.valueOf(sourceStr); + + return new HttpResponseParams( + type, + statusCode, + status, + responseHeaders, + payload, + requestParams, + time, + accountId, + isPending, + source, + message, + sourceIP, + destIP, + direction); + } + + public static Pattern createRegexPatternFromList(List discardedUrlList) { + StringJoiner joiner = new StringJoiner("|", ".*\\.(", ")(\\?.*)?"); + for (String extension : discardedUrlList) { + if (extension.startsWith("CONTENT-TYPE")) { + continue; + } + joiner.add(extension); + } + String regex = joiner.toString(); - HttpRequestParams ogRequestParams = originalHttpResponseParams.getRequestParams(); - OriginalHttpRequest modifiedRequest = rawApi.getRequest(); + Pattern pattern = Pattern.compile(regex); + return pattern; + } - ogRequestParams.setHeaders(modifiedRequest.getHeaders()); - ogRequestParams.setUrl(modifiedRequest.getFullUrlWithParams()); - ogRequestParams.setPayload(modifiedRequest.getBody()); + public static HttpResponseParams convertRawApiToHttpResponseParams( + RawApi rawApi, HttpResponseParams originalHttpResponseParams) { - originalHttpResponseParams.setRequestParams(ogRequestParams); + HttpRequestParams ogRequestParams = originalHttpResponseParams.getRequestParams(); + OriginalHttpRequest modifiedRequest = rawApi.getRequest(); - return originalHttpResponseParams; - } + ogRequestParams.setHeaders(modifiedRequest.getHeaders()); + ogRequestParams.setUrl(modifiedRequest.getFullUrlWithParams()); + ogRequestParams.setPayload(modifiedRequest.getBody()); + originalHttpResponseParams.setRequestParams(ogRequestParams); + return originalHttpResponseParams; + } } diff --git a/libs/utils/src/main/java/com/akto/traffic/KafkaRunner.java b/libs/utils/src/main/java/com/akto/traffic/KafkaRunner.java index ea364a1de5..571982f9aa 100644 --- a/libs/utils/src/main/java/com/akto/traffic/KafkaRunner.java +++ b/libs/utils/src/main/java/com/akto/traffic/KafkaRunner.java @@ -9,12 +9,13 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import com.akto.DaoInit; +import com.mongodb.ConnectionString; import org.apache.commons.lang3.function.FailableFunction; import org.apache.kafka.clients.consumer.*; import org.apache.kafka.common.Metric; import org.apache.kafka.common.MetricName; import org.apache.kafka.common.errors.WakeupException; -import com.akto.DaoInit; import com.akto.RuntimeMode; import com.akto.dao.context.Context; import com.akto.data_actor.DataActor; @@ -24,137 +25,143 @@ import com.akto.log.LoggerMaker.LogDb; import com.akto.metrics.AllMetrics; import com.akto.runtime.utils.Utils; -import com.mongodb.ConnectionString; public class KafkaRunner { - private Consumer consumer; - private static final LoggerMaker loggerMaker = new LoggerMaker(KafkaRunner.class, LogDb.RUNTIME); - private static final DataActor dataActor = DataActorFactory.fetchInstance(); - - public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); - - public static void processKafkaRecords(LogDb module, List topics, - FailableFunction, Void, Exception> recordProcessor) { - - loggerMaker.setDb(module); - - boolean hybridSaas = RuntimeMode.isHybridDeployment(); - boolean connected =false; - if (hybridSaas) { - AccountSettings accountSettings = dataActor.fetchAccountSettings(); - if (accountSettings != null) { - int acc = accountSettings.getId(); - Context.accountId.set(acc); - connected = true; - } - } else { - String mongoURI = System.getenv("AKTO_MONGO_CONN"); - DaoInit.init(new ConnectionString(mongoURI)); - Context.accountId.set(1_000_000); - connected = true; - } - - if (connected) { - loggerMaker.infoAndAddToDb(String.format("Starting module for account : %d", Context.accountId.get())); - AllMetrics.instance.init(module); - } - - String kafkaBrokerUrl = "kafka1:19092"; - String isKubernetes = System.getenv("IS_KUBERNETES"); - if (isKubernetes != null && isKubernetes.equalsIgnoreCase("true")) { - loggerMaker.infoAndAddToDb("is_kubernetes: true"); - kafkaBrokerUrl = "127.0.0.1:29092"; - } - String groupIdConfig = System.getenv("AKTO_KAFKA_GROUP_ID_CONFIG"); - int maxPollRecordsConfig = Integer - .parseInt(System.getenv().getOrDefault("AKTO_KAFKA_MAX_POLL_RECORDS_CONFIG", "100")); + private Consumer consumer; + private static final LoggerMaker loggerMaker = new LoggerMaker(KafkaRunner.class, LogDb.RUNTIME); + private static final DataActor dataActor = DataActorFactory.fetchInstance(); + private static final String KAFKA_GROUP_ID = "akto-threat-detection"; + + public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); + + private static Properties generateKafkaProperties() { + String kafkaBrokerUrl = System.getenv("AKTO_KAFKA_BROKER_URL"); + int maxPollRecords = + Integer.parseInt(System.getenv().getOrDefault("AKTO_KAFKA_MAX_POLL_RECORDS_CONFIG", "100")); + + return Utils.configProperties(kafkaBrokerUrl, KAFKA_GROUP_ID, maxPollRecords); + } + + public static void consume( + LogDb module, + List topics, + FailableFunction, Void, Exception> recordProcessor) { + + loggerMaker.setDb(module); + + final KafkaRunner main = new KafkaRunner(); + main.consumer = new KafkaConsumer<>(generateKafkaProperties()); + + boolean hybridSaas = RuntimeMode.isHybridDeployment(); + boolean connected = false; + if (hybridSaas) { + AccountSettings accountSettings = dataActor.fetchAccountSettings(); + if (accountSettings != null) { + int acc = accountSettings.getId(); + Context.accountId.set(acc); + connected = true; + } + } else { + String mongoURI = System.getenv("AKTO_MONGO_CONN"); + DaoInit.init(new ConnectionString(mongoURI)); + Context.accountId.set(1_000_000); + connected = true; + } - Properties properties = Utils.configProperties(kafkaBrokerUrl, groupIdConfig, maxPollRecordsConfig); - final KafkaRunner main = new KafkaRunner(); - main.consumer = new KafkaConsumer<>(properties); + if (connected) { + loggerMaker.infoAndAddToDb( + String.format("Starting module for account : %d", Context.accountId.get())); + AllMetrics.instance.init(module); + } - final Thread mainThread = Thread.currentThread(); - final AtomicBoolean exceptionOnCommitSync = new AtomicBoolean(false); + final Thread mainThread = Thread.currentThread(); + final AtomicBoolean exceptionOnCommitSync = new AtomicBoolean(false); - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { + Runtime.getRuntime() + .addShutdownHook( + new Thread() { + public void run() { main.consumer.wakeup(); try { - if (!exceptionOnCommitSync.get()) { - mainThread.join(); - } + if (!exceptionOnCommitSync.get()) { + mainThread.join(); + } } catch (InterruptedException e) { - e.printStackTrace(); + e.printStackTrace(); } catch (Error e) { - loggerMaker.errorAndAddToDb("Error in main thread: " + e.getMessage()); + loggerMaker.errorAndAddToDb("Error in main thread: " + e.getMessage()); } - } - }); - - scheduler.scheduleAtFixedRate(() -> { - try { - logKafkaMetrics(main, module); - } catch (Exception e) { - loggerMaker.errorAndAddToDb(e, - String.format("Failed to get kafka metrics for %s error: %s", module.name(), e.toString())); - } - }, 0, 1, TimeUnit.MINUTES); - + } + }); + + scheduler.scheduleAtFixedRate( + () -> { + main.logKafkaMetrics(module); + }, + 0, + 1, + TimeUnit.MINUTES); + + try { + main.consumer.subscribe(topics); + loggerMaker.infoAndAddToDb( + String.format("Consumer subscribed for topics : %s", topics.toString())); + while (true) { + ConsumerRecords records = main.consumer.poll(Duration.ofMillis(10000)); try { - main.consumer.subscribe(topics); - loggerMaker.infoAndAddToDb(String.format("Consumer subscribed for topics : %s", topics.toString())); - while (true) { - ConsumerRecords records = main.consumer.poll(Duration.ofMillis(10000)); - try { - main.consumer.commitSync(); - } catch (Exception e) { - throw e; - } + main.consumer.commitSync(); + } catch (Exception e) { + throw e; + } - try { - recordProcessor.apply(records); - } catch (Exception e) { - loggerMaker.errorAndAddToDb(e, "Error while processing kafka messages " + e); - } - } - } catch (WakeupException ignored) { - // nothing to catch. This exception is called from the shutdown hook. + try { + recordProcessor.apply(records); } catch (Exception e) { - exceptionOnCommitSync.set(true); - Utils.printL(e); - loggerMaker.errorAndAddToDb("Error in Kafka consumer: " + e.getMessage()); - e.printStackTrace(); - System.exit(0); - } finally { - main.consumer.close(); + loggerMaker.errorAndAddToDb(e, "Error while processing kafka messages " + e); } + } + } catch (WakeupException ignored) { + // nothing to catch. This exception is called from the shutdown hook. + } catch (Exception e) { + exceptionOnCommitSync.set(true); + Utils.printL(e); + loggerMaker.errorAndAddToDb("Error in Kafka consumer: " + e.getMessage()); + e.printStackTrace(); + System.exit(0); + } finally { + main.consumer.close(); } + } + + public void logKafkaMetrics(LogDb module) { + try { + Map metrics = this.consumer.metrics(); + for (Map.Entry entry : metrics.entrySet()) { + MetricName key = entry.getKey(); + Metric value = entry.getValue(); + + if (key.name().equals("records-lag-max")) { + double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); + AllMetrics.instance.setKafkaRecordsLagMax((float) val); + } + if (key.name().equals("records-consumed-rate")) { + double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); + AllMetrics.instance.setKafkaRecordsConsumedRate((float) val); + } - private static void logKafkaMetrics(KafkaRunner main, LogDb module) { - Map metrics = main.consumer.metrics(); - for (Map.Entry entry : metrics.entrySet()) { - MetricName key = entry.getKey(); - Metric value = entry.getValue(); - - if (key.name().equals("records-lag-max")) { - double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); - AllMetrics.instance.setKafkaRecordsLagMax((float) val); - } - if (key.name().equals("records-consumed-rate")) { - double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); - AllMetrics.instance.setKafkaRecordsConsumedRate((float) val); - } - - if (key.name().equals("fetch-latency-avg")) { - double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); - AllMetrics.instance.setKafkaFetchAvgLatency((float) val); - } - - if (key.name().equals("bytes-consumed-rate")) { - double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); - AllMetrics.instance.setKafkaBytesConsumedRate((float) val); - } + if (key.name().equals("fetch-latency-avg")) { + double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); + AllMetrics.instance.setKafkaFetchAvgLatency((float) val); } - } -} \ No newline at end of file + if (key.name().equals("bytes-consumed-rate")) { + double val = value.metricValue().equals(Double.NaN) ? 0d : (double) value.metricValue(); + AllMetrics.instance.setKafkaBytesConsumedRate((float) val); + } + } + } catch (Exception e) { + loggerMaker.errorAndAddToDb( + e, String.format("Failed to get kafka metrics for %s error: %s", module.name(), e)); + } + } +} diff --git a/protobuf/threat_detection/message/http_response_param/v1/http_response_param.proto b/protobuf/threat_detection/message/http_response_param/v1/http_response_param.proto new file mode 100644 index 0000000000..fb2ee19225 --- /dev/null +++ b/protobuf/threat_detection/message/http_response_param/v1/http_response_param.proto @@ -0,0 +1,33 @@ +syntax = "proto3"; + +package threat_detection.message.http_response_param.v1; + +option java_outer_classname = "HttpResponseParamProto"; + +option go_package = "protobuf/traffic_payload;trafficpb"; + +message StringList { + repeated string values = 1; +} + +message HttpResponseParam { + string method = 1; + string path = 2; + string type = 3; + map request_headers = 4 [json_name = "requestHeaders"]; + string request_payload = 5 [json_name = "requestPayload"]; + int32 api_collection_id = 6 [json_name = "apiCollectionId"]; + int32 status_code = 7 [json_name = "statusCode"]; + string status = 8; + map response_headers = 9 [json_name = "responseHeaders"]; + string response_payload = 10 [json_name = "responsePayload"]; + int32 time = 11; + string akto_account_id = 12; + string ip = 13; + string dest_ip = 14 [json_name = "destIp"]; + string direction = 15; + bool is_pending = 16; + string source = 17; + string akto_vxlan_id = 18; +} + \ No newline at end of file diff --git a/protobuf/threat_detection/message/malicious_event/dashboard/v1/message.proto b/protobuf/threat_detection/message/malicious_event/dashboard/v1/message.proto new file mode 100644 index 0000000000..fd9e0c806b --- /dev/null +++ b/protobuf/threat_detection/message/malicious_event/dashboard/v1/message.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package threat_detection.message.malicious_event.dashboard.v1; + +import "threat_detection/message/malicious_event/event_type/v1/event_type.proto"; + +option java_outer_classname = "MaliciousEventDashboardProto"; +option java_package = "threat_detection.message.malicious_event.dashboard.v1"; + +message DashboardMaliciousEventMessage { + string id = 1; + string actor = 2; + string filter_id = 3; + int64 detected_at = 4; + string ip = 5; + string endpoint = 6; + string method = 7; + int32 api_collection_id = 8; + string payload = 9; + string country = 10; + threat_detection.message.malicious_event.event_type.v1.EventType event_type = 11; +}