Skip to content

Commit 48af970

Browse files
committed
Find and use AuthSchemeFactories in dynamic client
1 parent 243e83d commit 48af970

3 files changed

Lines changed: 132 additions & 3 deletions

File tree

client/dynamic-client/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extra["moduleName"] = "software.amazon.smithy.java.dynamicclient"
1010
dependencies {
1111
api(project(":dynamic-schemas"))
1212
api(project(":client:client-core"))
13+
implementation(project(":logging"))
1314

1415
testImplementation(project(":client:client-rulesengine"))
1516
testImplementation(project(":aws:client:aws-client-restjson"))

client/dynamic-client/src/main/java/software/amazon/smithy/java/dynamicclient/plugins/SimpleAuthDetectionPlugin.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,37 @@
55

66
package software.amazon.smithy.java.dynamicclient.plugins;
77

8+
import java.util.HashMap;
9+
import java.util.HashSet;
10+
import java.util.Map;
11+
import java.util.ServiceLoader;
812
import software.amazon.smithy.java.client.core.AutoClientPlugin;
913
import software.amazon.smithy.java.client.core.ClientConfig;
14+
import software.amazon.smithy.java.client.core.auth.scheme.AuthSchemeFactory;
1015
import software.amazon.smithy.java.client.core.auth.scheme.AuthSchemeResolver;
1116
import software.amazon.smithy.java.dynamicclient.settings.ModelSetting;
1217
import software.amazon.smithy.java.dynamicclient.settings.ServiceIdSetting;
18+
import software.amazon.smithy.java.logging.InternalLogger;
1319
import software.amazon.smithy.model.Model;
1420
import software.amazon.smithy.model.knowledge.ServiceIndex;
1521
import software.amazon.smithy.model.shapes.ShapeId;
1622

1723
/**
1824
* A plugin used to detect if built-in auth schemes can be applied to a client automatically.
1925
*/
26+
@SuppressWarnings("rawtypes")
2027
public final class SimpleAuthDetectionPlugin implements AutoClientPlugin {
2128

29+
private static final InternalLogger LOGGER = InternalLogger.getLogger(SimpleAuthDetectionPlugin.class);
30+
31+
private static final Map<ShapeId, AuthSchemeFactory> AUTH_SCHEME_FACTORIES = new HashMap<>();
32+
static {
33+
for (var factory : ServiceLoader.load(AuthSchemeFactory.class,
34+
SimpleAuthDetectionPlugin.class.getClassLoader())) {
35+
AUTH_SCHEME_FACTORIES.put(factory.schemeId(), factory);
36+
}
37+
}
38+
2239
public static final SimpleAuthDetectionPlugin INSTANCE = new SimpleAuthDetectionPlugin();
2340

2441
@Override
@@ -40,14 +57,35 @@ public void configureClient(ClientConfig.Builder config) {
4057
}
4158
}
4259

60+
@SuppressWarnings("unchecked")
4361
private void injectAuthSchemeResolver(ClientConfig.Builder config, Model model, ShapeId service) {
4462
var index = ServiceIndex.of(model);
4563
var potentialAuthSchemes = index.getEffectiveAuthSchemes(service);
4664
if (potentialAuthSchemes.isEmpty()) {
4765
config.authSchemeResolver(AuthSchemeResolver.NO_AUTH);
48-
} else {
49-
// TODO: Add similar behavior as done in ClientInterfaceGenerator to register AuthSchemeFactories.
50-
config.authSchemeResolver(AuthSchemeResolver.DEFAULT);
66+
return;
67+
}
68+
69+
// Make a set of the auth schemes explicitly configured since we don't want to overwrite them.
70+
var existingSchemeIds = new HashSet<>(config.supportedAuthSchemes().size());
71+
for (var scheme : config.supportedAuthSchemes()) {
72+
existingSchemeIds.add(scheme.schemeId());
5173
}
74+
75+
for (var entry : potentialAuthSchemes.entrySet()) {
76+
var id = entry.getKey();
77+
if (existingSchemeIds.contains(id)) {
78+
continue;
79+
}
80+
var factory = AUTH_SCHEME_FACTORIES.get(id);
81+
if (factory != null) {
82+
config.putSupportedAuthSchemes(factory.createAuthScheme(entry.getValue()));
83+
} else {
84+
LOGGER.warn("Could not find software.amazon.smithy.java.client.core.auth.scheme.AuthSchemeFactory "
85+
+ "implementation for auth scheme {}", id);
86+
}
87+
}
88+
89+
config.authSchemeResolver(AuthSchemeResolver.DEFAULT);
5290
}
5391
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.java.dynamicclient.plugins;
7+
8+
import static org.hamcrest.MatcherAssert.assertThat;
9+
import static org.hamcrest.Matchers.equalTo;
10+
import static org.hamcrest.Matchers.is;
11+
12+
import org.junit.jupiter.api.Test;
13+
import software.amazon.smithy.aws.traits.auth.SigV4Trait;
14+
import software.amazon.smithy.java.client.core.auth.scheme.AuthSchemeResolver;
15+
import software.amazon.smithy.java.client.core.endpoint.EndpointResolver;
16+
import software.amazon.smithy.java.dynamicclient.DynamicClient;
17+
import software.amazon.smithy.model.Model;
18+
import software.amazon.smithy.model.shapes.ShapeId;
19+
20+
class SimpleAuthDetectionPluginTest {
21+
22+
@Test
23+
void registersAuthSchemeFactoriesForServiceAuthTraits() {
24+
var model = Model.assembler()
25+
.addUnparsedModel("test.smithy", """
26+
$version: "2"
27+
namespace smithy.example
28+
29+
use aws.auth#sigv4
30+
use aws.protocols#awsJson1_0
31+
32+
@awsJson1_0
33+
@sigv4(name: "testservice")
34+
service AuthService {
35+
operations: [DoThing]
36+
}
37+
38+
operation DoThing {
39+
input := {}
40+
output := {}
41+
}
42+
""")
43+
.discoverModels()
44+
.assemble()
45+
.unwrap();
46+
47+
var client = DynamicClient.builder()
48+
.serviceId(ShapeId.from("smithy.example#AuthService"))
49+
.model(model)
50+
.endpointResolver(EndpointResolver.staticEndpoint("https://example.com"))
51+
.build();
52+
53+
var authSchemes = client.config().supportedAuthSchemes();
54+
var hasSigV4 = authSchemes.stream().anyMatch(s -> s.schemeId().equals(SigV4Trait.ID));
55+
assertThat("Expected SigV4 auth scheme to be registered", hasSigV4, is(true));
56+
assertThat(client.config().authSchemeResolver(), is(AuthSchemeResolver.DEFAULT));
57+
}
58+
59+
@Test
60+
void setsNoAuthResolverWhenNoAuthTraits() {
61+
var model = Model.assembler()
62+
.addUnparsedModel("test.smithy", """
63+
$version: "2"
64+
namespace smithy.example
65+
66+
use aws.protocols#awsJson1_0
67+
68+
@awsJson1_0
69+
service NoAuthService {
70+
operations: [DoThing]
71+
}
72+
73+
operation DoThing {
74+
input := {}
75+
output := {}
76+
}
77+
""")
78+
.discoverModels()
79+
.assemble()
80+
.unwrap();
81+
82+
var client = DynamicClient.builder()
83+
.serviceId(ShapeId.from("smithy.example#NoAuthService"))
84+
.model(model)
85+
.endpointResolver(EndpointResolver.staticEndpoint("https://example.com"))
86+
.build();
87+
88+
assertThat(client.config().authSchemeResolver(), equalTo(AuthSchemeResolver.NO_AUTH));
89+
}
90+
}

0 commit comments

Comments
 (0)