Add support for DAPR_API_TOKEN (#330)

* Add supoort for DAPR_API_TOKEN

* Add tests for dapr api token

* Move interceptor logic

* Remove additional interceptor

* Fix check style voilation

* Add dapr api token as system property
This commit is contained in:
Pruthvidhar R Dhodda 2020-09-01 12:09:52 -07:00 committed by GitHub
parent eede480403
commit 7b174d88e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 5 deletions

View File

@ -84,6 +84,12 @@
<version>1.3.2</version> <version>1.3.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.19.0</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId> <artifactId>junit-jupiter-engine</artifactId>

View File

@ -21,6 +21,8 @@ import io.dapr.client.domain.SaveStateRequest;
import io.dapr.client.domain.State; import io.dapr.client.domain.State;
import io.dapr.client.domain.StateOptions; import io.dapr.client.domain.StateOptions;
import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.utils.Constants;
import io.dapr.utils.Properties;
import io.dapr.utils.TypeRef; import io.dapr.utils.TypeRef;
import io.dapr.v1.CommonProtos; import io.dapr.v1.CommonProtos;
import io.dapr.v1.DaprGrpc; import io.dapr.v1.DaprGrpc;
@ -32,6 +34,7 @@ import io.grpc.ClientInterceptor;
import io.grpc.Context; import io.grpc.Context;
import io.grpc.ForwardingClientCall; import io.grpc.ForwardingClientCall;
import io.grpc.Metadata; import io.grpc.Metadata;
import io.grpc.Metadata.Key;
import io.grpc.MethodDescriptor; import io.grpc.MethodDescriptor;
import io.opencensus.implcore.trace.propagation.PropagationComponentImpl; import io.opencensus.implcore.trace.propagation.PropagationComponentImpl;
import io.opencensus.implcore.trace.propagation.TraceContextFormat; import io.opencensus.implcore.trace.propagation.TraceContextFormat;
@ -483,8 +486,14 @@ public class DaprClientGrpc extends AbstractDaprClient {
SpanContext opencensusSpanContext = extractOpenCensusSpanContext(context); SpanContext opencensusSpanContext = extractOpenCensusSpanContext(context);
if (opencensusSpanContext != null) { if (opencensusSpanContext != null) {
byte[] grpcTraceBin = OPENCENSUS_BINARY_FORMAT.toByteArray(opencensusSpanContext); byte[] grpcTraceBin = OPENCENSUS_BINARY_FORMAT.toByteArray(opencensusSpanContext);
headers.put(Metadata.Key.of("grpc-trace-bin", Metadata.BINARY_BYTE_MARSHALLER), grpcTraceBin); headers.put(Key.of("grpc-trace-bin", Metadata.BINARY_BYTE_MARSHALLER), grpcTraceBin);
} }
String daprApiToken = Properties.DAPR_API_TOKEN.get();
if (daprApiToken != null) {
headers.put(Key.of(Constants.DAPR_API_TOKEN_HEADER, Metadata.ASCII_STRING_MARSHALLER), daprApiToken);
}
super.start(responseListener, headers); super.start(responseListener, headers);
} }
}; };

View File

