Skip to content

Commit

Permalink
Introduce HeaderMaskingFunction
Browse files Browse the repository at this point in the history
- A header name is necessary to dynamically mask header values.
- Handle a null value returned by masking functions.
- Replace Function<String,String` with `HeaderMaskingFunction`.
- `HeaderSanitizer` their builders are moved to `common.logging` from
  `common`.
  • Loading branch information
ikhoon committed Jan 29, 2024
1 parent 042141a commit b7697b5
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* under the License.
*/

package com.linecorp.armeria.common;
package com.linecorp.armeria.common.logging;

import static java.util.Objects.requireNonNull;

Expand All @@ -24,6 +24,8 @@

import com.google.common.collect.ImmutableSet;

import com.linecorp.armeria.common.HttpHeaderNames;

import io.netty.util.AsciiString;

/**
Expand All @@ -41,7 +43,9 @@ public abstract class AbstractHeadersSanitizerBuilder<T> {

private final Set<AsciiString> maskingHeaders = new HashSet<>();

private Function<String, String> maskingFunction = header -> "****";
private HeaderMaskingFunction maskingFunction = HeaderMaskingFunction.of();

AbstractHeadersSanitizerBuilder() {}

/**
* Sets the headers to mask before logging.
Expand Down Expand Up @@ -69,16 +73,29 @@ final Set<AsciiString> maskingHeaders() {

/**
* Sets the {@link Function} to use to maskFunction headers before logging.
* The default maskingFunction is {@link HeaderMaskingFunction#of()}
*
* <pre>{@code
* builder.maskingFunction((name, value) -> {
* if (name.equals(HttpHeaderNames.AUTHORIZATION)) {
* return "****";
* } else if (name.equals(HttpHeaderNames.COOKIE)) {
* return name.substring(0, 4) + "****";
* } else {
* return value;
* }
* }
* }</pre>
*/
public AbstractHeadersSanitizerBuilder<T> maskingFunction(Function<String, String> maskingFunction) {
public AbstractHeadersSanitizerBuilder<T> maskingFunction(HeaderMaskingFunction maskingFunction) {
this.maskingFunction = requireNonNull(maskingFunction, "maskingFunction");
return this;
}

/**
* Returns the {@link Function} to use to mask headers before logging.
*/
final Function<String, String> maskingFunction() {
final HeaderMaskingFunction maskingFunction() {
return maskingFunction;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.function.BiFunction;
import java.util.function.Function;

import com.linecorp.armeria.common.HeadersSanitizer;
import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.RequestContext;
import com.linecorp.armeria.common.annotation.Nullable;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2024 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.armeria.common.logging;

import com.linecorp.armeria.common.annotation.Nullable;

import io.netty.util.AsciiString;

/**
* A function that masks the specified header value.
*/
@FunctionalInterface
public interface HeaderMaskingFunction {

/**
* Returns the default {@link HeaderMaskingFunction} that masks the given value with {@code ****}.
*/
static HeaderMaskingFunction of() {
return (name, value) -> "****";
}

/**
* Masks the specified {@code value} of the specified {@code name}.
* If {@code null} is returned, the specified {@code value} will be removed from the log.
*/
@Nullable
String mask(AsciiString name, String value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
* under the License.
*/

package com.linecorp.armeria.common;
package com.linecorp.armeria.common.logging;

import java.util.function.BiFunction;

import com.fasterxml.jackson.databind.JsonNode;

import com.linecorp.armeria.common.HttpHeaderNames;
import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.RequestContext;
import com.linecorp.armeria.common.annotation.Nullable;

/**
Expand All @@ -28,9 +31,9 @@
@FunctionalInterface
public interface HeadersSanitizer<T> extends BiFunction<RequestContext, HttpHeaders, T> {
/**
* Returns the default text {@link HeadersSanitizer}.
* {@link HttpHeaderNames#AUTHORIZATION}, {@link HttpHeaderNames#COOKIE}, {@link HttpHeaderNames#SET_COOKIE},
* and {@link HttpHeaderNames#PROXY_AUTHORIZATION} are masked.
* Returns the default text {@link HeadersSanitizer} that masks
* {@link HttpHeaderNames#AUTHORIZATION}, {@link HttpHeaderNames#COOKIE},
* {@link HttpHeaderNames#SET_COOKIE}, and {@link HttpHeaderNames#PROXY_AUTHORIZATION} with {@code ****}.
*/
static HeadersSanitizer<String> ofText() {
return TextHeadersSanitizer.INSTANCE;
Expand All @@ -44,9 +47,9 @@ static TextHeadersSanitizerBuilder builderForText() {
}

/**
* Returns the default json {@link HeadersSanitizer}.
* {@link HttpHeaderNames#AUTHORIZATION}, {@link HttpHeaderNames#COOKIE}, {@link HttpHeaderNames#SET_COOKIE},
* and {@link HttpHeaderNames#PROXY_AUTHORIZATION} are masked.
* Returns the default JSON {@link HeadersSanitizer} that masks
* {@link HttpHeaderNames#AUTHORIZATION}, {@link HttpHeaderNames#COOKIE},
* {@link HttpHeaderNames#SET_COOKIE}, and {@link HttpHeaderNames#PROXY_AUTHORIZATION} with {@code ****}.
*/
static HeadersSanitizer<JsonNode> ofJson() {
return JsonHeadersSanitizer.INSTANCE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@
* under the License.
*/

package com.linecorp.armeria.common;
package com.linecorp.armeria.common.logging;

import static com.linecorp.armeria.common.TextHeadersSanitizer.maskHeaders;
import static com.linecorp.armeria.common.logging.TextHeadersSanitizer.maskHeaders;

import java.util.Set;
import java.util.function.Function;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.RequestContext;

import io.netty.util.AsciiString;

/**
Expand All @@ -34,10 +36,10 @@ final class JsonHeadersSanitizer implements HeadersSanitizer<JsonNode> {

static final HeadersSanitizer<JsonNode> INSTANCE = new JsonHeadersSanitizerBuilder().build();
private final Set<AsciiString> maskingHeaders;
private final Function<String, String> maskingFunction;
private final HeaderMaskingFunction maskingFunction;
private final ObjectMapper objectMapper;

JsonHeadersSanitizer(Set<AsciiString> maskingHeaders, Function<String, String> maskingFunction,
JsonHeadersSanitizer(Set<AsciiString> maskingHeaders, HeaderMaskingFunction maskingFunction,
ObjectMapper objectMapper) {
this.maskingHeaders = maskingHeaders;
this.maskingFunction = maskingFunction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
* under the License.
*/

package com.linecorp.armeria.common;
package com.linecorp.armeria.common.logging;

import static java.util.Objects.requireNonNull;

import java.util.function.Function;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

Expand All @@ -45,7 +43,7 @@ public JsonHeadersSanitizerBuilder maskingHeaders(Iterable<? extends CharSequenc
}

@Override
public JsonHeadersSanitizerBuilder maskingFunction(Function<String, String> maskingFunction) {
public JsonHeadersSanitizerBuilder maskingFunction(HeaderMaskingFunction maskingFunction) {
return (JsonHeadersSanitizerBuilder) super.maskingFunction(maskingFunction);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.MoreObjects;

import com.linecorp.armeria.common.HeadersSanitizer;
import com.linecorp.armeria.common.RequestContext;
import com.linecorp.armeria.common.SerializationFormat;
import com.linecorp.armeria.common.annotation.Nullable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.linecorp.armeria.common.HeadersSanitizer;
import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.RequestContext;
import com.linecorp.armeria.common.annotation.Nullable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@
* under the License.
*/

package com.linecorp.armeria.common;
package com.linecorp.armeria.common.logging;

import static com.google.common.collect.ImmutableList.toImmutableList;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;

import com.google.common.collect.ImmutableList;

import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.RequestContext;

import io.netty.util.AsciiString;

/**
Expand All @@ -36,9 +39,10 @@ final class TextHeadersSanitizer implements HeadersSanitizer<String> {

private final Set<AsciiString> maskingHeaders;

private final Function<String, String> maskingFunction;
private final HeaderMaskingFunction maskingFunction;

TextHeadersSanitizer(Set<AsciiString> maskingHeaders, Function<String, String> maskingFunction) {
TextHeadersSanitizer(Set<AsciiString> maskingHeaders,
HeaderMaskingFunction maskingFunction) {
this.maskingHeaders = maskingHeaders;
this.maskingFunction = maskingFunction;
}
Expand Down Expand Up @@ -66,19 +70,30 @@ public String sanitize(RequestContext ctx, HttpHeaders headers) {
}

static void maskHeaders(
HttpHeaders headers, Set<AsciiString> maskingHeaders, Function<String, String> maskingFunction,
final BiConsumer<AsciiString, List<String>> consumer) {
HttpHeaders headers, Set<AsciiString> maskingHeaders,
HeaderMaskingFunction maskingFunction,
BiConsumer<AsciiString, List<String>> consumer) {
for (AsciiString headerName : headers.names()) {
List<String> values = headers.getAll(headerName);
if (maskingHeaders.contains(headerName)) {
// Mask the header values.
if (values.size() == 1) {
values = ImmutableList.of(maskingFunction.apply(values.get(0)));
final String masked = maskingFunction.mask(headerName, values.get(0));
if (masked == null) {
values = ImmutableList.of();
} else {
values = ImmutableList.of(masked);
}
} else {
values = values.stream().map(maskingFunction).collect(toImmutableList());
values = values.stream()
.map(value -> maskingFunction.mask(headerName, value))
.filter(Objects::nonNull)
.collect(toImmutableList());
}
}
consumer.accept(headerName, values);
if (!values.isEmpty()) {
consumer.accept(headerName, values);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
* under the License.
*/

package com.linecorp.armeria.common;

import java.util.function.Function;
package com.linecorp.armeria.common.logging;

/**
* A builder implementation for Text {@link HeadersSanitizer}.
Expand All @@ -34,7 +32,7 @@ public TextHeadersSanitizerBuilder maskingHeaders(Iterable<? extends CharSequenc
}

@Override
public TextHeadersSanitizerBuilder maskingFunction(Function<String, String> maskingFunction) {
public TextHeadersSanitizerBuilder maskingFunction(HeaderMaskingFunction maskingFunction) {
return (TextHeadersSanitizerBuilder) super.maskingFunction(maskingFunction);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import com.google.common.base.MoreObjects;

import com.linecorp.armeria.common.HeadersSanitizer;
import com.linecorp.armeria.common.RequestContext;
import com.linecorp.armeria.common.SerializationFormat;
import com.linecorp.armeria.common.annotation.Nullable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import java.util.function.BiFunction;

import com.linecorp.armeria.common.HeadersSanitizer;
import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.RequestContext;
import com.linecorp.armeria.common.annotation.Nullable;
Expand Down
Loading

0 comments on commit b7697b5

Please sign in to comment.