76
76
import org .elasticsearch .common .CheckedRunnable ;
77
77
import org .elasticsearch .common .Nullable ;
78
78
import org .elasticsearch .common .Strings ;
79
- import org .elasticsearch .common .SuppressForbidden ;
80
79
import org .elasticsearch .common .collect .Tuple ;
81
80
import org .elasticsearch .common .util .concurrent .EsExecutors ;
82
81
import org .elasticsearch .common .util .concurrent .ListenableFuture ;
95
94
import java .net .URI ;
96
95
import java .net .URISyntaxException ;
97
96
import java .net .URL ;
98
-
99
97
import java .net .URLEncoder ;
100
98
import java .nio .charset .Charset ;
101
99
import java .nio .charset .StandardCharsets ;
100
+ import java .nio .file .Files ;
102
101
import java .nio .file .Path ;
103
102
import java .security .AccessController ;
104
103
import java .security .PrivilegedAction ;
111
110
import java .util .concurrent .atomic .AtomicReference ;
112
111
113
112
import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .ALLOWED_CLOCK_SKEW ;
114
- import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_CONNECT_TIMEOUT ;
115
113
import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_CONNECTION_READ_TIMEOUT ;
114
+ import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_CONNECT_TIMEOUT ;
116
115
import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_MAX_CONNECTIONS ;
117
116
import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_MAX_ENDPOINT_CONNECTIONS ;
118
117
import static org .elasticsearch .xpack .core .security .authc .oidc .OpenIdConnectRealmSettings .HTTP_SOCKET_TIMEOUT ;
@@ -142,7 +141,7 @@ public OpenIdConnectAuthenticator(RealmConfig realmConfig, OpenIdConnectProvider
142
141
this .sslService = sslService ;
143
142
this .httpClient = createHttpClient ();
144
143
this .watcherService = watcherService ;
145
- this .idTokenValidator .set (createIdTokenValidator ());
144
+ this .idTokenValidator .set (createIdTokenValidator (true ));
146
145
}
147
146
148
147
// For testing
@@ -314,10 +313,11 @@ private void validateAccessToken(AccessToken accessToken, JWT idToken) {
314
313
* @throws ParseException if the file cannot be parsed
315
314
* @throws IOException if the file cannot be read
316
315
*/
317
- @ SuppressForbidden (reason = "uses toFile" )
318
316
private JWKSet readJwkSetFromFile (String jwkSetPath ) throws IOException , ParseException {
319
317
final Path path = realmConfig .env ().configFile ().resolve (jwkSetPath );
320
- return JWKSet .load (path .toFile ());
318
+ // avoid using JWKSet.loadFile() as it does not close FileInputStream internally
319
+ String jwkSet = new String (Files .readAllBytes (path ), StandardCharsets .UTF_8 );
320
+ return JWKSet .parse (jwkSet );
321
321
}
322
322
323
323
/**
@@ -589,7 +589,7 @@ private CloseableHttpAsyncClient createHttpClient() {
589
589
/*
590
590
* Creates an {@link IDTokenValidator} based on the current Relying Party configuration
591
591
*/
592
- IDTokenValidator createIdTokenValidator () {
592
+ IDTokenValidator createIdTokenValidator (boolean addFileWatcherIfRequired ) {
593
593
try {
594
594
final JWSAlgorithm requestedAlgorithm = rpConfig .getSignatureAlgorithm ();
595
595
final int allowedClockSkew = Math .toIntExact (realmConfig .getSetting (ALLOWED_CLOCK_SKEW ).getMillis ());
@@ -600,12 +600,16 @@ IDTokenValidator createIdTokenValidator() {
600
600
new IDTokenValidator (opConfig .getIssuer (), rpConfig .getClientId (), requestedAlgorithm , clientSecret );
601
601
} else {
602
602
String jwkSetPath = opConfig .getJwkSetPath ();
603
- if (jwkSetPath .startsWith ("https://" )) {
603
+ if (jwkSetPath .startsWith ("http://" )) {
604
+ throw new IllegalArgumentException ("The [http] protocol is not supported as it is insecure. Use [https] instead" );
605
+ } else if (jwkSetPath .startsWith ("https://" )) {
604
606
final JWSVerificationKeySelector keySelector = new JWSVerificationKeySelector (requestedAlgorithm ,
605
607
new ReloadableJWKSource (new URL (jwkSetPath )));
606
608
idTokenValidator = new IDTokenValidator (opConfig .getIssuer (), rpConfig .getClientId (), keySelector , null );
607
609
} else {
608
- setMetadataFileWatcher (jwkSetPath );
610
+ if (addFileWatcherIfRequired ) {
611
+ setMetadataFileWatcher (jwkSetPath );
612
+ }
609
613
final JWKSet jwkSet = readJwkSetFromFile (jwkSetPath );
610
614
idTokenValidator = new IDTokenValidator (opConfig .getIssuer (), rpConfig .getClientId (), requestedAlgorithm , jwkSet );
611
615
}
@@ -620,7 +624,7 @@ IDTokenValidator createIdTokenValidator() {
620
624
private void setMetadataFileWatcher (String jwkSetPath ) throws IOException {
621
625
final Path path = realmConfig .env ().configFile ().resolve (jwkSetPath );
622
626
FileWatcher watcher = new FileWatcher (path );
623
- watcher .addListener (new FileListener (LOGGER , () -> this .idTokenValidator .set (createIdTokenValidator ())));
627
+ watcher .addListener (new FileListener (LOGGER , () -> this .idTokenValidator .set (createIdTokenValidator (false ))));
624
628
watcherService .add (watcher , ResourceWatcherService .Frequency .MEDIUM );
625
629
}
626
630
0 commit comments