func()

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
}