Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Adding logging for X-Forwarded-For client IP address (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlisonbee authored Aug 16, 2017
1 parent 0d65757 commit b0e4bd1
Show file tree
Hide file tree
Showing 17 changed files with 173 additions and 84 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
# limitations under the License.
#

version=0.27.0
version=0.28.0-RC1
groupId=com.nike.cerberus
artifactId=cms
36 changes: 36 additions & 0 deletions src/main/java/com/nike/cerberus/CerberusHttpHeaders.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
package com.nike.cerberus;

import com.nike.riposte.server.http.RequestInfo;
import io.netty.handler.codec.http.HttpHeaders;
import org.apache.commons.lang3.StringUtils;

public final class CerberusHttpHeaders {

public static final String HEADER_X_CERBERUS_CLIENT = "X-Cerberus-Client";
public static final String HEADER_X_REFRESH_TOKEN = "X-Refresh-Token";
public static final String HEADER_X_FORWARDED_FOR = "X-Forwarded-For";
private static final String UNKNOWN = "Unknown";

/**
* Get the value of the X-Cerberus-Client header or "Unknown" if not found.
*/
public static String getClientVersion(RequestInfo request) {
final HttpHeaders headers = request.getHeaders();
if (headers != null) {
String value = headers.get(HEADER_X_CERBERUS_CLIENT);
if (value != null) {
return value;
}
}
return UNKNOWN;
}

/**
* Get the first IP address from the Http header "X-Forwarded-For"
*
* E.g. "X-Forwarded-For: ip1, ip2, ip3" would return "ip1"
*/
public static String getXForwardedClientIp(RequestInfo request) {
final HttpHeaders headers = request.getHeaders();
if (headers != null) {
String value = headers.get(HEADER_X_FORWARDED_FOR);
if (value != null) {
return StringUtils.substringBefore(value, ",").trim();
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;

/**
* Extension endpoint class for validating caller is admin before executing.
*/
Expand All @@ -51,9 +53,9 @@ public final CompletableFuture<ResponseInfo<O>> execute(final RequestInfo<I> req
securityContext.get().getUserPrincipal().getName() :
"( Principal is not a Vault auth principal. )" : "( Principal name is empty. )";

log.info("Admin Endpoint Event: the principal {} is attempting to access admin endpoint: {}", principal, this.getClass().getName());
log.info("Admin Endpoint Event: the principal {} from ip: {} is attempting to access admin endpoint: {}", principal, getXForwardedClientIp(request), this.getClass().getName());
if (!securityContext.isPresent() || !securityContext.get().isUserInRole(VaultAuthPrincipal.ROLE_ADMIN)) {
log.error("Admin Endpoint Event: the principal {} is attempted to access {}, an admin endpoint but was not an admin", principal,
log.error("Admin Endpoint Event: the principal {} from ip: {} attempted to access {}, an admin endpoint but was not an admin", principal, getXForwardedClientIp(request),
this.getClass().getName());
throw new ApiException(DefaultApiError.ACCESS_DENIED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import com.nike.riposte.util.AsyncNettyHelper;
import com.nike.riposte.util.Matcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -36,6 +35,8 @@
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;

/**
* Authentication endpoint for IAM roles. If valid, a client token that is encrypted via KMS is returned. The
Expand Down Expand Up @@ -64,14 +65,12 @@ public CompletableFuture<ResponseInfo<IamRoleAuthResponse>> execute(final Reques

private ResponseInfo<IamRoleAuthResponse> authenticate(RequestInfo<IamPrincipalCredentials> request) {
final IamPrincipalCredentials credentials = request.getContent();
final HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

log.info("{}: {}, IAM Auth Event: the IAM principal {} in attempting to authenticate in region {}",
log.info("{}: {}, IAM Auth Event: the IAM principal {} with ip: {} in attempting to authenticate in region {}",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
getClientVersion(request),
credentials.getIamPrincipalArn(),
getXForwardedClientIp(request),
credentials.getRegion());

return ResponseInfo.newBuilder(authenticationService.authenticate(request.getContent())).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import com.nike.riposte.util.AsyncNettyHelper;
import com.nike.riposte.util.Matcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -36,6 +35,8 @@
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;

/**
* Authentication endpoint for IAM roles. If valid, a client token that is encrypted via KMS is returned. The
Expand Down Expand Up @@ -66,16 +67,14 @@ public CompletableFuture<ResponseInfo<IamRoleAuthResponse>> execute(final Reques

private ResponseInfo<IamRoleAuthResponse> authenticate(RequestInfo<IamRoleCredentials> request) {
final IamRoleCredentials credentials = request.getContent();
final HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

log.info("{}: {}, IAM Auth Event: the IAM principal {} in attempting to authenticate in region {}",
log.info("{}: {}, IAM Auth Event: the IAM principal {} with ip: {} is attempting to authenticate in region {}",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
getClientVersion(request),
String.format(AwsIamRoleArnParser.AWS_IAM_ROLE_ARN_TEMPLATE,
credentials.getAccountId(),
credentials.getRoleName()),
getXForwardedClientIp(request),
credentials.getRegion());

return ResponseInfo.newBuilder(authenticationService.authenticate(request.getContent())).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;

/**
* Authentication endpoint for user credentials. If valid, a client token will be returned.
Expand Down Expand Up @@ -67,14 +69,12 @@ public CompletableFuture<ResponseInfo<AuthResponse>> execute(final RequestInfo<V

private ResponseInfo<AuthResponse> authenticate(RequestInfo<Void> request) {
final UserCredentials credentials = extractCredentials(request.getHeaders().get(HttpHeaders.AUTHORIZATION));
final io.netty.handler.codec.http.HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

log.info("{}: {}, User Auth Event: the principal: {} is attempting to authenticate",
log.info("{}: {}, User Auth Event: the principal: {} with ip: {} is attempting to authenticate",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
credentials.getUsername());
getClientVersion(request),
credentials.getUsername(),
getXForwardedClientIp(request));

return ResponseInfo.newBuilder(authenticationService.authenticate(credentials)).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import com.nike.riposte.util.AsyncNettyHelper;
import com.nike.riposte.util.Matcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -40,6 +39,8 @@
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;

/**
* Authentication endpoint that allows refreshing the user token to pickup any permission changes.
Expand Down Expand Up @@ -72,14 +73,12 @@ public ResponseInfo<AuthResponse> getRefreshedUserToken(final RequestInfo<Void>
if (securityContext.isPresent()) {
final VaultAuthPrincipal vaultAuthPrincipal =
(VaultAuthPrincipal) securityContext.get().getUserPrincipal();
final HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

log.info("{}: {}, Refresh User Token Auth Event: the principal: {} is attempting to refresh its token",
log.info("{}: {}, Refresh User Token Auth Event: the principal: {} with ip: {} is attempting to refresh its token",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
vaultAuthPrincipal.getName());
getClientVersion(request),
vaultAuthPrincipal.getName(),
getXForwardedClientIp(request));

return ResponseInfo.newBuilder(
authenticationService.refreshUserToken(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import com.nike.riposte.util.AsyncNettyHelper;
import com.nike.riposte.util.Matcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
Expand All @@ -40,6 +39,8 @@
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;

/**
* Revokes the token supplied in the Vault token header.
Expand Down Expand Up @@ -72,14 +73,12 @@ public ResponseInfo<Void> revokeToken(RequestInfo<Void> request) {
if (securityContext.isPresent()) {
final VaultAuthPrincipal vaultAuthPrincipal =
(VaultAuthPrincipal) securityContext.get().getUserPrincipal();
final HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

log.info("{}: {}, Delete Token Auth Event: the principal: {} is attempting to delete a token",
log.info("{}: {}, Delete Token Auth Event: the principal: {} with ip: {} is attempting to delete a token",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
vaultAuthPrincipal.getName());
getClientVersion(request),
vaultAuthPrincipal.getName(),
getXForwardedClientIp(request));

authenticationService.revoke(vaultAuthPrincipal.getClientToken().getId());
return ResponseInfo.<Void>newBuilder().withHttpStatusCode(HttpResponseStatus.NO_CONTENT.code()).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import com.nike.riposte.util.Matcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
Expand All @@ -43,8 +42,12 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;


import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;
import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_REFRESH_TOKEN;

import static io.netty.handler.codec.http.HttpHeaders.Names.LOCATION;

/**
Expand Down Expand Up @@ -81,14 +84,12 @@ private ResponseInfo<Map<String, String>> createSafeDepositBox(final RequestInfo

if (securityContext.isPresent()) {
final VaultAuthPrincipal vaultAuthPrincipal = (VaultAuthPrincipal) securityContext.get().getUserPrincipal();
final HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

log.info("{}: {}, Create SDB Event: the principal: {} is attempting to create sdb name: '{}'",
log.info("{}: {}, Create SDB Event: the principal: {} from ip; {} is attempting to create sdb name: '{}'",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
getClientVersion(request),
vaultAuthPrincipal.getName(),
getXForwardedClientIp(request),
request.getContent().getName());

final String id =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import com.nike.riposte.util.Matcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
Expand All @@ -42,8 +41,11 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;
import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_REFRESH_TOKEN;

import static io.netty.handler.codec.http.HttpHeaders.Names.LOCATION;

/**
Expand Down Expand Up @@ -79,14 +81,12 @@ private ResponseInfo<SafeDepositBoxV2> createSafeDepositBox(final RequestInfo<Sa

if (securityContext.isPresent()) {
final VaultAuthPrincipal vaultAuthPrincipal = (VaultAuthPrincipal) securityContext.get().getUserPrincipal();
final HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

log.info("{}: {}, Create SDB Event: the principal: {} is attempting to create sdb name: '{}'",
log.info("{}: {}, Create SDB Event: the principal: {} from ip: {} is attempting to create sdb name: '{}'",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
getClientVersion(request),
vaultAuthPrincipal.getName(),
getXForwardedClientIp(request),
request.getContent().getName());

final SafeDepositBoxV2 safeDepositBox =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import com.nike.riposte.util.MultiMatcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
Expand All @@ -42,6 +41,8 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

import static com.nike.cerberus.CerberusHttpHeaders.getClientVersion;
import static com.nike.cerberus.CerberusHttpHeaders.getXForwardedClientIp;
import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_CERBERUS_CLIENT;
import static com.nike.cerberus.CerberusHttpHeaders.HEADER_X_REFRESH_TOKEN;

Expand Down Expand Up @@ -73,18 +74,16 @@ private ResponseInfo<Void> deleteSafeDepositBox(final RequestInfo<Void> request)

if (securityContext.isPresent()) {
final VaultAuthPrincipal vaultAuthPrincipal = (VaultAuthPrincipal) securityContext.get().getUserPrincipal();
final HttpHeaders headers = request.getHeaders();
final boolean clientHeaderExists = headers != null && headers.get(HEADER_X_CERBERUS_CLIENT) != null;
final String clientHeader = clientHeaderExists ? headers.get(HEADER_X_CERBERUS_CLIENT) : "Unknown";

String sdbId = request.getPathParam("id");
Optional<String> sdbNameOptional = safeDepositBoxService.getSafeDepositBoxNameById(sdbId);
String sdbName = sdbNameOptional.orElse(String.format("(Failed to lookup name from id: %s)", sdbId));

log.info("{}: {}, Delete SDB Event: the principal: {} is attempting to delete sdb name: '{}' and id: '{}'",
log.info("{}: {}, Delete SDB Event: the principal: {} from ip: {} is attempting to delete sdb name: '{}' and id: '{}'",
HEADER_X_CERBERUS_CLIENT,
clientHeader,
getClientVersion(request),
vaultAuthPrincipal.getName(),
getXForwardedClientIp(request),
sdbName,
sdbId);

Expand Down
Loading

0 comments on commit b0e4bd1

Please sign in to comment.