github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/applicationproxy/tcp/lookup.go (about)

     1  package tcp
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"strconv"
     7  
     8  	"go.aporeto.io/enforcerd/trireme-lib/collector"
     9  	"go.aporeto.io/enforcerd/trireme-lib/controller/constants"
    10  	"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/packet"
    11  	"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/pucontext"
    12  	"go.aporeto.io/enforcerd/trireme-lib/policy"
    13  	"go.uber.org/zap"
    14  )
    15  
    16  const indeterminateRemoteController = ""
    17  
    18  // proxyFlowProperties is a struct used to pass flow information up
    19  type proxyFlowProperties struct {
    20  	myControllerID string
    21  	SourceIP       string
    22  	DestIP         string
    23  	PolicyID       string
    24  	ServiceID      string
    25  	DestType       collector.EndPointType
    26  	SourceType     collector.EndPointType
    27  	SourcePort     uint16
    28  	DestPort       uint16
    29  }
    30  
    31  type lookup struct {
    32  	SourceIP   net.IP
    33  	DestIP     net.IP
    34  	SourcePort uint16
    35  	DestPort   uint16
    36  	collector  collector.EventCollector
    37  	puContext  *pucontext.PUContext
    38  	pfp        *proxyFlowProperties
    39  	client     bool
    40  }
    41  
    42  // IDLookup performs policy lookup based on incoming tags from remote PU and matching against our policy DB.
    43  // Stats reporting is done for:
    44  //   - all rejects
    45  //   - accepts on server
    46  func (l *lookup) IDLookup(remoteController, remotePUID string, tags *policy.TagStore) bool { // nolint: staticcheck
    47  
    48  	remoteController = ""
    49  	// TODO: Enable this
    50  	// if remoteController == l.pfp.myControllerID {
    51  	// 	remoteController = ""
    52  	// }
    53  
    54  	report, packet := l.Policy(tags)
    55  
    56  	if packet.Action.Rejected() {
    57  		l.ReportStats(
    58  			collector.EndPointTypePU,
    59  			remoteController,
    60  			remotePUID,
    61  			collector.PolicyDrop,
    62  			report,
    63  			packet,
    64  			false,
    65  		)
    66  		zap.L().Debug("lookup reject", zap.Bool("client", l.client), zap.Strings("tags", tags.GetSlice()))
    67  		return false
    68  	}
    69  
    70  	if !l.client && packet.Action.Accepted() {
    71  		l.ReportStats(
    72  			collector.EndPointTypePU,
    73  			remoteController,
    74  			remotePUID,
    75  			"N/A",
    76  			report,
    77  			packet,
    78  			false,
    79  		)
    80  		zap.L().Debug("lookup accept", zap.Bool("client", l.client), zap.Strings("tags", tags.GetSlice()))
    81  	}
    82  	return true
    83  }
    84  
    85  // Policy performs policy lookup based on incoming tags from remote PU and matching against our policy DB.
    86  // It also returns the report and packet policy.
    87  func (l *lookup) Policy(tags *policy.TagStore) (*policy.FlowPolicy, *policy.FlowPolicy) {
    88  
    89  	var report *policy.FlowPolicy
    90  	var packet *policy.FlowPolicy
    91  
    92  	if l.client {
    93  		tags.AppendKeyValue(constants.PortNumberLabelString, fmt.Sprintf("%s/%s", constants.TCPProtoString, strconv.Itoa(int(l.DestPort))))
    94  		report, packet = l.puContext.SearchTxtRules(tags, false)
    95  	} else {
    96  		tags.AppendKeyValue(constants.PortNumberLabelString, fmt.Sprintf("%s/%s", constants.TCPProtoString, strconv.Itoa(int(l.DestPort))))
    97  		report, packet = l.puContext.SearchRcvRules(tags)
    98  	}
    99  
   100  	return report, packet
   101  }
   102  
   103  func (l *lookup) IPLookup() bool {
   104  
   105  	var report *policy.FlowPolicy
   106  	var packetPolicy *policy.FlowPolicy
   107  	var noPolicy error
   108  
   109  	if l.client {
   110  		report, packetPolicy, noPolicy = l.puContext.ApplicationACLPolicyFromAddr(l.DestIP, l.DestPort, packet.IPProtocolTCP)
   111  	} else {
   112  		report, packetPolicy, noPolicy = l.puContext.NetworkACLPolicyFromAddr(l.SourceIP, l.DestPort, packet.IPProtocolTCP)
   113  	}
   114  
   115  	matchString := "none"
   116  	if noPolicy != nil {
   117  		matchString = noPolicy.Error()
   118  	}
   119  
   120  	// Clients and Servers should reject and report if a reject action is found.
   121  	if packetPolicy.Action.Rejected() {
   122  
   123  		l.ReportStats(
   124  			collector.EndPointTypeExternalIP,
   125  			indeterminateRemoteController,
   126  			packetPolicy.ServiceID,
   127  			collector.PolicyDrop,
   128  			report,
   129  			packetPolicy,
   130  			false,
   131  		)
   132  		zap.L().Debug(
   133  			"IP ACL Lookup Reject",
   134  			zap.Bool("client", l.client),
   135  			zap.String("match", matchString),
   136  			zap.String("src-ip", l.pfp.SourceIP),
   137  			zap.Uint16("src-port", l.SourcePort),
   138  			zap.String("dst-ip", l.pfp.DestIP),
   139  			zap.Uint16("dst-port", l.DestPort),
   140  			zap.String("report", report.PolicyID),
   141  			zap.String("policy", packetPolicy.PolicyID))
   142  		return false
   143  	}
   144  
   145  	if !l.client && packetPolicy.Action.Accepted() {
   146  		l.ReportStats(
   147  			collector.EndPointTypeExternalIP,
   148  			indeterminateRemoteController,
   149  			packetPolicy.ServiceID,
   150  			"N/A",
   151  			report,
   152  			packetPolicy,
   153  			false,
   154  		)
   155  	}
   156  	zap.L().Debug(
   157  		"IP ACL Lookup Accept",
   158  		zap.Bool("client", l.client),
   159  		zap.String("match", matchString),
   160  		zap.String("src-ip", l.pfp.SourceIP),
   161  		zap.Uint16("src-port", l.SourcePort),
   162  		zap.String("dst-ip", l.pfp.DestIP),
   163  		zap.Uint16("dst-port", l.DestPort),
   164  		zap.String("report", report.PolicyID),
   165  		zap.String("policy", packetPolicy.PolicyID))
   166  	return true
   167  }
   168  
   169  func (l *lookup) ReportStats(remoteType collector.EndPointType, remoteController string, remotePUID string, mode string, report *policy.FlowPolicy, packet *policy.FlowPolicy, accept bool) {
   170  
   171  	dstController, dstID, srcController, srcID := "", "", "", ""
   172  
   173  	if l.client {
   174  		l.pfp.DestType = remoteType
   175  		if l.pfp.myControllerID != remoteController {
   176  			dstController = remoteController
   177  		}
   178  		dstID = remotePUID
   179  		srcID = l.puContext.ManagementID()
   180  	} else {
   181  		l.pfp.SourceType = remoteType
   182  		dstID = l.puContext.ManagementID()
   183  		if l.pfp.myControllerID != remoteController {
   184  			srcController = remoteController
   185  		}
   186  		srcID = remotePUID
   187  	}
   188  
   189  	if accept {
   190  		l.reportAcceptedFlow(
   191  			l.pfp,
   192  			srcID,
   193  			dstID,
   194  			l.puContext,
   195  			report,
   196  			packet,
   197  			srcController,
   198  			dstController,
   199  		)
   200  		return
   201  	}
   202  
   203  	l.reportRejectedFlow(
   204  		l.pfp,
   205  		srcID,
   206  		dstID,
   207  		l.puContext,
   208  		mode,
   209  		report,
   210  		packet,
   211  		srcController,
   212  		dstController,
   213  	)
   214  }
   215  
   216  func (l *lookup) reportFlow(flowproperties *proxyFlowProperties, sourceID string, destID string, context *pucontext.PUContext, mode string, report *policy.FlowPolicy, actual *policy.FlowPolicy, sourceController string, destController string) {
   217  
   218  	c := &collector.FlowRecord{
   219  		ContextID: context.ID(),
   220  		Source: collector.EndPoint{
   221  			ID:   sourceID,
   222  			IP:   flowproperties.SourceIP,
   223  			Port: flowproperties.SourcePort,
   224  			Type: flowproperties.SourceType,
   225  		},
   226  		Destination: collector.EndPoint{
   227  			ID:   destID,
   228  			IP:   flowproperties.DestIP,
   229  			Port: flowproperties.DestPort,
   230  			Type: flowproperties.DestType,
   231  		},
   232  
   233  		Action:                actual.Action,
   234  		DropReason:            mode,
   235  		PolicyID:              actual.PolicyID,
   236  		L4Protocol:            packet.IPProtocolTCP,
   237  		ServiceType:           policy.ServiceTCP,
   238  		ServiceID:             flowproperties.ServiceID,
   239  		Namespace:             context.ManagementNamespace(),
   240  		SourceController:      sourceController,
   241  		DestinationController: destController,
   242  	}
   243  
   244  	if context.Annotations() != nil {
   245  		c.Tags = context.Annotations().GetSlice()
   246  	}
   247  
   248  	if report.ObserveAction.Observed() {
   249  		c.ObservedAction = report.Action
   250  		c.ObservedPolicyID = report.PolicyID
   251  		c.ObservedActionType = report.ObserveAction
   252  	}
   253  
   254  	l.collector.CollectFlowEvent(c)
   255  }
   256  
   257  func (l *lookup) reportAcceptedFlow(flowproperties *proxyFlowProperties, sourceID string, destID string, context *pucontext.PUContext, report *policy.FlowPolicy, packet *policy.FlowPolicy, sourceController string, destController string) {
   258  
   259  	l.reportFlow(flowproperties, sourceID, destID, context, "N/A", report, packet, sourceController, destController)
   260  }
   261  
   262  func (l *lookup) reportRejectedFlow(flowproperties *proxyFlowProperties, sourceID string, destID string, context *pucontext.PUContext, mode string, report *policy.FlowPolicy, packet *policy.FlowPolicy, sourceController string, destController string) {
   263  
   264  	if report == nil {
   265  		report = &policy.FlowPolicy{
   266  			Action:   policy.Reject | policy.Log,
   267  			PolicyID: "default",
   268  		}
   269  	}
   270  	if packet == nil {
   271  		packet = report
   272  	}
   273  	l.reportFlow(flowproperties, sourceID, destID, context, mode, report, packet, sourceController, destController)
   274  }