Skip to content

Commit 90fc833

Browse files
committed
Fail fast at Apache5HttpClient construction when SecurityManager is active and jdk.net.NetworkPermission setOption.TCP_KEEPIDLE, setOption.TCP_KEEPINTERVAL, setOption.TCP_KEEPCOUNT are not granted
1 parent edb2077 commit 90fc833

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "Apache HTTP Client 5",
4+
"contributor": "",
5+
"description": "Fail fast at Apache5HttpClient construction when SecurityManager is active and jdk.net.NetworkPermission setOption.TCP_KEEPIDLE, setOption.TCP_KEEPINTERVAL, setOption.TCP_KEEPCOUNT are not granted."
6+
}

http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
import software.amazon.awssdk.metrics.MetricCollector;
102102
import software.amazon.awssdk.metrics.NoOpMetricCollector;
103103
import software.amazon.awssdk.utils.AttributeMap;
104+
import software.amazon.awssdk.utils.ClassLoaderHelper;
104105
import software.amazon.awssdk.utils.Logger;
105106
import software.amazon.awssdk.utils.Validate;
106107

@@ -543,6 +544,12 @@ public interface Builder extends SdkHttpClient.Builder<Apache5HttpClient.Builder
543544
}
544545

545546
private static final class DefaultBuilder implements Builder {
547+
private static final String[] REQUIRED_TCP_KEEPALIVE_PERMISSIONS = {
548+
"setOption.TCP_KEEPIDLE",
549+
"setOption.TCP_KEEPINTERVAL",
550+
"setOption.TCP_KEEPCOUNT"
551+
};
552+
546553
private final AttributeMap.Builder standardOptions = AttributeMap.builder();
547554
private Registry<AuthSchemeFactory> authSchemeRegistry;
548555
private ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder().build();
@@ -744,8 +751,37 @@ public void setAuthSchemeProviderRegistry(Registry<AuthSchemeFactory> authScheme
744751
public SdkHttpClient buildWithDefaults(AttributeMap serviceDefaults) {
745752
AttributeMap resolvedOptions = standardOptions.build().merge(serviceDefaults).merge(
746753
SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS);
754+
checkTcpKeepAlivePermissions();
747755
return new Apache5HttpClient(this, resolvedOptions);
748756
}
757+
758+
/**
759+
* Fails fast if a SecurityManager is active but denies the {@code jdk.net.NetworkPermission} entries
760+
* that Apache HC5 requires for its default TCP keepalive socket options.
761+
* No-op when no SecurityManager is installed (including Java 24+).
762+
*/
763+
private static void checkTcpKeepAlivePermissions() {
764+
SecurityManager sm = System.getSecurityManager();
765+
if (sm == null) {
766+
return;
767+
}
768+
769+
try {
770+
Class<?> permClass = ClassLoaderHelper.loadClass("jdk.net.NetworkPermission", Apache5HttpClient.class);
771+
for (String permName : REQUIRED_TCP_KEEPALIVE_PERMISSIONS) {
772+
java.security.Permission perm =
773+
(java.security.Permission) permClass.getConstructor(String.class).newInstance(permName);
774+
sm.checkPermission(perm);
775+
}
776+
} catch (SecurityException e) {
777+
throw new IllegalStateException(
778+
"Apache5HttpClient requires jdk.net.NetworkPermission for \""
779+
+ String.join("\", \"", REQUIRED_TCP_KEEPALIVE_PERMISSIONS)
780+
+ "\" when a SecurityManager is active.", e);
781+
} catch (Exception e) {
782+
log.warn(() -> "Unable to verify TCP keepalive permissions: " + e.getMessage(), e);
783+
}
784+
}
749785
}
750786

751787
private static class ApacheConnectionManagerFactory {

0 commit comments

Comments
 (0)