@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import io.dapr.exceptions.DaprError; import io.dapr.exceptions.DaprError;
import io.dapr.exceptions.DaprException; import io.dapr.exceptions.DaprException;
import io.dapr.utils.Constants; import io.dapr.utils.Constants;
import io.dapr.utils.Properties;
import io.grpc.Context; import io.grpc.Context;
import io.opentelemetry.OpenTelemetry; import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.context.propagation.HttpTextFormat;
@ -258,6 +259,12 @@ public class DaprHttp implements Closeable {
} else { } else {
requestBuilder.method(method, body); requestBuilder.method(method, body);
} }
String daprApiToken = Properties.DAPR_API_TOKEN.get();
if (daprApiToken != null) {
requestBuilder.addHeader(Constants.DAPR_API_TOKEN_HEADER, daprApiToken);
}
if (headers != null) { if (headers != null) {
Optional.ofNullable(headers.entrySet()).orElse(Collections.emptySet()).stream() Optional.ofNullable(headers.entrySet()).orElse(Collections.emptySet()).stream()
.forEach(header -> { .forEach(header -> {
@ -308,4 +315,4 @@ public class DaprHttp implements Closeable {
return EMPTY_BYTES; return EMPTY_BYTES;
} }
} }

View File

@ -60,6 +60,16 @@ public final class Constants {
*/ */
public static final String ACTOR_TIMER_RELATIVE_URL_FORMAT = ACTORS_BASE_URL + "/%s/%s/timers/%s"; public static final String ACTOR_TIMER_RELATIVE_URL_FORMAT = ACTORS_BASE_URL + "/%s/%s/timers/%s";
/**
* Environment variable name for dapr api token.
*/
public static final String DAPR_API_TOKEN = "DAPR_API_TOKEN";
/**
* Header name for the dapr api token environment variable name.
*/
public static final String DAPR_API_TOKEN_HEADER = "dapr-api-token";
/** /**
* Base path to invoke methods. * Base path to invoke methods.
*/ */

View File

@ -35,6 +35,13 @@ public class Properties {
*/ */
private static final String DEFAULT_STRING_CHARSET = StandardCharsets.UTF_8.name(); private static final String DEFAULT_STRING_CHARSET = StandardCharsets.UTF_8.name();
/**
* API token for Dapr after checking system property and environment variable.
*/
public static final Supplier<String> DAPR_API_TOKEN = () -> getStringOrDefault(
"dapr.api.token",
Constants.DAPR_API_TOKEN, null);
/** /**
* HTTP port for Dapr after checking system property and environment variable. * HTTP port for Dapr after checking system property and environment variable.
*/ */
@ -70,7 +77,7 @@ public class Properties {
* *
* @return Integer from system property (1st) or env variable (2nd) or default (last). * @return Integer from system property (1st) or env variable (2nd) or default (last).
*/ */
public static Integer getIntOrDefault(String propName, String envName, Integer defaultValue) { private static Integer getIntOrDefault(String propName, String envName, Integer defaultValue) {
return getValueOrDefault(propName, envName, defaultValue, s -> Integer.valueOf(s)); return getValueOrDefault(propName, envName, defaultValue, s -> Integer.valueOf(s));
} }
@ -82,7 +89,7 @@ public class Properties {
* *
* @return Boolean from system property (1st) or env variable (2nd) or default (last). * @return Boolean from system property (1st) or env variable (2nd) or default (last).
*/ */
public static Boolean getBooleanOrDefault(String propName, String envName, Boolean defaultValue) { private static Boolean getBooleanOrDefault(String propName, String envName, Boolean defaultValue) {
return getValueOrDefault(propName, envName, defaultValue, s -> Boolean.valueOf(s)); return getValueOrDefault(propName, envName, defaultValue, s -> Boolean.valueOf(s));
} }
@ -94,7 +101,7 @@ public class Properties {
* *
* @return String from system property (1st) or env variable (2nd) or default (last). * @return String from system property (1st) or env variable (2nd) or default (last).
*/ */
public static String getStringOrDefault(String propName, String envName, String defaultValue) { private static String getStringOrDefault(String propName, String envName, String defaultValue) {
return getValueOrDefault(propName, envName, defaultValue, s -> s); return getValueOrDefault(propName, envName, defaultValue, s -> s);
} }

View File

@ -6,6 +6,7 @@ package io.dapr.client;
import io.dapr.exceptions.DaprException; import io.dapr.exceptions.DaprException;
import io.dapr.utils.Constants; import io.dapr.utils.Constants;
import io.dapr.utils.Properties;
import io.grpc.Context; import io.grpc.Context;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
@ -13,6 +14,8 @@ import okhttp3.ResponseBody;
import okhttp3.mock.Behavior; import okhttp3.mock.Behavior;
import okhttp3.mock.MockInterceptor; import okhttp3.mock.MockInterceptor;
import org.junit.Before; import org.junit.Before;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -27,6 +30,9 @@ import static org.junit.Assert.fail;
public class DaprHttpTest { public class DaprHttpTest {
@Rule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables();
private static final String EXPECTED_RESULT = private static final String EXPECTED_RESULT =
"{\"data\":\"ewoJCSJwcm9wZXJ0eUEiOiAidmFsdWVBIiwKCQkicHJvcGVydHlCIjogInZhbHVlQiIKCX0=\"}"; "{\"data\":\"ewoJCSJwcm9wZXJ0eUEiOiAidmFsdWVBIiwKCQkicHJvcGVydHlCIjogInZhbHVlQiIKCX0=\"}";
@ -42,6 +48,38 @@ public class DaprHttpTest {
okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build(); okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build();
} }
@Test
public void invokeApi_daprApiToken_present() throws IOException {
mockInterceptor.addRule()
.post("http://127.0.0.1:3500/v1.0/state")
.hasHeader(Constants.DAPR_API_TOKEN_HEADER)
.respond(serializer.serialize(EXPECTED_RESULT));
environmentVariables.set(Constants.DAPR_API_TOKEN, "xyz");
assertEquals("xyz", Properties.DAPR_API_TOKEN.get());
DaprHttp daprHttp = new DaprHttp(3500, okHttpClient);
Mono<DaprHttp.Response> mono =
daprHttp.invokeApi("POST", "v1.0/state", null, (byte[]) null, null, Context.current());
DaprHttp.Response response = mono.block();
String body = serializer.deserialize(response.getBody(), String.class);
assertEquals(EXPECTED_RESULT, body);
}
@Test
public void invokeApi_daprApiToken_absent() throws IOException {
mockInterceptor.addRule()
.post("http://127.0.0.1:3500/v1.0/state")
.not()
.hasHeader(Constants.DAPR_API_TOKEN_HEADER)
.respond(serializer.serialize(EXPECTED_RESULT));
assertNull(Properties.DAPR_API_TOKEN.get());
DaprHttp daprHttp = new DaprHttp(3500, okHttpClient);
Mono<DaprHttp.Response> mono =
daprHttp.invokeApi("POST", "v1.0/state", null, (byte[]) null, null, Context.current());
DaprHttp.Response response = mono.block();
String body = serializer.deserialize(response.getBody(), String.class);
assertEquals(EXPECTED_RESULT, body);
}
@Test @Test
public void invokeMethod() throws IOException { public void invokeMethod() throws IOException {
Map<String, String> headers = new HashMap<>(); Map<String, String> headers = new HashMap<>();