Skip to content

Commit d2027bd

Browse files
authored
Merge pull request #1164 from micronaut-projects/certificate-refactor
Support client certificate refresh from certificate service
2 parents c74b52d + 413d67d commit d2027bd

File tree

32 files changed

+1521
-617
lines changed

32 files changed

+1521
-617
lines changed

buildSrc/src/main/groovy/io.micronaut.build.internal.oraclecloud-base.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies {
1313
testRuntimeOnly libs.junit.jupiter
1414
testAnnotationProcessor mn.micronaut.inject.java
1515
testRuntimeOnly mnSerde.micronaut.serde.jackson
16-
testImplementation(mnTest.junit.platform.launcher)
16+
testImplementation(mnTest.junit.platform.launcher)
1717
}
1818

1919
tasks.withType(JavaCompile).configureEach {

gradle/libs.versions.toml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[versions]
2-
micronaut = "4.9.12"
2+
micronaut = "4.10.0"
33
micronaut-platform = "4.9.1"
44
micronaut-docs = "2.0.0"
55
fn = '1.0.209'
@@ -13,16 +13,15 @@ groovy = "4.0.28"
1313
spock = "2.3-groovy-4.0"
1414
oci = "3.72.1"
1515
oracle-database-security = "21.17.0.0"
16-
bcpkixjdk15to18 = "1.80"
1716
protobuf = '0.9.5'
18-
netty-http3 = "0.0.29.Final"
1917

2018
managed-apache-http-core5 = "5.3.4"
2119
micronaut-gradle-plugin = "4.5.4"
2220
micronaut-groovy = "4.7.0"
2321
micronaut-kotlin = "4.7.0"
2422
micronaut-kubernetes = "7.1.1"
2523
micronaut-micrometer = "5.12.0"
24+
micronaut-security = "4.13.1"
2625
micronaut-reactor = "3.8.0"
2726
micronaut-rxjava2 = "2.8.0"
2827
micronaut-serde = "2.15.1"
@@ -50,6 +49,7 @@ micronaut-groovy = { module = "io.micronaut.groovy:micronaut-groovy-bom", versio
5049
micronaut-kotlin = { module = "io.micronaut.kotlin:micronaut-kotlin-bom", version.ref = "micronaut-kotlin" }
5150
micronaut-kubernetes = { module = "io.micronaut.kubernetes:micronaut-kubernetes-bom", version.ref = "micronaut-kubernetes" }
5251
micronaut-micrometer = { module = "io.micronaut.micrometer:micronaut-micrometer-bom", version.ref = "micronaut-micrometer" }
52+
micronaut-security = { module = "io.micronaut.security:micronaut-security-bom", version.ref = "micronaut-security" }
5353
micronaut-reactor = { module = "io.micronaut.reactor:micronaut-reactor-bom", version.ref = "micronaut-reactor" }
5454
micronaut-rxjava2 = { module = "io.micronaut.rxjava2:micronaut-rxjava2-bom", version.ref = "micronaut-rxjava2" }
5555
micronaut-serde = { module = "io.micronaut.serde:micronaut-serde-bom", version.ref = "micronaut-serde" }
@@ -89,9 +89,7 @@ oracle-jdbc-bom = { module = "com.oracle.database.jdbc:ojdbc-bom" }
8989
oracle-security-cert = { module = "com.oracle.database.security:osdt_cert", version.ref = "oracle-database-security" }
9090
oracle-security-core = { module = "com.oracle.database.security:osdt_core", version.ref = "oracle-database-security" }
9191
oracle-xml-xdb = { module = 'com.oracle.database.xml:xdb' }
92-
netty-incubator-codec-http3 = { module = "io.netty.incubator:netty-incubator-codec-http3", version.ref = "netty-http3" }
9392
apache-http-core5 = { module = 'org.apache.httpcomponents.core5:httpcore5', version.ref = 'managed-apache-http-core5' }
94-
bcpkixjdk15to18 = { module = "org.bouncycastle:bcpkix-jdk15to18", version.ref = "bcpkixjdk15to18"}
9593

9694
#plugins
9795
kotlin-gradle-plugin = { module = 'org.jetbrains.kotlin:kotlin-gradle-plugin', version.ref = 'kotlin' }

oraclecloud-certificates/build.gradle

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ dependencies {
77
implementation mn.micronaut.http.server.netty
88
implementation mn.micronaut.inject.java
99
implementation mn.micronaut.retry
10-
implementation(libs.bcpkixjdk15to18)
11-
compileOnly libs.netty.incubator.codec.http3
10+
implementation mnReactor.micronaut.reactor
11+
compileOnly(mn.micronaut.http.client)
1212

13+
testImplementation(mnSecurity.micronaut.security)
14+
testImplementation(mn.micronaut.http.client)
15+
testImplementation projects.micronautOraclecloudBmcObjectstorage
1316
testImplementation mnTest.micronaut.test.spock
14-
testImplementation mn.micronaut.http.client
1517
testImplementation mn.micronaut.inject.groovy
1618
}
19+

oraclecloud-certificates/src/main/java/io/micronaut/oraclecloud/certificates/OracleCloudCertificationsConfiguration.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,46 @@
1515
*/
1616
package io.micronaut.oraclecloud.certificates;
1717

18+
import io.micronaut.context.annotation.BootstrapContextCompatible;
1819
import io.micronaut.context.annotation.ConfigurationProperties;
20+
import io.micronaut.context.annotation.Requires;
21+
import io.micronaut.core.annotation.NonNull;
1922
import io.micronaut.core.util.Toggleable;
20-
import io.micronaut.oraclecloud.core.OracleCloudCoreFactory;
23+
import io.micronaut.oraclecloud.certificates.config.OracleCloudCertificateProperties;
2124
import jakarta.annotation.Nullable;
25+
import jakarta.inject.Named;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
2228

23-
import static io.micronaut.oraclecloud.certificates.OracleCloudCertificationsConfiguration.PREFIX;
29+
import static io.micronaut.oraclecloud.certificates.config.OracleCloudCertificateProperties.PREFIX;
2430

2531
/**
26-
* Allows the configuration of the Oracle Cloud certificate process.
32+
* Allows the configuration of the default Oracle Cloud certificate to use.
2733
* @param certificateId ocid of certificate
2834
* @param versionNumber version number of certificate
2935
* @param certificateVersionName certificate name
3036
* @param enabled flag for enabling feature
3137
*/
3238
@ConfigurationProperties(PREFIX)
33-
public record OracleCloudCertificationsConfiguration(String certificateId, @Nullable Long versionNumber, @Nullable String certificateVersionName, @Nullable Boolean enabled) implements Toggleable {
39+
@Deprecated(forRemoval = true)
40+
@Requires(property = OracleCloudCertificationsConfiguration.CERTIFICATE_ID)
41+
@Named("deprecated")
42+
@BootstrapContextCompatible
43+
public record OracleCloudCertificationsConfiguration(
44+
@NonNull String certificateId,
45+
@Nullable Long versionNumber,
46+
@Nullable String certificateVersionName,
47+
boolean enabled) implements Toggleable, OracleCloudCertificateProperties {
48+
public static final String CERTIFICATE_ID = PREFIX + ".certificate-id";
49+
public static final String ENABLED_PROPERTY = PREFIX + ".enabled";
50+
private static final Logger LOG = LoggerFactory.getLogger(OracleCloudCertificationsConfiguration.class);
3451

35-
public static final String PREFIX = OracleCloudCoreFactory.ORACLE_CLOUD + ".certificates";
52+
public OracleCloudCertificationsConfiguration {
53+
LOG.warn("Configuring server certificate via " + CERTIFICATE_ID + " is deprecated. Use " + OracleCloudCertificateProperties.PREFIX + " namespace instead");
54+
}
3655

37-
/**
38-
* If Oracle Cloud certificate background and setup process should be enabled.
39-
*
40-
* @return True if Oracle Cloud certificate process is enabled.
41-
*/
4256
@Override
43-
public boolean isEnabled() {
44-
return enabled != null && enabled;
57+
public @NonNull String getName() {
58+
return "deprecated";
4559
}
4660
}

oraclecloud-certificates/src/main/java/io/micronaut/oraclecloud/certificates/background/OracleCloudCertificationRefresherTask.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import io.micronaut.context.annotation.Context;
1919
import io.micronaut.context.annotation.Requires;
2020
import io.micronaut.core.annotation.Internal;
21-
import io.micronaut.oraclecloud.certificates.OracleCloudCertificationsConfiguration;
21+
import io.micronaut.oraclecloud.certificates.config.OracleCloudCertificateProperties;
2222
import io.micronaut.oraclecloud.certificates.services.OracleCloudCertificateService;
2323
import io.micronaut.scheduling.annotation.Scheduled;
2424
import jakarta.inject.Singleton;
@@ -29,9 +29,9 @@
2929
* Background task to automatically refresh the certificates from an Oracle Cloud Certificate server on a configurable interval.
3030
*/
3131
@Singleton
32-
@Requires(property = OracleCloudCertificationsConfiguration.PREFIX + ".enabled", value = "true")
3332
@Context
3433
@Internal
34+
@Requires(bean = OracleCloudCertificateProperties.class)
3535
public final class OracleCloudCertificationRefresherTask {
3636

3737
private static final Logger LOG = LoggerFactory.getLogger(OracleCloudCertificationRefresherTask.class);
@@ -45,7 +45,6 @@ public final class OracleCloudCertificationRefresherTask {
4545
*/
4646
public OracleCloudCertificationRefresherTask(OracleCloudCertificateService oracleCloudCertificateService) {
4747
this.oracleCloudCertificateService = oracleCloudCertificateService;
48-
oracleCloudCertificateService.refreshCertificate();
4948
}
5049

5150
/**
@@ -57,12 +56,12 @@ public OracleCloudCertificationRefresherTask(OracleCloudCertificateService oracl
5756
initialDelay = "${oci.certificates.refresh.delay:24h}")
5857
public void backgroundRenewal() {
5958
if (LOG.isDebugEnabled()) {
60-
LOG.debug("Running background/scheduled renewal process");
59+
LOG.debug("Running background/scheduled certificate renewal process");
6160
}
6261
try {
6362
oracleCloudCertificateService.refreshCertificate();
6463
} catch (Exception e) {
65-
LOG.error("There was error during refreshing certificate process", e);
64+
LOG.error("There was error during refreshing certificate process: {}", e.getMessage(), e);
6665
}
6766
}
6867
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2017-2025 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.oraclecloud.certificates.config;
17+
18+
import io.micronaut.context.ApplicationContextBuilder;
19+
import io.micronaut.context.ApplicationContextConfigurer;
20+
import io.micronaut.context.annotation.ContextConfigurer;
21+
import io.micronaut.context.env.Environment;
22+
import io.micronaut.core.annotation.Internal;
23+
import io.micronaut.core.util.StringUtils;
24+
25+
import java.util.Map;
26+
27+
28+
/**
29+
* ApplicationContext configurer for the OCI Certificates client.
30+
* <p>
31+
* Marks the Micronaut ApplicationContext as a bootstrap context and sets
32+
* {@code oci.clients.certificates.ssl.enabled=true}. This ensures the per-service
33+
* client configuration bean {@link io.micronaut.oraclecloud.core.ServiceOracleCloudClientConfigurationProperties}
34+
* named {@code certificates} is created and applied to the OCI Certificates client so SSL and other
35+
* client options can be customized under the {@code oci.clients.certificates.*} namespace.
36+
* </p>
37+
*/
38+
@ContextConfigurer
39+
@Internal
40+
public class CertificateClientContextConfigurer implements ApplicationContextConfigurer {
41+
/**
42+
* Configure the context for the OCI Certificates client by enabling the
43+
* per-service client configuration for the {@code certificates} service.
44+
* Specifically, this sets {@code oci.clients.certificates.ssl.enabled=true} during bootstrap,
45+
* which causes Micronaut to bind and use
46+
* {@link io.micronaut.oraclecloud.core.ServiceOracleCloudClientConfigurationProperties}
47+
* for the Certificates client.
48+
*
49+
* @param builder The application context builder
50+
*/
51+
@Override
52+
public void configure(ApplicationContextBuilder builder) {
53+
System.setProperty(Environment.BOOTSTRAP_CONTEXT_PROPERTY, StringUtils.TRUE);
54+
builder.properties(Map.of(
55+
"oci.clients.certificates.ssl.enabled", "true"
56+
));
57+
}
58+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2017-2025 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.oraclecloud.certificates.config;
17+
18+
import io.micronaut.context.annotation.ConfigurationProperties;
19+
import io.micronaut.core.bind.annotation.Bindable;
20+
import jakarta.annotation.Nullable;
21+
22+
import java.time.Duration;
23+
24+
/**
25+
* Configuration for certificate refresh frequency.
26+
*
27+
* @param frequency The frequency. Default 24 hours.
28+
* @param delay The initial delay. Default 24 hours.
29+
* @param retry The retry configuration.
30+
*/
31+
@ConfigurationProperties(OracleCloudCertificateProperties.PREFIX + ".refresh")
32+
public record CertificateRefreshConfiguration(
33+
@Bindable(defaultValue = "24h")
34+
Duration frequency,
35+
@Bindable(defaultValue = "24h")
36+
Duration delay,
37+
@Nullable
38+
RetryConfiguration retry
39+
) {
40+
/**
41+
* Retry retry configuration.
42+
* @param attempts Number of times to retry
43+
* @param delay The delay between retries.
44+
*/
45+
@ConfigurationProperties("retry")
46+
record RetryConfiguration(
47+
@Bindable(defaultValue = "3")
48+
int attempts,
49+
@Bindable(defaultValue = "1s")
50+
Duration delay
51+
) { }
52+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2017-2025 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.oraclecloud.certificates.config;
17+
18+
import io.micronaut.context.annotation.BootstrapContextCompatible;
19+
import io.micronaut.context.annotation.EachProperty;
20+
import io.micronaut.context.annotation.Parameter;
21+
import io.micronaut.context.annotation.Requires;
22+
import io.micronaut.core.annotation.NonNull;
23+
import io.micronaut.core.annotation.Nullable;
24+
import io.micronaut.core.bind.annotation.Bindable;
25+
import io.micronaut.oraclecloud.certificates.OracleCloudCertificationsConfiguration;
26+
27+
/**
28+
* Configuration entry for an Oracle Cloud Infrastructure (OCI) certificate.
29+
* <p>
30+
* Each instance represents one certificate to be fetched from OCI Certificates service and exposed
31+
* to Micronaut's SSL infrastructure.
32+
* </p>
33+
*
34+
* @param name The name of the config.
35+
* @param certificateId The OCID of the certificate.
36+
* @param versionNumber The specific certificate version number to use, or null to resolve by name/latest.
37+
* @param certificateVersionName The named certificate version to use, or null.
38+
* @param enabled Whether this certificate entry is enabled. Defaults to true when unspecified.
39+
*/
40+
@EachProperty(value = OracleCloudCertificateProperties.PREFIX)
41+
@Requires(missingProperty = OracleCloudCertificationsConfiguration.CERTIFICATE_ID)
42+
@Requires(missingProperty = OracleCloudCertificationsConfiguration.ENABLED_PROPERTY)
43+
@BootstrapContextCompatible
44+
public record OracleCloudCertificateConfiguration(
45+
@Parameter String name,
46+
@NonNull String certificateId,
47+
@Nullable Long versionNumber,
48+
@Nullable String certificateVersionName,
49+
@Bindable(defaultValue = "true") boolean enabled
50+
) implements OracleCloudCertificateProperties {
51+
52+
@Override
53+
public @NonNull String getName() {
54+
return name;
55+
}
56+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2017-2025 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.oraclecloud.certificates.config;
17+
18+
import io.micronaut.core.annotation.NonNull;
19+
import io.micronaut.core.naming.Named;
20+
import io.micronaut.core.util.Toggleable;
21+
import io.micronaut.oraclecloud.core.OracleCloudCoreFactory;
22+
import jakarta.annotation.Nullable;
23+
24+
/**
25+
* Interface for configuration properties for certificates.
26+
*/
27+
public interface OracleCloudCertificateProperties extends Toggleable, Named {
28+
String PREFIX = OracleCloudCoreFactory.ORACLE_CLOUD + ".certificates";
29+
30+
/**
31+
* @return Is the certificate enabled.
32+
*/
33+
boolean enabled();
34+
35+
/**
36+
* @return The ID of the certificate
37+
*/
38+
@NonNull
39+
String certificateId();
40+
41+
/**
42+
* @return The version number of the certificate
43+
*/
44+
@Nullable
45+
Long versionNumber();
46+
47+
/**
48+
* @return The version name of the certificate.
49+
*/
50+
@Nullable String certificateVersionName();
51+
52+
@Override
53+
default boolean isEnabled() {
54+
return enabled();
55+
}
56+
}

0 commit comments

Comments
 (0)