Skip to content

Commit 466f53b

Browse files
authored
Merge pull request #11140 from swagger-api/auth-access-control
Auth access control
2 parents 8771407 + fcfe6b3 commit 466f53b

File tree

8 files changed

+383
-4
lines changed

8 files changed

+383
-4
lines changed

modules/swagger-codegen/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,12 @@
314314
<version>${swagger-codegen-generators-version}</version>
315315
<scope>test</scope>
316316
</dependency>
317+
<dependency>
318+
<groupId>com.github.tomakehurst</groupId>
319+
<artifactId>wiremock</artifactId>
320+
<version>2.25.0</version>
321+
<scope>test</scope>
322+
</dependency>
317323
</dependencies>
318324
<repositories>
319325
<repository>

modules/swagger-codegen/src/main/java/io/swagger/codegen/v3/config/CodegenConfigurator.java

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.swagger.codegen.v3.CodegenConfigLoader;
1111
import io.swagger.codegen.v3.CodegenConstants;
1212
import io.swagger.codegen.v3.auth.AuthParser;
13+
import io.swagger.codegen.v3.service.HostAccessControl;
1314
import io.swagger.parser.OpenAPIParser;
1415
import io.swagger.v3.oas.models.OpenAPI;
1516
import io.swagger.v3.core.util.Json;
@@ -28,6 +29,7 @@
2829
import java.io.IOException;
2930
import java.io.Serializable;
3031
import java.net.URI;
32+
import java.net.URL;
3133
import java.nio.file.Files;
3234
import java.nio.file.Path;
3335
import java.nio.file.Paths;
@@ -37,6 +39,7 @@
3739
import java.util.List;
3840
import java.util.Map;
3941
import java.util.Set;
42+
import java.util.function.Predicate;
4043

4144
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
4245

@@ -93,6 +96,25 @@ public CodegenConfigurator() {
9396
this.setOutputDir(".");
9497
}
9598

