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 }