Skip to content

Commit ccacff5

Browse files
authored
KOGITO-6458: Define default authentication method to be used by OpenAPI (#90)
* KOGITO-6458: Define default authentication method to be used by OpenAPI * KOGITO-6458: Add integration test to verify configuration property "quarkus.openapi-generator.codegen.default.security.scheme" * KOGITO-6458: Update readme * KOGITO-6458: Minor refactoring handling null value
1 parent e875b5a commit ccacff5

File tree

11 files changed

+459
-4
lines changed

11 files changed

+459
-4
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ pattern: `quarkus.openapi-generator.[filename].[security_scheme_name].auth.[auth
147147

148148
> Tip: on production environments you will likely to use [HashiCorp Vault](https://quarkiverse.github.io/quarkiverse-docs/quarkus-vault/dev/index.html) or [Kubernetes Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) to provide this information for your application.
149149
150+
If the OpenAPI specification file has `securitySchemes` definitions, but no [Security Requirement Object](https://spec.openapis.org/oas/v3.1.0#security-requirement-object) definitions, the generator can be configured to create these by default. In this case, for all operations without a security requirement the default one will be created. Note that the property value needs to match the name of a security scheme object definition, eg. `api_key` or `basic_auth` in the `securitySchemes` list above.
151+
152+
| Description | Property Key | Example |
153+
| -------------------- | -------------------------------------------------------------- | ---------------------------------------------------- |
154+
| Create security for the referenced security scheme | `quarkus.openapi-generator.codegen.default.security.scheme` | `quarkus.openapi-generator.codegen.default.security.scheme=api_key` |
155+
150156
### Basic HTTP Authentication
151157

152158
For Basic HTTP Authentication, these are the supported configurations:

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class CodegenConfig {
1717
public static final String API_PKG_SUFFIX = ".api";
1818
public static final String MODEL_PKG_SUFFIX = ".model";
1919
public static final String VERBOSE_PROPERTY_NAME = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".verbose";
20+
public static final String DEFAULT_SECURITY_SCHEME = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".default.security.scheme";
2021
// package visibility for unit tests
2122
static final String BUILD_TIME_SPEC_PREFIX_FORMAT = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".spec.%s";
2223
private static final String BASE_PACKAGE_PROP_FORMAT = "%s.base-package";
@@ -33,6 +34,11 @@ public class CodegenConfig {
3334
*/
3435
@ConfigItem(name = "verbose", defaultValue = "false")
3536
public boolean verbose;
37+
/**
38+
* Security type for which security constraints should be created automatically if not explicitly defined
39+
*/
40+
@ConfigItem(name = "default.security.scheme", defaultValue = "none")
41+
public String defaultSecurityScheme;
3642

3743
public static String resolveApiPackage(final String basePackage) {
3844
return String.format("%s%s", basePackage, API_PKG_SUFFIX);

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import java.util.stream.Stream;
1212

1313
import org.eclipse.microprofile.config.Config;
14+
import org.openapitools.codegen.config.GlobalSettings;
1415

16+
import io.quarkiverse.openapi.generator.deployment.CodegenConfig;
1517
import io.quarkiverse.openapi.generator.deployment.circuitbreaker.CircuitBreakerConfigurationParser;
1618
import io.quarkiverse.openapi.generator.deployment.wrapper.OpenApiClientGeneratorWrapper;
1719
import io.quarkus.bootstrap.prebuild.CodeGenException;
@@ -64,6 +66,8 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
6466
protected void generate(final Config config, final Path openApiFilePath, final Path outDir) {
6567
final String basePackage = getBasePackage(config, openApiFilePath);
6668
final Boolean verbose = config.getOptionalValue(VERBOSE_PROPERTY_NAME, Boolean.class).orElse(false);
69+
GlobalSettings.setProperty(OpenApiClientGeneratorWrapper.DEFAULT_SECURITY_SCHEME,
70+
config.getOptionalValue(CodegenConfig.DEFAULT_SECURITY_SCHEME, String.class).orElse(""));
6771

6872
final OpenApiClientGeneratorWrapper generator = new OpenApiClientGeneratorWrapper(
6973
openApiFilePath.normalize(),

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ public class OpenApiClientGeneratorWrapper {
2828

2929
public static final String VERBOSE = "verbose";
3030
private static final String ONCE_LOGGER = "org.openapitools.codegen.utils.oncelogger.enabled";
31-
31+
/**
32+
* Security scheme for which to apply security constraints even if the OpenAPI definition has no security definition
33+
*/
34+
public static final String DEFAULT_SECURITY_SCHEME = "defaultSecurityScheme";
3235
private final QuarkusCodegenConfigurator configurator;
3336
private final DefaultGenerator generator;
3437

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/QuarkusJavaClientCodegen.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
7878
super.preprocessOpenAPI(openAPI);
7979
// add the default server url to the context
8080
additionalProperties.put(DEFAULT_SERVER_URL, URLPathUtils.getServerURL(this.openAPI, serverVariableOverrides()));
81+
additionalProperties.put(OpenApiClientGeneratorWrapper.DEFAULT_SECURITY_SCHEME,
82+
GlobalSettings.getProperty(OpenApiClientGeneratorWrapper.DEFAULT_SECURITY_SCHEME));
8183
}
8284

8385
@Override

deployment/src/main/resources/templates/auth/compositeAuthenticationProvider.qute

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ public class CompositeAuthenticationProvider extends AbstractCompositeAuthentica
4646
.build())
4747
{/if}
4848
{/for}
49+
{#else if defaultSecurityScheme == auth.name}
50+
.addOperation(OperationAuthInfo.builder()
51+
.withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
52+
.withId("{op.operationId}")
53+
.withMethod("{op.httpMethod}")
54+
.build())
4955
{/if}
5056
{/for}
5157
{/for});
@@ -64,6 +70,12 @@ public class CompositeAuthenticationProvider extends AbstractCompositeAuthentica
6470
.build())
6571
{/if}
6672
{/for}
73+
{#else if defaultSecurityScheme == auth.name}
74+
.addOperation(OperationAuthInfo.builder()
75+
.withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
76+
.withId("{op.operationId}")
77+
.withMethod("{op.httpMethod}")
78+
.build())
6779
{/if}
6880
{/for}
6981
{/for});
@@ -82,6 +94,12 @@ public class CompositeAuthenticationProvider extends AbstractCompositeAuthentica
8294
.build())
8395
{/if}
8496
{/for}
97+
{#else if defaultSecurityScheme == auth.name}
98+
.addOperation(OperationAuthInfo.builder()
99+
.withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
100+
.withId("{op.operationId}")
101+
.withMethod("{op.httpMethod}")
102+
.build())
85103
{/if}
86104
{/for}
87105
{/for});
@@ -101,6 +119,12 @@ public class CompositeAuthenticationProvider extends AbstractCompositeAuthentica
101119
.build())
102120
{/if}
103121
{/for}
122+
{#else if defaultSecurityScheme == auth.name}
123+
.addOperation(OperationAuthInfo.builder()
124+
.withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
125+
.withId("{op.operationId}")
126+
.withMethod("{op.httpMethod}")
127+
.build())
104128
{/if}
105129
{/for}
106130
{/for});
@@ -119,6 +143,12 @@ public class CompositeAuthenticationProvider extends AbstractCompositeAuthentica
119143
.build())
120144
{/if}
121145
{/for}
146+
{#else if defaultSecurityScheme == auth.name}
147+
.addOperation(OperationAuthInfo.builder()
148+
.withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
149+
.withId("{op.operationId}")
150+
.withMethod("{op.httpMethod}")
151+
.build())
122152
{/if}
123153
{/for}
124154
{/for});
@@ -137,6 +167,12 @@ public class CompositeAuthenticationProvider extends AbstractCompositeAuthentica
137167
.build())
138168
{/if}
139169
{/for}
170+
{#else if defaultSecurityScheme == auth.name}
171+
.addOperation(OperationAuthInfo.builder()
172+
.withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
173+
.withId("{op.operationId}")
174+
.withMethod("{op.httpMethod}")
175+
.build())
140176
{/if}
141177
{/for}
142178
{/for});

deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
import java.util.Optional;
1717

1818
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.params.ParameterizedTest;
20+
import org.junit.jupiter.params.provider.ValueSource;
21+
import org.openapitools.codegen.config.GlobalSettings;
1922

2023
import com.github.javaparser.StaticJavaParser;
2124
import com.github.javaparser.ast.CompilationUnit;
@@ -45,6 +48,32 @@ void verifyAuthBasicGenerated() throws URISyntaxException {
4548
assertTrue(generatedFiles.stream().anyMatch(f -> f.getName().equals("CompositeAuthenticationProvider.java")));
4649
}
4750

51+
@ParameterizedTest
52+
@ValueSource(strings = { "basic", "undefined" })
53+
void verifyAuthBasicWithMissingSecurityDefinition(String defaultSecurityScheme)
54+
throws URISyntaxException, FileNotFoundException {
55+
GlobalSettings.setProperty(OpenApiClientGeneratorWrapper.DEFAULT_SECURITY_SCHEME, defaultSecurityScheme);
56+
final List<File> generatedFiles = createGeneratorWrapper("petstore-openapi-httpbasic.json").generate("org.petstore");
57+
final Optional<File> authProviderFile = generatedFiles.stream()
58+
.filter(f -> f.getName().endsWith("CompositeAuthenticationProvider.java")).findFirst();
59+
assertThat(authProviderFile).isPresent();
60+
61+
CompilationUnit compilationUnit = StaticJavaParser.parse(authProviderFile.orElseThrow());
62+
List<MethodDeclaration> methodDeclarations = compilationUnit.findAll(MethodDeclaration.class);
63+
assertThat(methodDeclarations).isNotEmpty();
64+
65+
Optional<MethodDeclaration> initMethod = methodDeclarations.stream()
66+
.filter(m -> m.getNameAsString().equals("init"))
67+
.findAny();
68+
assertThat(initMethod).isPresent();
69+
70+
String fileContent = compilationUnit.toString();
71+
assertTrue(fileContent.contains("addAuthenticationProvider"));
72+
if (!defaultSecurityScheme.equals("undefined")) {
73+
assertTrue(fileContent.contains("addOperation"));
74+
}
75+
}
76+
4877
@Test
4978
void verifyAuthBearerGenerated() throws URISyntaxException {
5079
final List<File> generatedFiles = createGeneratorWrapper("petstore-openapi-bearer.json").generate("org.petstore");

0 commit comments

Comments
 (0)