99+
private List<HostAccessControl> allowedAuthHosts = new ArrayList<>();
100+
private List<HostAccessControl> deniedAuthHosts = new ArrayList<>();
101+
102+
public List<HostAccessControl> getAllowedAuthHosts() {
103+
return allowedAuthHosts;
104+
}
105+
106+
public void setAllowedAuthHosts(List<HostAccessControl> allowedAuthHosts) {
107+
this.allowedAuthHosts = allowedAuthHosts;
108+
}
109+
110+
public List<HostAccessControl> getDeniedAuthHosts() {
111+
return deniedAuthHosts;
112+
}
113+
114+
public void setDeniedAuthHosts(List<HostAccessControl> deniedAuthHosts) {
115+
this.deniedAuthHosts = deniedAuthHosts;
116+
}
117+
96118
public CodegenConfigurator setLang(String lang) {
97119
this.lang = lang;
98120
return this;
@@ -470,8 +492,59 @@ public ClientOptInput toClientOptInput() {
470492

471493
CodegenConfig config = CodegenConfigLoader.forName(lang);
472494
ClientOptInput input = new ClientOptInput();
495+
496+
Predicate<URL> urlMatcher = null;
497+
if (!allowedAuthHosts.isEmpty() || !deniedAuthHosts.isEmpty()) {
498+
urlMatcher = (url) -> {
499+
String host = url.getHost();
500+
// first check denies
501+
for (HostAccessControl check: deniedAuthHosts) {
502+
if (check.isRegex()) {
503+
if (host.matches(check.getHost())) {
504+
return false;
505+
}
506+
} else if (check.isEndsWith()){
507+
if (host.toLowerCase().endsWith(check.getHost().toLowerCase())){
508+
return false;
509+
}
510+
} else {
511+
if (host.equalsIgnoreCase(check.getHost())) {
512+
return false;
513+
}
514+
}
515+
}
516+
// then allows
517+
for (HostAccessControl check: allowedAuthHosts) {
518+
if (check.isRegex()) {
519+
if (!host.matches(check.getHost())) {
520+
return false;
521+
}
522+
} else if (check.isEndsWith()){
523+
if (!host.toLowerCase().endsWith(check.getHost().toLowerCase())){
524+
return false;
525+
}
526+
} else {
527+
if (!host.equalsIgnoreCase(check.getHost())) {
528+
return false;
529+
}
530+
}
531+
}
532+
return true;
533+
};
534+
}
535+
473536
final List<AuthorizationValue> authorizationValues = AuthParser.parse(auth);
537+
if (!authorizationValues.isEmpty() && urlMatcher != null) {
538+
for (AuthorizationValue authVal: authorizationValues) {
539+
if (authVal.getUrlMatcher() == null) {
540+
authVal.setUrlMatcher(urlMatcher);
541+
}
542+
}
543+
}
474544
if (authorizationValue != null) {
545+
if (urlMatcher != null) {
546+
authorizationValue.setUrlMatcher(urlMatcher);
547+
}
475548
authorizationValues.add(authorizationValue);
476549
}
477550

modules/swagger-codegen/src/main/java/io/swagger/codegen/v3/service/GeneratorUtil.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.swagger.codegen.v3.config.CodegenConfigurator;
1111
import io.swagger.codegen.v3.service.exception.BadRequestException;
1212
import io.swagger.models.Swagger;
13+
import io.swagger.models.auth.UrlMatcher;
1314
import io.swagger.parser.SwaggerParser;
1415
import io.swagger.v3.core.util.Json;
1516
import org.apache.commons.lang3.StringUtils;
@@ -41,12 +42,68 @@ public static io.swagger.codegen.ClientOptInput getClientOptInputV2(GenerationRe
4142
String lang = generationRequest.getLang();
4243
validateSpec(lang, inputSpec, inputSpecURL);
4344
LOGGER.debug("getClientOptInputV2 - spec validated");
45+
io.swagger.models.auth.UrlMatcher urlMatcher = null;
46+
if (!generationRequest.getOptions().getAllowedAuthHosts().isEmpty() || !generationRequest.getOptions().getDeniedAuthHosts().isEmpty()) {
47+
urlMatcher = url -> {
48+
String host = url.getHost();
49+
// first check denies
50+
for (HostAccessControl check: generationRequest.getOptions().getDeniedAuthHosts()) {
51+
if (check.isRegex()) {
52+
if (host.matches(check.getHost())) {
53+
return false;
54+
}
55+
} else if (check.isEndsWith()){
56+
if (host.toLowerCase().endsWith(check.getHost().toLowerCase())){
57+
return false;
58+
}
59+
} else {
60+
if (host.equalsIgnoreCase(check.getHost())) {
61+
return false;
62+
}
63+
}
64+
}
65+
// then allows
66+
for (HostAccessControl check: generationRequest.getOptions().getAllowedAuthHosts()) {
67+
if (check.isRegex()) {
68+
if (!host.matches(check.getHost())) {
69+
return false;
70+
}
71+
} else if (check.isEndsWith()){
72+
if (!host.toLowerCase().endsWith(check.getHost().toLowerCase())){
73+
return false;
74+
}
75+
} else {
76+
if (!host.equalsIgnoreCase(check.getHost())) {
77+
return false;
78+
}
79+
}
80+
}
81+
return true;
82+
};
83+
}
84+
4485
final List<io.swagger.models.auth.AuthorizationValue> authorizationValues = io.swagger.codegen.auth.AuthParser.parse(generationRequest.getOptions().getAuth());
86+
if (!authorizationValues.isEmpty() && urlMatcher != null) {
87+
for (io.swagger.models.auth.AuthorizationValue authVal: authorizationValues) {
88+
if (authVal.getUrlMatcher() == null) {
89+
authVal.setUrlMatcher(urlMatcher);
90+
}
91+
}
92+
}
4593
if (generationRequest.getOptions().getAuthorizationValue() != null) {
4694
io.swagger.models.auth.AuthorizationValue authorizationValue = new io.swagger.models.auth.AuthorizationValue()
4795
.value(generationRequest.getOptions().getAuthorizationValue().getValue())
4896
.keyName(generationRequest.getOptions().getAuthorizationValue().getKeyName())
4997
.type(generationRequest.getOptions().getAuthorizationValue().getType());
98+
UrlMatcher predicateUrlMatcher = null;
99+
if (generationRequest.getOptions().getAuthorizationValue().getUrlMatcher() != null) {
100+
predicateUrlMatcher = url -> generationRequest.getOptions().getAuthorizationValue().getUrlMatcher().test(url);
101+
}
102+
if (predicateUrlMatcher != null) {
103+
authorizationValue.setUrlMatcher(predicateUrlMatcher);
104+
} else if (urlMatcher != null) {
105+
authorizationValue.setUrlMatcher(urlMatcher);
106+
}
50107
authorizationValues.add(authorizationValue);
51108
}
52109
LOGGER.debug("getClientOptInputV2 - processed auth");
@@ -235,7 +292,7 @@ public static ClientOptInput getClientOptInput(GenerationRequest generationReque
235292
}
236293
if (options.getResolveFully() != null) {
237294
configurator.setResolveFully(options.getResolveFully());
238-
}
295+
}
239296
if (isNotEmpty(options.getArtifactVersion())) {
240297
configurator.setArtifactVersion(options.getArtifactVersion());
241298
}
@@ -290,6 +347,9 @@ public static ClientOptInput getClientOptInput(GenerationRequest generationReque
290347
configurator.addAdditionalReservedWordMapping(entry.getKey(), entry.getValue());
291348
}
292349
}
350+
351+
configurator.setAllowedAuthHosts(options.getAllowedAuthHosts());
352+
configurator.setDeniedAuthHosts(options.getDeniedAuthHosts());
293353
LOGGER.debug("getClientOptInput - end");
294354
return configurator.toClientOptInput();
295355
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.swagger.codegen.v3.service;
2+
3+
public class HostAccessControl {
4+
public String getHost() {
5+
return host;
6+
}
7+
8+
public void setHost(String host) {
9+
this.host = host;
10+
}
11+
12+
public boolean isRegex() {
13+
return regex;
14+
}
15+
16+
public void setRegex(boolean regex) {
17+
this.regex = regex;
18+
}
19+
20+
public boolean isEndsWith() {
21+
return endsWith;
22+
}
23+
24+
public void setEndsWith(boolean endsWith) {
25+
this.endsWith = endsWith;
26+
}
27+
28+
private String host;
29+
private boolean regex;
30+
private boolean endsWith;
31+
}

modules/swagger-codegen/src/main/java/io/swagger/codegen/v3/service/Options.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,41 @@ public class Options {
4242

4343
private boolean flattenInlineComposedSchemas = false;
4444

45+
private List<HostAccessControl> allowedAuthHosts = new ArrayList<>();
46+
private List<HostAccessControl> deniedAuthHosts = new ArrayList<>();
47+
48+
public List<HostAccessControl> getAllowedAuthHosts() {
49+
return allowedAuthHosts;
50+
}
51+
52+
public void setAllowedAuthHosts(List<HostAccessControl> allowedAuthHosts) {
53+
this.allowedAuthHosts = allowedAuthHosts;
54+
}
55+
56+
public List<HostAccessControl> getDeniedAuthHosts() {
57+
return deniedAuthHosts;
58+
}
59+
60+
public void setDeniedAuthHosts(List<HostAccessControl> deniedAuthHosts) {
61+
this.deniedAuthHosts = deniedAuthHosts;
62+
}
63+
64+
public Options allowedAuthHosts(List<HostAccessControl> allowedAuthHosts) {
65+
this.allowedAuthHosts = allowedAuthHosts;
66+
return this;
67+
}
68+
69+
public Options deniedAuthHosts(List<HostAccessControl> deniedAuthHosts) {
70+
this.deniedAuthHosts = deniedAuthHosts;
71+
return this;
72+
}
73+
4574
public Options authorizationValue(AuthorizationValue authorizationValue) {
4675
this.authorizationValue = authorizationValue;
4776
return this;
4877
}
4978

79+
5080
public AuthorizationValue getAuthorizationValue() {
5181
return authorizationValue;
5282
}
@@ -455,4 +485,10 @@ public Options flattenInlineComposedSchema(boolean flattenInlineComposedSchemas)
455485
this.flattenInlineComposedSchemas = flattenInlineComposedSchemas;
456486
return this;
457487
}
488+
489+
public Options flattenInlineComposedSchemas(boolean flattenInlineComposedSchemas) {
490+
this.flattenInlineComposedSchemas = flattenInlineComposedSchemas;
491+
return this;
492+
}
493+
458494
}

modules/swagger-codegen/src/test/java/io/swagger/codegen/v3/service/GeneratorServiceTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
public class GeneratorServiceTest {
2121

22+
2223
@Test(description = "test generator service with html2")
2324
public void testGeneratorService_HTML2_Bearer() throws IOException {
2425

0 commit comments

Comments
 (0)