diff --git a/providers/flagd/README.md b/providers/flagd/README.md index 158538f1f..6095e022c 100644 --- a/providers/flagd/README.md +++ b/providers/flagd/README.md @@ -112,6 +112,7 @@ Given below are the supported configurations: | maxEventStreamRetries | FLAGD_MAX_EVENT_STREAM_RETRIES | int | 5 | rpc | | retryBackoffMs | FLAGD_RETRY_BACKOFF_MS | int | 1000 | rpc | | offlineFlagSourcePath | FLAGD_OFFLINE_FLAG_SOURCE_PATH | String | null | in-process | +| authority | FLAGD_AUTHORITY_OVERRIDE | String | null | rpc & in-process | > [!NOTE] > Some configurations are only applicable for RPC resolver. diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java index 415b509b6..caeff76e9 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java @@ -35,6 +35,7 @@ public final class Config { static final String OFFLINE_SOURCE_PATH = "FLAGD_OFFLINE_FLAG_SOURCE_PATH"; static final String KEEP_ALIVE_MS_ENV_VAR_NAME_OLD = "FLAGD_KEEP_ALIVE_TIME"; static final String KEEP_ALIVE_MS_ENV_VAR_NAME = "FLAGD_KEEP_ALIVE_TIME_MS"; + static final String AUTHORITY_OVERRIDE = "FLAGD_AUTHORITY_OVERRIDE"; static final String RESOLVER_RPC = "rpc"; static final String RESOLVER_IN_PROCESS = "in-process"; diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java index c88709a32..9427d7d24 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java @@ -96,7 +96,7 @@ public class FlagdOptions { /** * gRPC client KeepAlive in milliseconds. Disabled with 0. * Defaults to 0 (disabled). - * + * **/ @Builder.Default private long keepAlive = fallBackToEnvOrDefault(Config.KEEP_ALIVE_MS_ENV_VAR_NAME, @@ -109,6 +109,16 @@ public class FlagdOptions { @Builder.Default private String offlineFlagSourcePath = fallBackToEnvOrDefault(Config.OFFLINE_SOURCE_PATH, null); + + /** + * gRPC authority override. + * Setting this will allow user to override the system generated authority with + * user specified string. This is useful when running flagd gRPC sync service behind + * proxy e.g. envoy, istio etc. + */ + @Builder.Default + private String authority = fallBackToEnvOrDefault(Config.AUTHORITY_OVERRIDE, null); + /** * Inject a Custom Connector for fetching flags. */ diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ChannelBuilder.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ChannelBuilder.java index e5c94e21d..a9fb7d257 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ChannelBuilder.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ChannelBuilder.java @@ -53,6 +53,12 @@ public static ManagedChannel nettyChannel(final FlagdOptions options) { final NettyChannelBuilder builder = NettyChannelBuilder .forAddress(options.getHost(), options.getPort()) .keepAliveTime(keepAliveMs, TimeUnit.MILLISECONDS); + + + if (options.getAuthority() != null) { + builder.overrideAuthority(options.getAuthority()); + } + if (options.isTls()) { SslContextBuilder sslContext = GrpcSslContexts.forClient(); diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java index 081193c22..793081f6c 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java @@ -34,6 +34,7 @@ void TestDefaults() { assertNull(builder.getOfflineFlagSourcePath()); assertEquals(Resolver.RPC, builder.getResolverType()); assertEquals(0, builder.getKeepAlive()); + assertNull(builder.getAuthority()); } @Test @@ -55,6 +56,7 @@ void TestBuilderOptions() { .customConnector(connector) .resolverType(Resolver.IN_PROCESS) .keepAlive(1000) + .authority("test.service") .build(); assertEquals("https://hosted-flagd", flagdOptions.getHost()); @@ -70,6 +72,7 @@ void TestBuilderOptions() { assertEquals(connector, flagdOptions.getCustomConnector()); assertEquals(Resolver.IN_PROCESS, flagdOptions.getResolverType()); assertEquals(1000, flagdOptions.getKeepAlive()); + assertEquals("test.service", flagdOptions.getAuthority()); } @@ -187,4 +190,13 @@ void testRpcProviderFromEnv_portConfigured_usesConfiguredPort() { assertThat(flagdOptions.getPort()).isEqualTo(1534); } + + + @Test + @SetEnvironmentVariable(key = AUTHORITY_OVERRIDE, value = "test.service") + void testAuthorityOverrideFromEnv() { + FlagdOptions flagdOptions = FlagdOptions.builder().build(); + + assertThat(flagdOptions.getAuthority()).isEqualTo("test.service"); + } }