Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class AccessTokenAction implements Action, ServletResponseAware, ServletR
public static final String ACCESS_TOKEN_HEADER_NAME = "access-token";
public static final String CONTEXT_SOURCE_HEADER = "x-context-source";
public static final String AKTO_SESSION_TOKEN = "x-akto-session-token";
public static final String SUB_CATEGORY_HEADER = "x-sub-category";

@Override
public String execute() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public class ApiCollectionsAction extends UserAction {
int mcpDataCount;
@Setter
String type;
@Setter
String contextType;
@Getter
List<McpAuditInfo> auditAlerts;

Expand All @@ -116,10 +118,15 @@ public void setApiList(List<ApiInfoKey> apiList) {
* Only populates MCP URLs when dashboard context is not API security.
*/
private void populateCollectionUrls(ApiCollection apiCollection) {
// Do not populate MCP URLs if dashboard context is API security
if (Context.contextSource.get() != null && Context.contextSource.get() == GlobalEnums.CONTEXT_SOURCE.MCP) {
apiCollectionUrlService.populateMcpCollectionUrls(apiCollection);
}else {
try {
// Do not populate MCP URLs if dashboard context is API security
GlobalEnums.CONTEXT_SOURCE contextSource = Context.contextSource.get();
if (contextSource != null && contextSource == GlobalEnums.CONTEXT_SOURCE.MCP) {
apiCollectionUrlService.populateMcpCollectionUrls(apiCollection);
} else {
apiCollection.setUrls(new HashSet<>());
}
} catch (Exception e) {
apiCollection.setUrls(new HashSet<>());
}
}
Expand Down Expand Up @@ -237,7 +244,18 @@ public String fetchApiStats() {
}

public String fetchAllCollectionsBasic() {
UsersCollectionsList.deleteContextCollectionsForUser(Context.accountId.get(), Context.contextSource.get());
try {
// Safely delete context collections for user - handle potential null context source
Integer accountId = Context.accountId.get();
GlobalEnums.CONTEXT_SOURCE contextSource = Context.contextSource.get();
if (accountId != null) {
UsersCollectionsList.deleteContextCollectionsForUser(accountId, contextSource, Context.subCategory.get());
}
} catch (Exception e) {
// Log the error but don't fail the entire request
loggerMaker.errorAndAddToDb(e, "Error deleting context collections for user", LogDb.DASHBOARD);
}

this.apiCollections = ApiCollectionsDao.instance.findAll(Filters.empty(), Projections.exclude("urls"));
this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections, Filters.nin(SingleTypeInfo._API_COLLECTION_ID, deactivatedCollections));
return Action.SUCCESS.toUpperCase();
Expand Down Expand Up @@ -316,7 +334,7 @@ public String createCollection() {

UsersCollectionsList.deleteCollectionIdsFromCache(userId, accountId);
// remove the cache of context collections for account
UsersCollectionsList.deleteContextCollectionsForUser(Context.accountId.get(), Context.contextSource.get());
UsersCollectionsList.deleteContextCollectionsForUser(Context.accountId.get(), Context.contextSource.get(), Context.subCategory.get());
} catch(Exception e){
}

Expand Down Expand Up @@ -385,7 +403,7 @@ public String deleteMultipleCollections() {
UsersCollectionsList.deleteCollectionIdsFromCache(userId, accountId);

// remove the cache of context collections for account
UsersCollectionsList.deleteContextCollectionsForUser(Context.accountId.get(), Context.contextSource.get());
UsersCollectionsList.deleteContextCollectionsForUser(Context.accountId.get(), Context.contextSource.get(), Context.subCategory.get());
} catch (Exception e) {
}

Expand Down Expand Up @@ -1171,7 +1189,9 @@ public String fetchMcpdata() {
Bson mcpTagFilter = Filters.elemMatch(ApiCollection.TAGS_STRING,
Filters.eq("keyName", com.akto.util.Constants.AKTO_MCP_SERVER_TAG)
);

List<ApiCollection> mcpCollections = ApiCollectionsDao.instance.findAll(mcpTagFilter, null);

List<Integer> mcpCollectionIds = mcpCollections.stream().map(ApiCollection::getId).collect(Collectors.toList());

switch (filterType) {
Expand Down Expand Up @@ -1314,11 +1334,13 @@ public String fetchMcpdata() {
Bson guardRailTagFilter = Filters.elemMatch(ApiCollection.TAGS_STRING,
Filters.eq("keyName", Constants.AKTO_GUARD_RAIL_TAG)
);

// Use projection to only fetch IDs, reducing memory usage
List<ApiCollection> guardRailCollections = ApiCollectionsDao.instance.findAll(
guardRailTagFilter,
Projections.include(ApiCollection.ID)
guardRailTagFilter,
Projections.include(ApiCollection.ID)
);

List<Integer> guardRailCollectionIds = guardRailCollections.stream()
.map(ApiCollection::getId)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.akto.dao.context.Context;
import com.akto.dao.monitoring.FilterYamlTemplateDao;
import com.akto.util.enums.GlobalEnums.CONTEXT_SOURCE;
import com.akto.util.enums.GlobalEnums.SUB_CATEGORY_SOURCE;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -12,12 +14,56 @@ public class ThreatsUtils {

public static List<String> getTemplates(List<String> latestAttack) {
Set<String> contextTemplatesForAccount = FilterYamlTemplateDao.getContextTemplatesForAccount(Context.accountId.get(), Context.contextSource.get());
// Set<String> contextTemplatesForAccount = getContextTemplatesWithSubCategoryFilter(
// Context.accountId.get(),
// Context.contextSource.get(),
// Context.getSubCategory()
// );
//
// System.out.println("ThreatsUtils.getTemplates: Context=" + Context.contextSource.get() +
// ", SubCategory=" + Context.getSubCategory() +
// ", Templates count=" + contextTemplatesForAccount.size());

if(latestAttack == null || latestAttack.isEmpty()) {
return new ArrayList<>(contextTemplatesForAccount);
}


return latestAttack.stream().filter(contextTemplatesForAccount::contains).collect(Collectors.toList());
}

/**
* Get templates filtered by context and subcategory.
* Implements the same filtering logic as UsersCollectionsList.getContextCollections()
*/
// private static Set<String> getContextTemplatesWithSubCategoryFilter(int accountId, CONTEXT_SOURCE contextSource, SUB_CATEGORY_SOURCE subCategory) {
// // For non-AGENTIC contexts, use existing logic without subcategory filtering
// if (contextSource != CONTEXT_SOURCE.AGENTIC) {
// System.out.println("ThreatsUtils: Using standard context filtering for " + contextSource);
// return FilterYamlTemplateDao.getContextTemplatesForAccount(accountId, contextSource,subCategory);
// }
//
// // Handle null subcategory
// if (subCategory == null) {
// subCategory = SUB_CATEGORY_SOURCE.DEFAULT;
// }
//
// System.out.println("ThreatsUtils: Processing AGENTIC context with SubCategory: " + subCategory);
//
// // Apply subcategory-based filtering similar to UsersCollectionsList.getContextCollections()
// if (subCategory == SUB_CATEGORY_SOURCE.ENDPOINT_SECURITY) {
// // For endpoint security, use only MCP templates
// System.out.println("ThreatsUtils: Using MCP templates for Endpoint Security");
// return FilterYamlTemplateDao.getContextTemplatesForAccount(accountId, CONTEXT_SOURCE.MCP,subCategory);
//
// } else if (subCategory == SUB_CATEGORY_SOURCE.CLOUD_SECURITY) {
// // For cloud security, use only GenAI templates
// System.out.println("ThreatsUtils: Using GenAI templates for Cloud Security");
// return FilterYamlTemplateDao.getContextTemplatesForAccount(accountId, CONTEXT_SOURCE.GEN_AI,subCategory);
//
// } else {
// // For DEFAULT subcategory or other cases, use full AGENTIC templates (both MCP and GenAI)
// System.out.println("ThreatsUtils: Using all AGENTIC templates (DEFAULT subcategory)");
// return FilterYamlTemplateDao.getContextTemplatesForAccount(accountId, CONTEXT_SOURCE.AGENTIC,subCategory);
// }
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
String accessTokenFromResponse = httpServletResponse.getHeader(AccessTokenAction.ACCESS_TOKEN_HEADER_NAME);
String accessTokenFromRequest = httpServletRequest.getHeader(AccessTokenAction.ACCESS_TOKEN_HEADER_NAME);
String contextSourceFromRequest = httpServletRequest.getHeader(AccessTokenAction.CONTEXT_SOURCE_HEADER);
String subCategoryFromRequest = httpServletRequest.getHeader(AccessTokenAction.SUB_CATEGORY_HEADER);

String aktoSessionTokenFromRequest = httpServletRequest.getHeader(AccessTokenAction.AKTO_SESSION_TOKEN);

Expand All @@ -108,6 +109,18 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
}
}

if(!StringUtils.isEmpty(subCategoryFromRequest)) {
if(StringUtils.isEmpty(subCategoryFromRequest)){
Context.subCategory.set(GlobalEnums.SUB_CATEGORY_SOURCE.DEFAULT);
} else {
try {
Context.subCategory.set(GlobalEnums.SUB_CATEGORY_SOURCE.valueOf(subCategoryFromRequest.toUpperCase()));
} catch (Exception e) {
Context.subCategory.set(GlobalEnums.SUB_CATEGORY_SOURCE.DEFAULT);
}
}
}

if(StringUtils.isNotEmpty(aktoSessionTokenFromRequest) && httpServletRequest.getRequestURI().contains("agent")){
try {
Jws<Claims> claims = JwtAuthenticator.authenticate(aktoSessionTokenFromRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ export default function Header() {
}

const handleDashboardChange = (value) => {
// Preserve current subcategory selection
const currentSubCategory = PersistStore.getState().subCategory || 'Cloud Security';

PersistStore.getState().setAllCollections([]);
PersistStore.getState().setCollectionsMap({});
PersistStore.getState().setHostNameMap({});
Expand All @@ -126,6 +129,20 @@ export default function Header() {
LocalStore.getState().setCategoryMap({});
LocalStore.getState().setSubCategoryMap({});
SessionStore.getState().setThreatFiltersMap({});

// Set appropriate default subcategory for each dashboard category
if (value === "Agentic Security") {
// For Agentic Security, use Cloud Security as default on first load
const defaultSubCategory = currentSubCategory === 'Default' ? 'Cloud Security' : currentSubCategory;
PersistStore.getState().setSubCategory(defaultSubCategory);
} else if (value === "API Security") {
// For API Security, use Default subcategory (no filtering)
PersistStore.getState().setSubCategory('Default');
} else {
// For other categories, use Default subcategory
PersistStore.getState().setSubCategory('Default');
}

setDashboardCategory(value);
window.location.reload();
window.location.href("/dashboard/observe/inventory")
Expand Down Expand Up @@ -244,7 +261,6 @@ export default function Header() {
<Dropdown
menuItems={[
{ value: "API Security", label: "API Security", id: "api-security" },
{ value: "MCP Security", label: "MCP Security", id: "mcp-security" },
{ value: "Agentic Security", label: "Agentic Security", id: "agentic-security" },
]}
initial={dashboardCategory || "API Security"}
Expand Down
Loading
Loading