Skip to content

Commit

Permalink
Use ipv6 for geo location call if ipv4 is not defined (#1256)
Browse files Browse the repository at this point in the history
  • Loading branch information
SerhiiNahornyi authored and nickluck8 committed Aug 10, 2021
1 parent 78ad8bb commit 1911f6e
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.auction.model.BidderPrivacyResult;
import org.prebid.server.auction.model.IpAddress;
import org.prebid.server.bidder.BidderCatalog;
import org.prebid.server.execution.Timeout;
import org.prebid.server.metric.MetricName;
Expand Down Expand Up @@ -64,6 +66,7 @@ public class PrivacyEnforcementService {
private final BidderCatalog bidderCatalog;
private final PrivacyExtractor privacyExtractor;
private final TcfDefinerService tcfDefinerService;
private final ImplicitParametersExtractor implicitParametersExtractor;
private final IpAddressHelper ipAddressHelper;
private final Metrics metrics;
private final boolean ccpaEnforce;
Expand All @@ -72,6 +75,7 @@ public class PrivacyEnforcementService {
public PrivacyEnforcementService(BidderCatalog bidderCatalog,
PrivacyExtractor privacyExtractor,
TcfDefinerService tcfDefinerService,
ImplicitParametersExtractor implicitParametersExtractor,
IpAddressHelper ipAddressHelper,
Metrics metrics,
boolean ccpaEnforce,
Expand All @@ -80,6 +84,7 @@ public PrivacyEnforcementService(BidderCatalog bidderCatalog,
this.bidderCatalog = Objects.requireNonNull(bidderCatalog);
this.privacyExtractor = Objects.requireNonNull(privacyExtractor);
this.tcfDefinerService = Objects.requireNonNull(tcfDefinerService);
this.implicitParametersExtractor = Objects.requireNonNull(implicitParametersExtractor);
this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper);
this.metrics = Objects.requireNonNull(metrics);
this.ccpaEnforce = ccpaEnforce;
Expand All @@ -96,14 +101,11 @@ public Future<PrivacyContext> contextFromBidRequest(AuctionContext auctionContex
final Privacy privacy = privacyExtractor.validPrivacyFrom(bidRequest, errors);

final Device device = bidRequest.getDevice();
final String ipAddress = device != null ? device.getIp() : null;

final Geo geo = device != null ? device.getGeo() : null;
final String country = geo != null ? geo.getCountry() : null;

final String effectiveIpAddress = isCoppaMaskingRequired(privacy) || isLmtEnabled(device)
? ipAddressHelper.maskIpv4(ipAddress)
: ipAddress;
final String effectiveIpAddress = resolveIpAddress(device, privacy);

final AccountGdprConfig accountGdpr = account.getGdpr();
final String accountId = account.getId();
Expand All @@ -114,11 +116,27 @@ public Future<PrivacyContext> contextFromBidRequest(AuctionContext auctionContex
.map(tcfContext -> PrivacyContext.of(privacy, tcfContext, tcfContext.getIpAddress()));
}

private String resolveIpAddress(Device device, Privacy privacy) {
final boolean shouldBeMasked = isCoppaMaskingRequired(privacy) || isLmtEnabled(device);

final String ipV4Address = device != null ? device.getIp() : null;
if (StringUtils.isNotBlank(ipV4Address)) {
return shouldBeMasked ? ipAddressHelper.maskIpv4(ipV4Address) : ipV4Address;
}

final String ipV6Address = device != null ? device.getIpv6() : null;
if (StringUtils.isNotBlank(ipV6Address)) {
return shouldBeMasked ? ipAddressHelper.anonymizeIpv6(ipV6Address) : ipV6Address;
}

return null;
}

public Future<PrivacyContext> contextFromSetuidRequest(
HttpServerRequest httpRequest, Account account, Timeout timeout) {

final Privacy privacy = privacyExtractor.validPrivacyFromSetuidRequest(httpRequest);
final String ipAddress = HttpUtil.ipFrom(httpRequest);
final String ipAddress = resolveIpFromRequest(httpRequest);
final AccountGdprConfig accountGdpr = account.getGdpr();
final String accountId = account.getId();
final RequestLogInfo requestLogInfo = requestLogInfo(MetricName.setuid, null, accountId);
Expand All @@ -132,7 +150,7 @@ public Future<PrivacyContext> contextFromCookieSyncRequest(
CookieSyncRequest cookieSyncRequest, HttpServerRequest httpRequest, Account account, Timeout timeout) {

final Privacy privacy = privacyExtractor.validPrivacyFrom(cookieSyncRequest);
final String ipAddress = HttpUtil.ipFrom(httpRequest);
final String ipAddress = resolveIpFromRequest(httpRequest);
final AccountGdprConfig accountGdpr = account.getGdpr();
final String accountId = account.getId();
final RequestLogInfo requestLogInfo = requestLogInfo(MetricName.cookiesync, null, accountId);
Expand All @@ -142,6 +160,16 @@ public Future<PrivacyContext> contextFromCookieSyncRequest(
.map(tcfContext -> PrivacyContext.of(privacy, tcfContext));
}

private String resolveIpFromRequest(HttpServerRequest request) {
final List<String> requestIps = implicitParametersExtractor.ipFrom(request);
return requestIps.stream()
.map(ipAddressHelper::toIpAddress)
.filter(Objects::nonNull)
.map(IpAddress::getIp)
.findFirst()
.orElse(null);
}

private static RequestLogInfo requestLogInfo(MetricName requestType, BidRequest bidRequest, String accountId) {
if (Objects.equals(requestType, MetricName.openrtb2web)) {
final Site site = bidRequest != null ? bidRequest.getSite() : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.auction.IpAddressHelper;
import org.prebid.server.auction.model.IpAddress;
import org.prebid.server.bidder.BidderCatalog;
import org.prebid.server.execution.Timeout;
import org.prebid.server.geolocation.GeoLocationService;
Expand Down Expand Up @@ -83,6 +84,9 @@ public TcfDefinerService(GdprConfig gdprConfig,
this.metrics = Objects.requireNonNull(metrics);
}

/**
* Used for auctions.
*/
public Future<TcfContext> resolveTcfContext(Privacy privacy,
String country,
String ipAddress,
Expand All @@ -99,6 +103,9 @@ public Future<TcfContext> resolveTcfContext(Privacy privacy,
.map(this::updateTcfGeoMetrics);
}

/**
* Used for cookie sync and setuid.
*/
public Future<TcfContext> resolveTcfContext(Privacy privacy,
String ipAddress,
AccountGdprConfig accountGdprConfig,
Expand Down Expand Up @@ -234,7 +241,18 @@ private Future<TcfContext> toTcfContext(Privacy privacy,
}

private String maybeMaskIp(String ipAddress, TCString consent) {
return shouldMaskIp(consent) ? ipAddressHelper.maskIpv4(ipAddress) : ipAddress;
if (!shouldMaskIp(consent)) {
return ipAddress;
}

final IpAddress ip = ipAddressHelper.toIpAddress(ipAddress);
if (ip == null) {
return ipAddress;
}

return ip.getVersion() == IpAddress.IP.v4
? ipAddressHelper.maskIpv4(ipAddress)
: ipAddressHelper.anonymizeIpv6(ipAddress);
}

private static boolean shouldMaskIp(TCString consent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,13 +585,21 @@ PrivacyEnforcementService privacyEnforcementService(
BidderCatalog bidderCatalog,
PrivacyExtractor privacyExtractor,
TcfDefinerService tcfDefinerService,
ImplicitParametersExtractor implicitParametersExtractor,
IpAddressHelper ipAddressHelper,
Metrics metrics,
@Value("${ccpa.enforce}") boolean ccpaEnforce,
@Value("${lmt.enforce}") boolean lmtEnforce) {

return new PrivacyEnforcementService(
bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, ccpaEnforce, lmtEnforce);
bidderCatalog,
privacyExtractor,
tcfDefinerService,
implicitParametersExtractor,
ipAddressHelper,
metrics,
ccpaEnforce,
lmtEnforce);
}

@Bean
Expand Down
20 changes: 1 addition & 19 deletions src/main/java/org/prebid/server/util/HttpUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import io.vertx.core.MultiMap;
import io.vertx.core.http.Cookie;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.RoutingContext;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -109,23 +108,6 @@ public static void addHeaderIfValueIsNotEmpty(MultiMap headers, CharSequence hea
}
}

/**
* Determines IP-Address by checking "X-Forwarded-For", "X-Real-IP" http headers or remote host address
* if both are empty.
*/
public static String ipFrom(HttpServerRequest request) {
// X-Forwarded-For: client1, proxy1, proxy2
String ip = StringUtils.trimToNull(
StringUtils.substringBefore(request.headers().get("X-Forwarded-For"), ","));
if (ip == null) {
ip = StringUtils.trimToNull(request.headers().get("X-Real-IP"));
}
if (ip == null) {
ip = StringUtils.trimToNull(request.remoteAddress().host());
}
return ip;
}

public static String getDomainFromUrl(String url) {
if (StringUtils.isBlank(url)) {
return null;
Expand All @@ -147,7 +129,7 @@ public static String toSetCookieHeaderValue(Cookie cookie) {
}

/**
* Sends HTTP response according to the given status and body
* Sends HTTP response according to the given status and body.
*/
public static void respondWith(RoutingContext context, HttpResponseStatus status, String body) {
final HttpServerResponse response = context.response().setStatusCode(status.code());
Expand Down
Loading

0 comments on commit 1911f6e

Please sign in to comment.