diff --git a/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java b/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java index 7de4d41..a182067 100644 --- a/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java +++ b/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java @@ -1,6 +1,7 @@ package net.geedge.asw.module.app.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.servlet.http.HttpServletResponse; import net.geedge.asw.common.util.ASWException; import net.geedge.asw.common.util.R; import net.geedge.asw.common.util.RCode; @@ -12,6 +13,7 @@ import net.geedge.asw.module.sys.service.ISysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -122,4 +124,12 @@ public class ApplicationController { applicationService.restore(id, version); return R.ok(); } + + @GetMapping("/analyze") + public void analyze(@RequestParam String workspaceId, + @RequestParam String pcapIds, + HttpServletResponse response) throws IOException { + applicationService.redirectDiscoverPage(workspaceId, pcapIds, response); + } + } diff --git a/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java b/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java index 839da97..032e55f 100644 --- a/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java +++ b/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java @@ -2,8 +2,10 @@ package net.geedge.asw.module.app.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.servlet.http.HttpServletResponse; import net.geedge.asw.module.app.entity.ApplicationEntity; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -24,4 +26,7 @@ public interface IApplicationService extends IService{ List queryLogList(String id); void restore(String id, String version); + + void redirectDiscoverPage(String workspaceId, String pcapIds, HttpServletResponse response) throws IOException; + } diff --git a/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java b/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java index 564b810..66b1ead 100644 --- a/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java @@ -1,9 +1,17 @@ package net.geedge.asw.module.app.service.impl; +import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.net.url.UrlBuilder; +import cn.hutool.log.Log; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import net.geedge.asw.module.feign.client.KibanaClient; import net.geedge.asw.common.util.ASWException; import net.geedge.asw.common.util.RCode; import net.geedge.asw.common.util.T; @@ -12,20 +20,41 @@ import net.geedge.asw.module.app.entity.ApplicationEntity; import net.geedge.asw.module.app.entity.ApplicationLogEntity; import net.geedge.asw.module.app.service.IApplicationLogService; import net.geedge.asw.module.app.service.IApplicationService; +import net.geedge.asw.module.runner.entity.PcapEntity; +import net.geedge.asw.module.runner.service.IPcapService; +import net.geedge.asw.module.workspace.entity.WorkspaceEntity; +import net.geedge.asw.module.workspace.service.IWorkspaceService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; @Service public class ApplicationServiceImpl extends ServiceImpl implements IApplicationService { + private static final Log log = Log.get(); + + @Value("${kibana.url:127.0.0.1:5601}") + private String kibanaUrl; + @Autowired private IApplicationLogService applicationLogService; + @Autowired + private IWorkspaceService workspaceService; + + @Autowired + private IPcapService pcapService; + + @Resource + private KibanaClient kibanaClient; + @Override public ApplicationEntity queryByApplicationAndLog(String id, String version) { ApplicationEntity entity = this.baseMapper.queryByApplicationAndLog(id, version); @@ -131,4 +160,91 @@ public class ApplicationServiceImpl extends ServiceImpl pcapIdList = T.StrUtil.split(pcapIds, ",").stream().filter(s -> T.StrUtil.isNotEmpty(s)).collect(Collectors.toList()); + List pcapList = pcapService.list(new LambdaQueryWrapper().in(PcapEntity::getId, pcapIdList)); + T.VerifyUtil.is(pcapList).notEmpty(RCode.SYS_RECORD_NOT_FOUND); + + // index name + String indexName = String.format("workspace-%s-*", workspace.getName()); + + SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); + String token = tokenInfo.getTokenValue(); + + JSONObject index = kibanaClient.findIndexPattern(token, indexName); + JSONArray savedObjects = index.getJSONArray("saved_objects"); + + // check if index exists + boolean indexExists = savedObjects.stream() + .filter(obj -> { + JSONObject attributes = ((JSONObject) obj).getJSONObject("attributes"); + if (T.ObjectUtil.isEmpty(attributes)) return false; + String title = attributes.getString("title"); + return T.StrUtil.equals(indexName, title); + }) + .findFirst() + .isPresent(); + if (log.isDebugEnabled()) { + log.debug("[redirectDiscoverPage] [idnex-pattern: {}] [exists: {}]", indexName, indexExists); + } + + // create index + if (T.BooleanUtil.negate(indexExists)) { + JSONObject attributes = new JSONObject(); + attributes.put("title", indexName); + + JSONObject body = new JSONObject(); + body.put("attributes", attributes); + kibanaClient.saveIndexPattern(token, workspaceId, body); + } + + // build url + String baseUrl = UrlBuilder.ofHttp(kibanaUrl) + .addPath("/app/data-explorer/discover") + .addQuery("jwt", token) + .toString(); + + // build query param + String param1 = String.format("_a=(discover:(columns:!(_source),isDirty:!f,sort:!()),metadata:(indexPattern:'%s',view:discover))", workspaceId); + String param2 = "_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))"; + + String source = pcapList.stream() + .map(PcapEntity::getName) + .map(fileName -> "\"" + fileName + "\"") + .collect(Collectors.joining("|", "source: (", ")")); + String param3 = String.format("_q=(filters:!(),query:(language:lucene,query:'%s'))", source); + + String query = String.format("?%s&%s&%s", param1, param2, param3); + String redirectUrl = baseUrl + "#" + query; + + if(log.isDebugEnabled()){ + log.debug("[redirectDiscoverPage] [url: {}]", redirectUrl); + } + + // redirect + response.sendRedirect(redirectUrl); + } } diff --git a/src/main/java/net/geedge/asw/module/runner/client/FeignClientConfiguration.java b/src/main/java/net/geedge/asw/module/feign/FeignClientConfiguration.java similarity index 60% rename from src/main/java/net/geedge/asw/module/runner/client/FeignClientConfiguration.java rename to src/main/java/net/geedge/asw/module/feign/FeignClientConfiguration.java index da5488f..d04bb0f 100644 --- a/src/main/java/net/geedge/asw/module/runner/client/FeignClientConfiguration.java +++ b/src/main/java/net/geedge/asw/module/feign/FeignClientConfiguration.java @@ -1,12 +1,15 @@ -package net.geedge.asw.module.runner.client; +package net.geedge.asw.module.feign; import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.log.Log; import feign.Feign; import feign.form.FormEncoder; -import net.geedge.asw.common.config.feign.Fastjson2Decoder; -import net.geedge.asw.common.config.feign.Fastjson2Encoder; -import net.geedge.asw.common.config.feign.Http2Client; +import net.geedge.asw.module.feign.client.GeoipClient; +import net.geedge.asw.module.feign.client.KibanaClient; +import net.geedge.asw.module.feign.client.ZeekClient; +import net.geedge.asw.module.feign.support.Fastjson2Decoder; +import net.geedge.asw.module.feign.support.Fastjson2Encoder; +import net.geedge.asw.module.feign.support.Http2Client; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -22,6 +25,8 @@ public class FeignClientConfiguration { @Value("${geoip.url:127.0.0.1:8087}") private String geoipUrl; + @Value("${kibana.url:127.0.0.1:5601}") + private String kibanaUrl; @Bean("zeekClient") public ZeekClient zeekClient() { @@ -45,4 +50,15 @@ public class FeignClientConfiguration { .target(GeoipClient.class, url); } + @Bean("kibanaClient") + public KibanaClient kibanaClient() { + String url = UrlBuilder.ofHttp(kibanaUrl).toString(); + log.info("[kibanaClient] [url: {}]", url); + return Feign.builder() + .encoder(new Fastjson2Encoder()) + .decoder(new Fastjson2Decoder()) + .client(new Http2Client()) + .target(KibanaClient.class, url); + } + } \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/runner/client/OpenSearchClientConfiguration.java b/src/main/java/net/geedge/asw/module/feign/OpenSearchClientConfiguration.java similarity index 98% rename from src/main/java/net/geedge/asw/module/runner/client/OpenSearchClientConfiguration.java rename to src/main/java/net/geedge/asw/module/feign/OpenSearchClientConfiguration.java index 6199b33..d4ef81f 100644 --- a/src/main/java/net/geedge/asw/module/runner/client/OpenSearchClientConfiguration.java +++ b/src/main/java/net/geedge/asw/module/feign/OpenSearchClientConfiguration.java @@ -1,4 +1,4 @@ -package net.geedge.asw.module.runner.client; +package net.geedge.asw.module.feign; import cn.hutool.log.Log; import net.geedge.asw.common.util.T; diff --git a/src/main/java/net/geedge/asw/module/runner/client/GeoipClient.java b/src/main/java/net/geedge/asw/module/feign/client/GeoipClient.java similarity index 87% rename from src/main/java/net/geedge/asw/module/runner/client/GeoipClient.java rename to src/main/java/net/geedge/asw/module/feign/client/GeoipClient.java index 94aed4e..63d6f6a 100644 --- a/src/main/java/net/geedge/asw/module/runner/client/GeoipClient.java +++ b/src/main/java/net/geedge/asw/module/feign/client/GeoipClient.java @@ -1,4 +1,4 @@ -package net.geedge.asw.module.runner.client; +package net.geedge.asw.module.feign.client; import com.alibaba.fastjson2.JSONArray; import feign.Param; diff --git a/src/main/java/net/geedge/asw/module/feign/client/KibanaClient.java b/src/main/java/net/geedge/asw/module/feign/client/KibanaClient.java new file mode 100644 index 0000000..7995f28 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/feign/client/KibanaClient.java @@ -0,0 +1,23 @@ +package net.geedge.asw.module.feign.client; + +import com.alibaba.fastjson2.JSONObject; +import feign.Headers; +import feign.Param; +import feign.RequestLine; +import org.springframework.cloud.openfeign.FeignClient; + +@FeignClient(name = "kibanaClient") +@Headers("Authorization: Bearer {token}") +public interface KibanaClient { + + @RequestLine("GET /api/saved_objects/_find?fields=title&per_page=10000&type=index-pattern&search_fields=title&search={name}") + JSONObject findIndexPattern(@Param("token") String token, @Param("name") String name); + + @Headers({ + "Content-Type: application/json", + "osd-xsrf: true" + }) + @RequestLine("POST /api/saved_objects/index-pattern/{id}") + JSONObject saveIndexPattern(@Param("token") String token, @Param("id") String id, JSONObject body); + +} \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/runner/client/ZeekClient.java b/src/main/java/net/geedge/asw/module/feign/client/ZeekClient.java similarity index 89% rename from src/main/java/net/geedge/asw/module/runner/client/ZeekClient.java rename to src/main/java/net/geedge/asw/module/feign/client/ZeekClient.java index 479e1ee..44e07a6 100644 --- a/src/main/java/net/geedge/asw/module/runner/client/ZeekClient.java +++ b/src/main/java/net/geedge/asw/module/feign/client/ZeekClient.java @@ -1,4 +1,4 @@ -package net.geedge.asw.module.runner.client; +package net.geedge.asw.module.feign.client; import com.alibaba.fastjson2.JSONArray; import feign.Headers; diff --git a/src/main/java/net/geedge/asw/common/config/feign/Fastjson2Decoder.java b/src/main/java/net/geedge/asw/module/feign/support/Fastjson2Decoder.java similarity index 97% rename from src/main/java/net/geedge/asw/common/config/feign/Fastjson2Decoder.java rename to src/main/java/net/geedge/asw/module/feign/support/Fastjson2Decoder.java index 67d8183..10c4192 100644 --- a/src/main/java/net/geedge/asw/common/config/feign/Fastjson2Decoder.java +++ b/src/main/java/net/geedge/asw/module/feign/support/Fastjson2Decoder.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package net.geedge.asw.common.config.feign; +package net.geedge.asw.module.feign.support; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONException; diff --git a/src/main/java/net/geedge/asw/common/config/feign/Fastjson2Encoder.java b/src/main/java/net/geedge/asw/module/feign/support/Fastjson2Encoder.java similarity index 96% rename from src/main/java/net/geedge/asw/common/config/feign/Fastjson2Encoder.java rename to src/main/java/net/geedge/asw/module/feign/support/Fastjson2Encoder.java index a2a8de8..8db177d 100644 --- a/src/main/java/net/geedge/asw/common/config/feign/Fastjson2Encoder.java +++ b/src/main/java/net/geedge/asw/module/feign/support/Fastjson2Encoder.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package net.geedge.asw.common.config.feign; +package net.geedge.asw.module.feign.support; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONWriter; diff --git a/src/main/java/net/geedge/asw/common/config/feign/Http2Client.java b/src/main/java/net/geedge/asw/module/feign/support/Http2Client.java similarity index 99% rename from src/main/java/net/geedge/asw/common/config/feign/Http2Client.java rename to src/main/java/net/geedge/asw/module/feign/support/Http2Client.java index 7932975..932ef03 100644 --- a/src/main/java/net/geedge/asw/common/config/feign/Http2Client.java +++ b/src/main/java/net/geedge/asw/module/feign/support/Http2Client.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package net.geedge.asw.common.config.feign; +package net.geedge.asw.module.feign.support; import feign.*; import feign.Request.Options; diff --git a/src/main/java/net/geedge/asw/module/runner/util/PcapParserThread.java b/src/main/java/net/geedge/asw/module/runner/util/PcapParserThread.java index dc91382..5a30d4d 100644 --- a/src/main/java/net/geedge/asw/module/runner/util/PcapParserThread.java +++ b/src/main/java/net/geedge/asw/module/runner/util/PcapParserThread.java @@ -7,8 +7,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import lombok.Data; import net.geedge.asw.common.config.SpringContextUtils; import net.geedge.asw.common.util.T; -import net.geedge.asw.module.runner.client.GeoipClient; -import net.geedge.asw.module.runner.client.ZeekClient; +import net.geedge.asw.module.feign.client.GeoipClient; +import net.geedge.asw.module.feign.client.ZeekClient; import net.geedge.asw.module.runner.entity.PcapEntity; import net.geedge.asw.module.runner.service.IPcapService; import org.apache.commons.lang3.time.StopWatch; diff --git a/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java b/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java index 142fe6d..b0e0498 100644 --- a/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java +++ b/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java @@ -58,6 +58,7 @@ public class SysAuthController { String sign = jwt.sign(JWTSignerUtil.hs256(saTokenConfig.getJwtSecretKey().getBytes())); tokenInfo.setTokenValue(sign); + StpUtil.setTokenValue(sign); userEntity.setPwd(null); return R.ok().putData("tokenInfo", tokenInfo).putData("user", userEntity);