github.com/prebid/prebid-server/v2@v2.18.0/privacy/scrubber.go (about)

     1  package privacy
     2  
     3  import (
     4  	"encoding/json"
     5  	"net"
     6  
     7  	"github.com/prebid/prebid-server/v2/util/jsonutil"
     8  
     9  	"github.com/prebid/openrtb/v20/openrtb2"
    10  	"github.com/prebid/prebid-server/v2/config"
    11  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    12  	"github.com/prebid/prebid-server/v2/util/iputil"
    13  )
    14  
    15  type IPConf struct {
    16  	IPV6 config.IPv6
    17  	IPV4 config.IPv4
    18  }
    19  
    20  func scrubDeviceIDs(reqWrapper *openrtb_ext.RequestWrapper) {
    21  	if reqWrapper.Device != nil {
    22  		reqWrapper.Device.DIDMD5 = ""
    23  		reqWrapper.Device.DIDSHA1 = ""
    24  		reqWrapper.Device.DPIDMD5 = ""
    25  		reqWrapper.Device.DPIDSHA1 = ""
    26  		reqWrapper.Device.IFA = ""
    27  		reqWrapper.Device.MACMD5 = ""
    28  		reqWrapper.Device.MACSHA1 = ""
    29  	}
    30  }
    31  
    32  func scrubUserIDs(reqWrapper *openrtb_ext.RequestWrapper) {
    33  	if reqWrapper.User != nil {
    34  		reqWrapper.User.Data = nil
    35  		reqWrapper.User.ID = ""
    36  		reqWrapper.User.BuyerUID = ""
    37  		reqWrapper.User.Yob = 0
    38  		reqWrapper.User.Gender = ""
    39  		reqWrapper.User.Keywords = ""
    40  		reqWrapper.User.KwArray = nil
    41  	}
    42  }
    43  
    44  func scrubUserDemographics(reqWrapper *openrtb_ext.RequestWrapper) {
    45  	if reqWrapper.User != nil {
    46  		reqWrapper.User.BuyerUID = ""
    47  		reqWrapper.User.ID = ""
    48  		reqWrapper.User.Yob = 0
    49  		reqWrapper.User.Gender = ""
    50  	}
    51  }
    52  
    53  func scrubUserExt(reqWrapper *openrtb_ext.RequestWrapper, fieldName string) error {
    54  	if reqWrapper.User != nil {
    55  		userExt, err := reqWrapper.GetUserExt()
    56  		if err != nil {
    57  			return err
    58  		}
    59  		ext := userExt.GetExt()
    60  		_, hasField := ext[fieldName]
    61  		if hasField {
    62  			delete(ext, fieldName)
    63  			userExt.SetExt(ext)
    64  		}
    65  	}
    66  	return nil
    67  }
    68  
    69  func ScrubEIDs(reqWrapper *openrtb_ext.RequestWrapper) error {
    70  	//transmitEids removes user.eids and user.ext.eids
    71  	if reqWrapper.User != nil {
    72  		reqWrapper.User.EIDs = nil
    73  	}
    74  	return scrubUserExt(reqWrapper, "eids")
    75  }
    76  
    77  func ScrubTID(reqWrapper *openrtb_ext.RequestWrapper) {
    78  	if reqWrapper.Source != nil {
    79  		reqWrapper.Source.TID = ""
    80  	}
    81  	impWrapper := reqWrapper.GetImp()
    82  	for ind, imp := range impWrapper {
    83  		impExt := scrubExtIDs(imp.Ext, "tid")
    84  		impWrapper[ind].Ext = impExt
    85  	}
    86  	reqWrapper.SetImp(impWrapper)
    87  }
    88  
    89  func scrubGEO(reqWrapper *openrtb_ext.RequestWrapper) {
    90  	//round user's geographic location by rounding off IP address and lat/lng data.
    91  	//this applies to both device.geo and user.geo
    92  	if reqWrapper.User != nil && reqWrapper.User.Geo != nil {
    93  		reqWrapper.User.Geo = scrubGeoPrecision(reqWrapper.User.Geo)
    94  	}
    95  
    96  	if reqWrapper.Device != nil && reqWrapper.Device.Geo != nil {
    97  		reqWrapper.Device.Geo = scrubGeoPrecision(reqWrapper.Device.Geo)
    98  	}
    99  }
   100  
   101  func scrubGeoFull(reqWrapper *openrtb_ext.RequestWrapper) {
   102  	if reqWrapper.User != nil && reqWrapper.User.Geo != nil {
   103  		reqWrapper.User.Geo = &openrtb2.Geo{}
   104  	}
   105  	if reqWrapper.Device != nil && reqWrapper.Device.Geo != nil {
   106  		reqWrapper.Device.Geo = &openrtb2.Geo{}
   107  	}
   108  
   109  }
   110  
   111  func scrubDeviceIP(reqWrapper *openrtb_ext.RequestWrapper, ipConf IPConf) {
   112  	if reqWrapper.Device != nil {
   113  		reqWrapper.Device.IP = scrubIP(reqWrapper.Device.IP, ipConf.IPV4.AnonKeepBits, iputil.IPv4BitSize)
   114  		reqWrapper.Device.IPv6 = scrubIP(reqWrapper.Device.IPv6, ipConf.IPV6.AnonKeepBits, iputil.IPv6BitSize)
   115  	}
   116  }
   117  
   118  func ScrubDeviceIDsIPsUserDemoExt(reqWrapper *openrtb_ext.RequestWrapper, ipConf IPConf, fieldName string, scrubFullGeo bool) {
   119  	scrubDeviceIDs(reqWrapper)
   120  	scrubDeviceIP(reqWrapper, ipConf)
   121  	scrubUserDemographics(reqWrapper)
   122  	scrubUserExt(reqWrapper, fieldName)
   123  
   124  	if scrubFullGeo {
   125  		scrubGeoFull(reqWrapper)
   126  	} else {
   127  		scrubGEO(reqWrapper)
   128  	}
   129  }
   130  
   131  func ScrubUserFPD(reqWrapper *openrtb_ext.RequestWrapper) {
   132  	scrubDeviceIDs(reqWrapper)
   133  	scrubUserIDs(reqWrapper)
   134  	scrubUserExt(reqWrapper, "data")
   135  	reqWrapper.User.EIDs = nil
   136  }
   137  
   138  func ScrubGdprID(reqWrapper *openrtb_ext.RequestWrapper) {
   139  	scrubDeviceIDs(reqWrapper)
   140  	scrubUserDemographics(reqWrapper)
   141  	scrubUserExt(reqWrapper, "eids")
   142  }
   143  
   144  func ScrubGeoAndDeviceIP(reqWrapper *openrtb_ext.RequestWrapper, ipConf IPConf) {
   145  	scrubDeviceIP(reqWrapper, ipConf)
   146  	scrubGEO(reqWrapper)
   147  }
   148  
   149  func scrubIP(ip string, ones, bits int) string {
   150  	if ip == "" {
   151  		return ""
   152  	}
   153  	ipMask := net.CIDRMask(ones, bits)
   154  	ipMasked := net.ParseIP(ip).Mask(ipMask)
   155  	return ipMasked.String()
   156  }
   157  
   158  func scrubGeoPrecision(geo *openrtb2.Geo) *openrtb2.Geo {
   159  	if geo == nil {
   160  		return nil
   161  	}
   162  
   163  	geoCopy := *geo
   164  
   165  	if geoCopy.Lat != nil {
   166  		lat := *geo.Lat
   167  		lat = float64(int(lat*100.0+0.5)) / 100.0
   168  		geoCopy.Lat = &lat
   169  	}
   170  
   171  	if geoCopy.Lon != nil {
   172  		lon := *geo.Lon
   173  		lon = float64(int(lon*100.0+0.5)) / 100.0
   174  		geoCopy.Lon = &lon
   175  	}
   176  
   177  	return &geoCopy
   178  }
   179  
   180  func scrubExtIDs(ext json.RawMessage, fieldName string) json.RawMessage {
   181  	if len(ext) == 0 {
   182  		return ext
   183  	}
   184  
   185  	var userExtParsed map[string]json.RawMessage
   186  	err := jsonutil.Unmarshal(ext, &userExtParsed)
   187  	if err != nil {
   188  		return ext
   189  	}
   190  
   191  	_, hasField := userExtParsed[fieldName]
   192  	if hasField {
   193  		delete(userExtParsed, fieldName)
   194  		result, err := jsonutil.Marshal(userExtParsed)
   195  		if err == nil {
   196  			return result
   197  		}
   198  	}
   199  
   200  	return ext
   201  }