REM:
1. 新增设备类型
2. 新增错误码
3. 修改Restful公共接口
4. 新增华为防火墙创建安全策略、删除安全策略、查询所有安全策略接口
5. 新增华为设备能力接口
This commit is contained in:
chenlinghy 2021-04-28 17:18:32 +08:00
parent afb3c5c67a
commit 80c6c197a7
10 changed files with 750 additions and 64 deletions

View File

@ -216,6 +216,11 @@
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j-core</artifactId>
<version>1.4-dev-8</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,400 @@
package com.dispose.ability.impl;
import cn.hutool.http.HttpResponse;
import com.dispose.ability.DisposeAbility;
import com.dispose.common.DisposeCapacityType;
import com.dispose.common.DisposeConfigValue;
import com.dispose.common.DisposeObjectType;
import com.dispose.common.ErrorCode;
import com.dispose.common.NetflowDirection;
import com.dispose.pojo.entity.ServiceInfo;
import com.dispose.pojo.po.MulReturnType;
import com.dispose.pojo.vo.DeviceFirewareInfo;
import com.dispose.security.arithmetic.CryptoHelper;
import com.huaweifirewall.dispose.common.HuaWeiFireWallCreatePolicyReq;
import com.huaweifirewall.dispose.protocol.HuaWeiFireWallInterface;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressString;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author Nicole
*/
@Slf4j
public class HuaWeiFireWallAbilityImpl implements DisposeAbility {
/**
* The Restful interface.
*/
private final HuaWeiFireWallInterface restfulInterface = new HuaWeiFireWallInterface();
/**
* The policy name prefix.
*/
private static final String POLICY_NAME_PREFIX = "C_";
/**
* The Timer cnt.
*/
private long timerCnt = 0;
/**
* The Device link status.
*/
private boolean deviceLinkStatus = false;
/**
* The Url root path.
*/
@Getter
@Setter
private String urlRootPath;
/**
* The Username.
*/
@Getter
@Setter
private String username;
/**
* The Password.
*/
@Getter
@Setter
private String password;
/**
* The Token.
*/
private String token;
/**
* Init device env.
*
* @param urlPath the url path
* @param username the username
* @param password the password
*/
@Override
public void initDeviceEnv(String urlPath, String username, String password) {
this.urlRootPath = urlPath;
this.username = username;
this.password = password;
upgradeToken();
}
/**
* Run dispose mul return type.
*
* @param disposeObject the dispose object
* @param objectType the object type
* @param capType the cap type
* @param nfDirection the nf direction
* @param attackType the attack type
* @param duration the duration
* @return the mul return type
*/
@Override
public MulReturnType<ErrorCode, String> runDispose(String disposeObject, DisposeObjectType objectType, DisposeCapacityType capType,
@Nullable NetflowDirection nfDirection, @Nullable Integer attackType, @Nullable Long duration) {
//调用创建安全策略规则的接口
String name = "/vsys=public/static-policy/rule=" + getPolicyName(disposeObject);
String url = urlRootPath + name;
String disposeObj = null;
IPAddress addr = new IPAddressString(disposeObject).getAddress();
if (addr.isIPv4()) {
disposeObj = disposeObject + "/32";
}
if (token == null || token.length() == 0) {
return new MulReturnType<>(ErrorCode.ERR_LOGOUT, "");
}
HuaWeiFireWallCreatePolicyReq policyReq = HuaWeiFireWallCreatePolicyReq.builder()
.sourceIp(disposeObj).action(false).build();
try {
log.info("++++Begging HuaWei FireWall Start Cleanup Task: {}", disposeObject);
//华为防火墙目前只提供封堵功能
if (capType != DisposeCapacityType.BLACKHOOL) {
log.error("----Error HuaWei FireWall don't support dispose capacity type: {}", capType);
return new MulReturnType<>(ErrorCode.ERR_UNSUPPORT, null);
}
ErrorCode resp = restfulInterface.createSecurityPolicy(url, token, policyReq);
// 判断是否token过期
if (resp == ErrorCode.ERR_TOKENNOTFOUND) {
// 重新登录获取 token
upgradeToken();
resp = restfulInterface.createSecurityPolicy(url, token, policyReq);
}
if (resp == null) {
log.error("----Error HuaWei FireWall start clean {} server return error", disposeObject);
return new MulReturnType<>(ErrorCode.ERR_HUAWEIFIREWALL_ERROR, null);
}
if (resp != ErrorCode.ERR_OK) {
log.error("----Error HuaWei FireWall start clean {} return error: {}, {}", disposeObject,
resp.getCode(), resp.getMsg());
return new MulReturnType<>(ErrorCode.ERR_HUAWEIFIREWALL_ERROR, null);
}
log.info("----Finish HuaWei FireWall Start Cleanup Task: {}", disposeObject);
return new MulReturnType<>(ErrorCode.ERR_OK, null);
} catch (Exception ex) {
log.error("----Exception HuaWei FireWall Start Cleanup Task [{}]: {}, {}, {}, {}, {}", ex.getMessage(),
disposeObject,
nfDirection,
duration, url, token);
return new MulReturnType<>(ErrorCode.ERR_SYSTEMEXCEPTION, null);
}
}
/**
* Stop dispose mul return type.
*
* @param disposeObject the dispose object
* @param capType the cap type
* @param nfDirection the nf direction
* @param attackType the attack type
* @param taskId the task id
* @return the mul return type
*/
@Override
public MulReturnType<ErrorCode, Long> stopDispose(String disposeObject, DisposeCapacityType capType,
@Nullable NetflowDirection nfDirection, @Nullable Integer attackType, @Nullable String taskId) {
//调用删除安全策略规则的接口规则名称通过前缀和IP地址进行拼接
String name = "/vsys=public/static-policy/rule=" + getPolicyName(disposeObject);
String url = urlRootPath + name;
if (token == null || token.length() == 0) {
return new MulReturnType<>(ErrorCode.ERR_LOGOUT, null);
}
try {
log.info("++++Begging HuaWei FireWall Stop Cleanup Task: {}", taskId);
//华为防火墙目前只提供封堵功能
if (capType != DisposeCapacityType.BLACKHOOL) {
log.error("----Error HuaWei FireWall don't support dispose capacity type: {}", capType);
return new MulReturnType<>(ErrorCode.ERR_UNSUPPORT, null);
}
if (taskId == null) {
return new MulReturnType<>(ErrorCode.ERR_PARAMS, null);
}
ErrorCode rspInfo = restfulInterface.deleteSecurityPolicy(url, token);
// 判断是否token过期
if (rspInfo == ErrorCode.ERR_TOKENNOTFOUND) {
// 重新登录获取 token
upgradeToken();
rspInfo = restfulInterface.deleteSecurityPolicy(url, token);
}
if (rspInfo == null) {
log.error("----Error HuaWei FireWall stop task{} server return error", taskId);
return new MulReturnType<>(ErrorCode.ERR_HUAWEIFIREWALL_ERROR, null);
}
if (rspInfo != ErrorCode.ERR_OK) {
log.error("----Error HuaWei FireWall stop task{} server return error", taskId);
return new MulReturnType<>(ErrorCode.ERR_HUAWEIFIREWALL_ERROR, null);
}
log.info("----Finish HuaWei FireWall Stop Cleanup Task: {}", taskId);
return new MulReturnType<>(ErrorCode.ERR_OK, null);
} catch (Exception ex) {
log.error("----Exception HuaWei FireWall Stop Cleanup Task [{}]: {}, {}, {}, {}", ex.getMessage(),
disposeObject,
nfDirection, url, token);
return new MulReturnType<>(ErrorCode.ERR_SYSTEMEXCEPTION, null);
}
}
/**
* Task status mul return type.
*
* @param taskId the task id
* @return the mul return type
*/
@Override
public MulReturnType<ErrorCode, Long> taskStatus(String taskId) {
return null;
}
/**
* Gets ability device fireware.
*
* @return the ability device fireware.
*/
@Override
public MulReturnType<ErrorCode, DeviceFirewareInfo> getAbilityDeviceFireware() {
return new MulReturnType<>(ErrorCode.ERR_OK,
DeviceFirewareInfo.builder()
.vendor("HuaWeiFireWall")
.model("Unknown")
.firmware("Unknown")
.os("Linux Server")
.kernel("Linux")
.arch("x86_64")
.version("Unknown")
.memory(-1)
.freeMemory(-1)
.cpuUsed(-1)
.build());
}
/**
* To device attack type long.
*
* @param ddosAttackTypeMask the ddos attack type mask
* @return the long
*/
@Override
public Long toDeviceAttackType(Long ddosAttackTypeMask) {
return ddosAttackTypeMask;
}
/**
* Gets device link status.
*
* @return the device link status
*/
@Override
public boolean getDeviceLinkStatus() {
return deviceLinkStatus;
}
/**
* Dev get link status.
*/
private void devGetLinkStatus() {
try {
//调用华为防火墙查询所有安全策略规则接口调用成功则认为设备心跳正常
String url = urlRootPath;
if (token == null || token.length() == 0) {
deviceLinkStatus = false;
return;
}
HttpResponse response = restfulInterface.getAllSecurityPolicy(url, token);
if (response.getStatus() == HttpServletResponse.SC_PRECONDITION_FAILED) {
// 重新登录获取 token
upgradeToken();
response = restfulInterface.getAllSecurityPolicy(url, token);
}
if (response.getStatus() == HttpServletResponse.SC_OK) {
deviceLinkStatus = true;
}
return;
} catch (Exception ex) {
log.error(ex.getMessage());
}
deviceLinkStatus = false;
}
/**
* Gets dispose device protect object.
*/
@Override
public void getDisposeDeviceProtectObject() {
}
/**
* Is carry protect ip boolean.
*
* @param ipAddr the ip addr
* @return the boolean
*/
@Override
public boolean isCarryProtectIp(String ipAddr) {
return true;
}
/**
* Is carry attack type boolean.
*
* @param attackType the attack type
* @return the boolean
*/
@Override
public boolean isCarryAttackType(Long attackType) {
return true;
}
/**
* Period task runtime.
*/
@Override
public void periodTaskRuntime() {
log.debug("++++HuaWei FireWall Period Task Running");
// 更新心跳状态
if (timerCnt++ % DisposeConfigValue.HEART_PERIOD_OF_SECOND == 0) {
devGetLinkStatus();
}
log.debug("----HuaWei FireWall Period Task Running");
}
/**
* Device ready boolean.
*
* @return the boolean
*/
@Override
public boolean deviceReady() {
return true;
}
/**
* Upgrade service group.
*
* @param svrList the svr list
*/
@Override
public void upgradeServiceGroup(List<ServiceInfo> svrList) {
}
/**
* Upgrade token.
*/
private void upgradeToken() {
try {
//由用户名密码的base64计算得到用户名密码格式用户名:密码
String plainText = username + ":" + password;
this.token = CryptoHelper.base64Encryption(plainText.getBytes(StandardCharsets.UTF_8));
} catch (Exception ignored) {
}
}
/**
* Gets policy name.
*
* @param sourceIp the source Ip
* @return the policy name
*/
private String getPolicyName(String sourceIp) {
return POLICY_NAME_PREFIX + sourceIp;
}
}

