Skip to content

Commit 907f71b

Browse files
author
Fernando Marino
committed
feat: add proxy support and ROPC authorization grant
1 parent dafaf0c commit 907f71b

20 files changed

Lines changed: 456 additions & 50 deletions

src/it/java/io/weaviate/integration/RbacITest.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,6 @@ public void test_roles_Lifecycle() throws IOException {
8484
Permission.groups("my-group", GroupType.OIDC, GroupsPermission.Action.READ));
8585
});
8686

87-
requireAtLeast(Weaviate.Version.V132, () -> {
88-
permissions.add(
89-
Permission.aliases("ThingsAlias", myCollection, AliasesPermission.Action.CREATE));
90-
});
91-
requireAtLeast(Weaviate.Version.V133, () -> {
92-
permissions.add(
93-
Permission.groups("my-group", GroupType.OIDC, GroupsPermission.Action.READ));
94-
});
95-
9687
// Act: create role
9788
client.roles.create(nsRole, permissions);
9889

src/main/java/io/weaviate/client6/v1/api/Authentication.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ public static Authentication resourceOwnerPassword(String username, String passw
5656
};
5757
}
5858

59+
/**
60+
* Authenticate using Resource Owner Password Credentials authorization grant.
61+
*
62+
* @param clientSecret Client secret.
63+
* @param username Resource owner username.
64+
* @param password Resource owner password.
65+
* @param scopes Client scopes.
66+
*
67+
* @return Authentication provider.
68+
* @throws WeaviateOAuthException if an error occurred at any point of the token
69+
* exchange process.
70+
*/
71+
public static Authentication resourceOwnerPasswordCredentials(String clientSecret, String username, String password,
72+
List<String> scopes) {
73+
return transport -> {
74+
OidcConfig oidc = OidcUtils.getConfig(transport).withScopes(scopes).withScopes("offline_access");
75+
return TokenProvider.resourceOwnerPasswordCredentials(oidc, clientSecret, username, password);
76+
};
77+
}
78+
5979
/**
6080
* Authenticate using Client Credentials authorization grant.
6181
*

src/main/java/io/weaviate/client6/v1/api/Config.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import io.weaviate.client6.v1.internal.BuildInfo;
1111
import io.weaviate.client6.v1.internal.ObjectBuilder;
12+
import io.weaviate.client6.v1.internal.Proxy;
1213
import io.weaviate.client6.v1.internal.Timeout;
1314
import io.weaviate.client6.v1.internal.TokenProvider;
1415
import io.weaviate.client6.v1.internal.grpc.GrpcChannelOptions;
@@ -23,7 +24,8 @@ public record Config(
2324
Map<String, String> headers,
2425
Authentication authentication,
2526
TrustManagerFactory trustManagerFactory,
26-
Timeout timeout) {
27+
Timeout timeout,
28+
Proxy proxy) {
2729

2830
public static Config of(Function<Custom, ObjectBuilder<Config>> fn) {
2931
return fn.apply(new Custom()).build();
@@ -39,23 +41,24 @@ private Config(Builder<?> builder) {
3941
builder.headers,
4042
builder.authentication,
4143
builder.trustManagerFactory,
42-
builder.timeout);
44+
builder.timeout,
45+
builder.proxy);
4346
}
4447

4548
RestTransportOptions restTransportOptions() {
4649
return restTransportOptions(null);
4750
}
4851

4952
RestTransportOptions restTransportOptions(TokenProvider tokenProvider) {
50-
return new RestTransportOptions(scheme, httpHost, httpPort, headers, tokenProvider, trustManagerFactory, timeout);
53+
return new RestTransportOptions(scheme, httpHost, httpPort, headers, tokenProvider, trustManagerFactory, timeout, proxy);
5154
}
5255

5356
GrpcChannelOptions grpcTransportOptions() {
5457
return grpcTransportOptions(null);
5558
}
5659

5760
GrpcChannelOptions grpcTransportOptions(TokenProvider tokenProvider) {
58-
return new GrpcChannelOptions(scheme, grpcHost, grpcPort, headers, tokenProvider, trustManagerFactory, timeout);
61+
return new GrpcChannelOptions(scheme, grpcHost, grpcPort, headers, tokenProvider, trustManagerFactory, timeout, proxy);
5962
}
6063

6164
private abstract static class Builder<SelfT extends Builder<SelfT>> implements ObjectBuilder<Config> {
@@ -69,6 +72,7 @@ private abstract static class Builder<SelfT extends Builder<SelfT>> implements O
6972
protected TrustManagerFactory trustManagerFactory;
7073
protected Timeout timeout = new Timeout();
7174
protected Map<String, String> headers = new HashMap<>();
75+
protected Proxy proxy;
7276

7377
/**
7478
* Set URL scheme. Subclasses may increase the visibility of this method to
@@ -174,6 +178,15 @@ public SelfT timeout(int initSeconds, int querySeconds, int insertSeconds) {
174178
return (SelfT) this;
175179
}
176180

181+
/**
182+
* Set proxy for all requests.
183+
*/
184+
@SuppressWarnings("unchecked")
185+
public SelfT proxy(Proxy proxy) {
186+
this.proxy = proxy;
187+
return (SelfT) this;
188+
}
189+
177190
/**
178191
* Weaviate will use the URL in this header to call Weaviate Embeddings
179192
* Service if an appropriate vectorizer is configured for collection.

src/main/java/io/weaviate/client6/v1/api/WeaviateClient.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,13 @@ public class WeaviateClient implements AutoCloseable {
6363
public final WeaviateClusterClient cluster;
6464

6565
public WeaviateClient(Config config) {
66-
RestTransportOptions restOpt;
66+
RestTransportOptions restOpt = config.restTransportOptions();
6767
GrpcChannelOptions grpcOpt;
6868
if (config.authentication() == null) {
69-
restOpt = config.restTransportOptions();
7069
grpcOpt = config.grpcTransportOptions();
7170
} else {
7271
TokenProvider tokenProvider;
73-
try (final var noAuthRest = new DefaultRestTransport(config.restTransportOptions())) {
72+
try (final var noAuthRest = new DefaultRestTransport(restOpt)) {
7473
tokenProvider = config.authentication().getTokenProvider(noAuthRest);
7574
} catch (Exception e) {
7675
// Generally exceptions are caught in TokenProvider internals.
@@ -126,6 +125,10 @@ public WeaviateClient(Config config) {
126125
this.config = config;
127126
}
128127

128+
public Config getConfig() {
129+
return config;
130+
}
131+
129132
/**
130133
* Create {@link WeaviateClientAsync} with identical configurations.
131134
* It is a shorthand for:

src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public CollectionHandle<Map<String, Object>> use(
7575
return use(CollectionDescriptor.ofMap(collectionName), fn);
7676
}
7777

78-
private <PropertiesT> CollectionHandle<PropertiesT> use(CollectionDescriptor<PropertiesT> collection,
78+
public <PropertiesT> CollectionHandle<PropertiesT> use(CollectionDescriptor<PropertiesT> collection,
7979
Function<CollectionHandleDefaults.Builder, ObjectBuilder<CollectionHandleDefaults>> fn) {
8080
return new CollectionHandle<>(restTransport, grpcTransport, collection, CollectionHandleDefaults.of(fn));
8181
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.weaviate.client6.v1.internal;
2+
3+
import javax.annotation.Nullable;
4+
5+
public record Proxy(
6+
String scheme,
7+
String host,
8+
int port,
9+
@Nullable String username,
10+
@Nullable String password
11+
) {
12+
public Proxy(String host, int port) {
13+
this("http", host, port, null, null);
14+
}
15+
}

src/main/java/io/weaviate/client6/v1/internal/TokenProvider.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,24 @@ public static TokenProvider resourceOwnerPassword(OidcConfig oidc, String userna
141141
return background(reuse(null, exchange(oidc, passwordGrant), DEFAULT_EARLY_EXPIRY));
142142
}
143143

144+
/**
145+
* Create a TokenProvider that uses Resource Owner Password Credentials authorization grant.
146+
*
147+
* @param oidc OIDC config.
148+
* @param clientSecret Client secret.
149+
* @param username Resource owner username.
150+
* @param password Resource owner password.
151+
*
152+
* @return Internal TokenProvider implementation.
153+
* @throws WeaviateOAuthException if an error occurred at any point of the token
154+
* exchange process.
155+
*/
156+
public static TokenProvider resourceOwnerPasswordCredentials(OidcConfig oidc, String clientSecret, String username,
157+
String password) {
158+
final var passwordGrant = NimbusTokenProvider.resouceOwnerPasswordCredentials(oidc, clientSecret, username, password);
159+
return background(reuse(null, exchange(oidc, passwordGrant), DEFAULT_EARLY_EXPIRY));
160+
}
161+
144162
/**
145163
* Create a TokenProvider that uses Client Credentials authorization grant.
146164
*

src/main/java/io/weaviate/client6/v1/internal/TransportOptions.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ public abstract class TransportOptions<H> {
1111
protected final H headers;
1212
protected final TrustManagerFactory trustManagerFactory;
1313
protected final Timeout timeout;
14+
protected final Proxy proxy;
1415

1516
protected TransportOptions(String scheme, String host, int port, H headers, TokenProvider tokenProvider,
16-
TrustManagerFactory tmf, Timeout timeout) {
17+
TrustManagerFactory tmf, Timeout timeout, Proxy proxy) {
1718
this.scheme = scheme;
1819
this.host = host;
1920
this.port = port;
2021
this.tokenProvider = tokenProvider;
2122
this.headers = headers;
2223
this.timeout = timeout;
2324
this.trustManagerFactory = tmf;
25+
this.proxy = proxy;
2426
}
2527

2628
public boolean isSecure() {
@@ -57,4 +59,9 @@ public H headers() {
5759
public TrustManagerFactory trustManagerFactory() {
5860
return this.trustManagerFactory;
5961
}
62+
63+
@Nullable
64+
public Proxy proxy() {
65+
return this.proxy;
66+
}
6067
}

src/main/java/io/weaviate/client6/v1/internal/grpc/DefaultGrpcTransport.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
package io.weaviate.client6.v1.internal.grpc;
22

3-
import java.util.concurrent.CompletableFuture;
4-
import java.util.concurrent.TimeUnit;
5-
6-
import javax.net.ssl.SSLException;
7-
83
import com.google.common.util.concurrent.FutureCallback;
94
import com.google.common.util.concurrent.Futures;
105
import com.google.common.util.concurrent.ListenableFuture;
11-
6+
import io.grpc.HttpConnectProxiedSocketAddress;
127
import io.grpc.ManagedChannel;
138
import io.grpc.StatusRuntimeException;
149
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
@@ -17,10 +12,17 @@
1712
import io.grpc.stub.AbstractStub;
1813
import io.grpc.stub.MetadataUtils;
1914
import io.weaviate.client6.v1.api.WeaviateApiException;
15+
import io.weaviate.client6.v1.internal.Proxy;
2016
import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc;
2117
import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateBlockingStub;
2218
import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateFutureStub;
2319

20+
import javax.net.ssl.SSLException;
21+
import java.net.InetSocketAddress;
22+
import java.net.SocketAddress;
23+
import java.util.concurrent.CompletableFuture;
24+
import java.util.concurrent.TimeUnit;
25+
2426
public final class DefaultGrpcTransport implements GrpcTransport {
2527
private final ManagedChannel channel;
2628

@@ -88,7 +90,7 @@ public <RequestT, RequestM, ReplyM, ResponseT> CompletableFuture<ResponseT> perf
8890
var method = rpc.methodAsync();
8991
var stub = applyTimeout(futureStub, rpc);
9092
var reply = method.apply(stub, message);
91-
return toCompletableFuture(reply).thenApply(r -> rpc.unmarshal(r));
93+
return toCompletableFuture(reply).thenApply(rpc::unmarshal);
9294
}
9395

9496
/**
@@ -139,6 +141,27 @@ private static ManagedChannel buildChannel(GrpcChannelOptions transportOptions)
139141
channel.sslContext(sslCtx);
140142
}
141143

144+
if (transportOptions.proxy() != null) {
145+
Proxy proxy = transportOptions.proxy();
146+
if ("http".equals(proxy.scheme())) {
147+
final SocketAddress proxyAddress = new InetSocketAddress(proxy.host(), proxy.port());
148+
channel.proxyDetector(targetAddress -> {
149+
if (targetAddress instanceof InetSocketAddress) {
150+
HttpConnectProxiedSocketAddress.Builder builder = HttpConnectProxiedSocketAddress.newBuilder()
151+
.setProxyAddress(proxyAddress)
152+
.setTargetAddress((InetSocketAddress) targetAddress);
153+
154+
if (proxy.username() != null && proxy.password() != null) {
155+
builder.setUsername(proxy.username());
156+
builder.setPassword(proxy.password());
157+
}
158+
return builder.build();
159+
}
160+
return null;
161+
});
162+
}
163+
}
164+
142165
channel.intercept(MetadataUtils.newAttachHeadersInterceptor(transportOptions.headers()));
143166

144167
return channel.build();

src/main/java/io/weaviate/client6/v1/internal/grpc/GrpcChannelOptions.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import javax.net.ssl.TrustManagerFactory;
66

77
import io.grpc.Metadata;
8+
import io.weaviate.client6.v1.internal.Proxy;
89
import io.weaviate.client6.v1.internal.Timeout;
910
import io.weaviate.client6.v1.internal.TokenProvider;
1011
import io.weaviate.client6.v1.internal.TransportOptions;
@@ -13,19 +14,19 @@ public class GrpcChannelOptions extends TransportOptions<Metadata> {
1314
private final Integer maxMessageSize;
1415

1516
public GrpcChannelOptions(String scheme, String host, int port, Map<String, String> headers,
16-
TokenProvider tokenProvider, TrustManagerFactory tmf, Timeout timeout) {
17-
this(scheme, host, port, buildMetadata(headers), tokenProvider, tmf, null, timeout);
17+
TokenProvider tokenProvider, TrustManagerFactory tmf, Timeout timeout, Proxy proxy) {
18+
this(scheme, host, port, buildMetadata(headers), tokenProvider, tmf, null, timeout, proxy);
1819
}
1920

2021
private GrpcChannelOptions(String scheme, String host, int port, Metadata headers,
21-
TokenProvider tokenProvider, TrustManagerFactory tmf, Integer maxMessageSize, Timeout timeout) {
22-
super(scheme, host, port, headers, tokenProvider, tmf, timeout);
22+
TokenProvider tokenProvider, TrustManagerFactory tmf, Integer maxMessageSize, Timeout timeout, Proxy proxy) {
23+
super(scheme, host, port, headers, tokenProvider, tmf, timeout, proxy);
2324
this.maxMessageSize = maxMessageSize;
2425
}
2526

2627
public GrpcChannelOptions withMaxMessageSize(int maxMessageSize) {
2728
return new GrpcChannelOptions(scheme, host, port, headers, tokenProvider, trustManagerFactory, maxMessageSize,
28-
timeout);
29+
timeout, proxy);
2930
}
3031

3132
public Integer maxMessageSize() {

0 commit comments

Comments
 (0)