feat: ASW-30 新增 Application 分析重定向接口
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<ApplicationEntity>{
|
||||
List<ApplicationEntity> queryLogList(String id);
|
||||
|
||||
void restore(String id, String version);
|
||||
|
||||
void redirectDiscoverPage(String workspaceId, String pcapIds, HttpServletResponse response) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -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<ApplicationDao, ApplicationEntity> 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<ApplicationDao, Applicat
|
||||
ApplicationEntity application = T.BeanUtil.toBean(oldApplication, ApplicationEntity.class);
|
||||
this.updateById(application);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 根据 workspace_name 查询 index-pattern 是否存在
|
||||
* 2. 不存在则创建索引
|
||||
*
|
||||
* 维护格式示例:
|
||||
* {
|
||||
* "type": "index-pattern",
|
||||
* "id": "workspace_id",
|
||||
* "attributes": {
|
||||
* "title": "workspace-{workspace_name}-*"
|
||||
* }
|
||||
* }
|
||||
* @param workspaceId
|
||||
* @param pcapIds
|
||||
* @param response
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void redirectDiscoverPage(String workspaceId, String pcapIds, HttpServletResponse response) throws IOException {
|
||||
// verify
|
||||
WorkspaceEntity workspace = workspaceService.getById(workspaceId);
|
||||
T.VerifyUtil.is(workspace).notNull(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
List<String> pcapIdList = T.StrUtil.split(pcapIds, ",").stream().filter(s -> T.StrUtil.isNotEmpty(s)).collect(Collectors.toList());
|
||||
List<PcapEntity> pcapList = pcapService.list(new LambdaQueryWrapper<PcapEntity>().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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user