View File

@ -11,6 +11,10 @@ public class ConstValue {
* The constant STRING_HTTP_AUTH_HEAD.
*/
public static final String STRING_HTTP_AUTH_HEAD = "Bearer ";
/**
* The constant HUAWEI_FIREWALL_HTTP_AUTH_HEAD.
*/
public static final String HUAWEI_FIREWALL_HTTP_AUTH_HEAD = "Basic ";
/**
* The constant IP_ADDR_REG.

View File

@ -26,6 +26,10 @@ public enum DisposeDeviceType implements BaseEnum {
* Dptech bypass umc dispose device type.
*/
DPTECH_BYPASS_UMC(4, "迪普旁路牵引UMC管理平台"),
/**
* The Huawei FireWall platform.
*/
HUAWEI_FIREWALL_PLATFORM(5, "华为防火墙"),
/**
* The Virtual dispose.
*/

View File

@ -286,6 +286,10 @@ public enum ErrorCode {
* Err not found device error code.
*/
ERR_NOTFOUNDDEVICE(304, "找不到设备先添加设备"),
/**
* The Err huawei firewall error.
*/
ERR_HUAWEIFIREWALL_ERROR(305, "华为防火墙返回错误"),
;
/**

View File

@ -102,6 +102,43 @@ public class RestfulInterface {
.execute();
}
/**
* Gets json.
*
* @param url the url
* @param header the header
* @return the http response
*/
private static HttpResponse huaweiFireWallGetJson(String url, Map<String, String> header) {
HttpRequest.setGlobalTimeout(timeOutValue);
return HttpRequest.get(url).addHeaders(header).execute();
}
/**
* Post json.
*
* @param url the url
* @param header the header
* @param body the body
* @return the http response
*/
private static HttpResponse huaweiFireWallPostJson(String url, Map<String, String> header, String body) {
HttpRequest.setGlobalTimeout(timeOutValue);
return HttpRequest.post(url).addHeaders(header).body(body).execute();
}
/**
* Deletes http response.
*
* @param url the url
* @param header the header
* @return the http response
*/
private static HttpResponse huaweiFireWallDeleteJson(String url, Map<String, String> header, String body) {
HttpRequest.setGlobalTimeout(timeOutValue);
return HttpRequest.delete(url).addHeaders(header).body(body).execute();
}
/**
* Protocol run t.
*
@ -258,6 +295,63 @@ public class RestfulInterface {
}
}
/**
* huawei firewall pro run protocol resp dto.
*
* @param url the url
* @param token the token
* @param reqBody the obj
* @param reqType the req type
* @return the t
*/
public static HttpResponse huaWeiFireWallProRun(String url, String token, String reqBody, RequestMethod reqType) {
String body = "";
HttpResponse svrResp = null;
//HTTP请求头格式
Map<String, String> httpHeadMap = new HashMap<>(2);
httpHeadMap.put(String.valueOf(Header.CONNECTION), "keep-alive");
httpHeadMap.put(String.valueOf(Header.ACCEPT), "application/yang.operation+xml");
if (token != null && token.length() > 0) {
httpHeadMap.put(String.valueOf(Header.AUTHORIZATION), ConstValue.HUAWEI_FIREWALL_HTTP_AUTH_HEAD + token);
}
//实际数据长度没有数据部分时值为0
httpHeadMap.put(String.valueOf(Header.CONTENT_LENGTH), body.equals(reqBody) ? String.valueOf(0) : String.valueOf(reqBody.length()));
//HTTP请求提交的内容类型只有在POST方法提交时才需要设置此属性 && body内容为空时该字段可不存在或取值为空
if ((!body.equals(reqBody)) && RequestMethod.POST.equals(reqType)) {
httpHeadMap.put(String.valueOf(Header.CONTENT_TYPE), "application/yang.operation+xml");
}
log.debug("Restful request: {}, {}: {}", url, token, reqBody);
switch (reqType) {
case GET:
svrResp = huaweiFireWallGetJson(url, httpHeadMap);
break;
case POST:
svrResp = huaweiFireWallPostJson(url, httpHeadMap, reqBody);
break;
case DELETE:
svrResp = huaweiFireWallDeleteJson(url, httpHeadMap, reqBody);
break;
default:
log.error("Unknown method: {}", reqType);
break;
}
if (svrResp == null) {
log.debug("Server return null: {}", url);
return null;
}
log.debug("Restful response: {}, {}: {}", url, token, svrResp.body());
return svrResp;
}
/**
* Create resp type type.
*

View File

@ -584,6 +584,10 @@ public class DeviceTaskManagerServiceImpl implements DeviceTaskManagerService {
restfulDeviceTaskRun(ai, v, task, DisposeDeviceType.HUAWEI_PLATFORM);
break;
case HUAWEI_FIREWALL_PLATFORM:
restfulDeviceTaskRun(ai, v, task, DisposeDeviceType.HUAWEI_FIREWALL_PLATFORM);
break;
default:
log.error("Unknown dispose device type: {}", ai.getDev());
break;
@ -661,6 +665,10 @@ public class DeviceTaskManagerServiceImpl implements DeviceTaskManagerService {
restfulDeviceTaskStop(ai, v, task, DisposeDeviceType.HUAWEI_PLATFORM);
break;
case HUAWEI_FIREWALL_PLATFORM:
restfulDeviceTaskStop(ai, v, task, DisposeDeviceType.HUAWEI_FIREWALL_PLATFORM);
break;
default:
log.error("Unknown dispose device type: {}", ai.getDev());
break;

View File

@ -5,6 +5,7 @@ import com.dispose.ability.impl.DpTechAbilityImpl;
import com.dispose.ability.impl.DpTechBypassAbilityImpl;
import com.dispose.ability.impl.HaoHanAbilityImpl;
import com.dispose.ability.impl.HuaWeiAbilityImpl;
import com.dispose.ability.impl.HuaWeiFireWallAbilityImpl;
import com.dispose.ability.impl.PengXinAbilityImpl;
import com.dispose.ability.impl.VirtualAbilityImpl;
import com.dispose.common.DisposeCapacityType;
@ -168,6 +169,9 @@ public class DisposeAbilityRouterServiceImpl implements DisposeAbilityRouterServ
db = new DpTechBypassAbilityImpl();
db.upgradeServiceGroup(serviceGroupMapper.selectAll());
break;
case HUAWEI_FIREWALL_PLATFORM:
db = new HuaWeiFireWallAbilityImpl();
break;
default:
log.error("Unknown dispose device type: {}", dev.getDeviceType());
return ErrorCode.ERR_PARAMS;

View File

@ -0,0 +1,28 @@
package com.huaweifirewall.dispose.common;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Nicole
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonPropertyOrder({"sourceIp", "action"})
@JsonInclude(JsonInclude.Include.NON_NULL)
public class HuaWeiFireWallCreatePolicyReq {
/**
* The source Ip.
*/
private String sourceIp;
/**
* The rule action. false:block true:unblock
*/
private Boolean action;
}

View File

@ -0,0 +1,135 @@
package com.huaweifirewall.dispose.protocol;
import cn.hutool.http.HttpResponse;
import com.dispose.common.ErrorCode;
import com.dispose.restful.RestfulInterface;
import com.huaweifirewall.dispose.common.HuaWeiFireWallCreatePolicyReq;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
/**
* The type Hua wei FireWall interface.
*
* @author Nicole
*/
@Slf4j
public class HuaWeiFireWallInterface {
/**
* Create security policy.
*
* @param baseUrlPath the base url path
* @param token the token
* @param policyReq the request dto
* @return the error code
*/
public ErrorCode createSecurityPolicy(String baseUrlPath, String token, HuaWeiFireWallCreatePolicyReq policyReq) {
//拼接HTTP body部分xml格式
String bodyContent = createXml(policyReq.getSourceIp(), policyReq.getAction());
//获取HTTP RESPONSE消息
HttpResponse response = RestfulInterface.huaWeiFireWallProRun(baseUrlPath,
token,
bodyContent,
RequestMethod.POST);
//对响应内容进行处理
if (response != null) {
if (response.getStatus() == HttpServletResponse.SC_CREATED) {
return ErrorCode.ERR_OK;
}
}
log.error("----HuaWei response [{}]: {}", response == null ? -1 : response.getStatus(), response);
return ErrorCode.ERR_UNKNOWNCMD;
}
/**
* delete security policy.
*
* @param baseUrlPath the base url path
* @param token the token
* @return the error code
*/
public ErrorCode deleteSecurityPolicy(String baseUrlPath, String token) {
HttpResponse response = RestfulInterface.huaWeiFireWallProRun(baseUrlPath,
token,
"",
RequestMethod.DELETE);
//对响应内容进行处理
if (response != null) {
if (response.getStatus() == HttpServletResponse.SC_CREATED) {
return ErrorCode.ERR_OK;
}
}
log.error("----HuaWei response [{}]: {}", response == null ? -1 : response.getStatus(), response);
return ErrorCode.ERR_UNKNOWNCMD;
}
/**
* get all security policy.
*
* @param baseUrlPath the base url path
* @param token the token
* @return the error code
*/
public HttpResponse getAllSecurityPolicy(String baseUrlPath, String token) {
return RestfulInterface.huaWeiFireWallProRun(baseUrlPath,
token,
"",
RequestMethod.GET);
}
/**
* 生成xml方法
*
* @param sourceIp the source ip
* @param ruleAction the rule action
* @return the error code
*/
public static String createXml(String sourceIp, Boolean ruleAction) {
try {
// 创建document对象
Document document = DocumentHelper.createDocument();
// 创建根节点rule
Element rule = document.addElement("rule");
// 生成子节点及子节点内容
Element addressIpv4 = rule.addElement("address-ipv4");
addressIpv4.setText(sourceIp);
Element action = rule.addElement("action");
action.setText(String.valueOf(ruleAction));
// 设置生成xml的格式
OutputFormat format = OutputFormat.createPrettyPrint();
// 设置编码格式
format.setEncoding("UTF-8");
// 生成xml文件
File file = new File("policyRule.xml");
XMLWriter writer = new XMLWriter(new FileOutputStream(file), format);
// 设置是否转义默认使用转义字符
writer.setEscapeText(false);
writer.write(document);
writer.close();
System.out.println("生成policyRule.xml成功");
return document.asXML();
} catch (Exception e) {
e.printStackTrace();
System.out.println("生成policyRule.xml失败");
}
return null;
}
}