in pkg/skoop/network/aliyun/assertion.go [43:188]
func (a *vpcAssertion) AssertSecurityGroup(srcECS, dstECS string, pkt *model.Packet) ([]model.Suspicion, error) {
if srcECS == "" && dstECS == "" {
return nil, nil
}
var suspicions []model.Suspicion
if srcECS != "" && dstECS != "" {
srcECSInfo, err := a.cloudManager.GetECSInfo(srcECS)
if err != nil {
return nil, err
}
dstECSInfo, err := a.cloudManager.GetECSInfo(dstECS)
if err != nil {
return nil, err
}
var srcECSSecurityGroup map[string]aliyun.SecurityGroupRule
srcENI := a.getENIFromIP(srcECSInfo, pkt.Src.String())
if srcENI != nil {
srcECSSecurityGroup = srcENI.SecurityGroups
} else {
srcECSSecurityGroup = srcECSInfo.Network.SecurityGroups
}
var dstECSSecurityGroup map[string]aliyun.SecurityGroupRule
dstENI := a.getENIFromIP(dstECSInfo, pkt.Dst.String())
if dstENI != nil {
dstECSSecurityGroup = dstENI.SecurityGroups
} else {
dstECSSecurityGroup = dstECSInfo.Network.SecurityGroups
}
sgIntersection := a.intersection(srcECSSecurityGroup, dstECSSecurityGroup)
if len(sgIntersection) == 0 {
suspicions = append(suspicions, model.Suspicion{
Level: model.SuspicionLevelWarning,
Message: fmt.Sprintf("%s(%s) and %s(%s) do not have same security group",
srcECS, a.getECSIP(srcECSInfo), dstECS, a.getECSIP(dstECSInfo)),
})
}
// eni 只能绑定一个类型sg
// sg 相交场景,且相交的是普通安全组,默认策略为 Allow
// sg 相交场景,且为企业安全组,默认策略 Deny
// sg 不相交,默认 Deny
sgPolicyVerdict := securityPolicyVerdictDrop
if len(sgIntersection) > 0 {
if sgIntersection[0].Type == aliyun.SecurityGroupTypeNormal {
sgPolicyVerdict = securityPolicyVerdictAccept
}
checkResult, err := a.checkSourceOut(pkt, srcECSSecurityGroup)
if err != nil {
return nil, err
}
if !checkResult {
sgIDs := lo.MapToSlice(srcECSSecurityGroup,
func(id string, _ aliyun.SecurityGroupRule) string { return id })
suspicions = append(suspicions, model.Suspicion{
Level: model.SuspicionLevelFatal,
Message: fmt.Sprintf("%s(%s) security group %v not allow packet to %s:%d",
srcECS, a.getECSIP(srcECSInfo), sgIDs, pkt.Dst.String(), pkt.Dport),
})
}
if !slices.Contains(srcECSInfo.Network.IP, pkt.Src.String()) || len(sgIntersection) == 0 ||
(len(sgIntersection) > 0 && srcECSSecurityGroup[sgIntersection[0].ID].Type == "enterprise") {
checkResult, err := a.checkDestinationIn(pkt, dstECSSecurityGroup, sgPolicyVerdict)
if err != nil {
return nil, err
}
if !checkResult {
sgIDs := lo.MapToSlice(dstECSSecurityGroup,
func(id string, _ aliyun.SecurityGroupRule) string { return id })
suspicions = append(suspicions, model.Suspicion{
Level: model.SuspicionLevelFatal,
Message: fmt.Sprintf("%s(%s) security group %v not allow packet from %s to port %d",
dstECS, a.getECSIP(dstECSInfo), sgIDs, pkt.Src.String(), pkt.Dport),
})
}
}
}
} else if srcECS != "" && dstECS == "" {
srcECSInfo, err := a.cloudManager.GetECSInfo(srcECS)
if err != nil {
return nil, err
}
srcENI := a.getENIFromIP(srcECSInfo, pkt.Src.String())
var srcECSSecurityGroup map[string]aliyun.SecurityGroupRule
if srcENI == nil {
srcECSSecurityGroup = srcECSInfo.Network.SecurityGroups
} else {
srcECSSecurityGroup = srcENI.SecurityGroups
}
checkResult, err := a.checkSourceOut(pkt, srcECSSecurityGroup)
if err != nil {
return nil, err
}
if !checkResult {
sgIDs := lo.Keys(srcECSSecurityGroup)
suspicions = append(suspicions, model.Suspicion{
Level: model.SuspicionLevelFatal,
Message: fmt.Sprintf("%s(%s) security group %v not allow packet from to %s:%d",
srcECS, a.getECSIP(srcECSInfo), sgIDs, pkt.Dst.String(), pkt.Dport),
})
}
} else if srcECS == "" && dstECS != "" {
dstECSInfo, err := a.cloudManager.GetECSInfo(dstECS)
if err != nil {
return nil, err
}
dstENI := a.getENIFromIP(dstECSInfo, pkt.Dst.String())
var dstECSSecurityGroup map[string]aliyun.SecurityGroupRule
if dstENI == nil {
dstECSSecurityGroup = dstECSInfo.Network.SecurityGroups
} else {
dstECSSecurityGroup = dstENI.SecurityGroups
}
sgs := lo.Values(dstECSSecurityGroup)
if len(sgs) > 0 {
sgPolicyVerdict := securityPolicyVerdictDrop
checkResult, err := a.checkDestinationIn(pkt, dstECSSecurityGroup, sgPolicyVerdict)
if err != nil {
return nil, err
}
if !checkResult {
sgIDs := lo.MapToSlice(dstECSSecurityGroup,
func(id string, _ aliyun.SecurityGroupRule) string { return id })
suspicions = append(suspicions, model.Suspicion{
Level: model.SuspicionLevelFatal,
Message: fmt.Sprintf("%s(%s) security group %v not allow packet from %s to port %d",
dstECS, a.getECSIP(dstECSInfo), sgIDs, pkt.Src.String(), pkt.Dport),
})
}
}
}
return suspicions, nil
}