mirror of https://github.com/apache/nifi.git
NIFI-13639 Replaced OkHttp with web-client-api in web-security
This closes #9157 Signed-off-by: Joseph Witt <joewitt@apache.org>
This commit is contained in:
parent
98f55b21b8
commit
7348740ecc
|
@ -299,8 +299,14 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-web-client-api</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-web-client</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
|
|
|
@ -73,7 +73,6 @@ import org.springframework.security.saml2.provider.service.web.authentication.lo
|
|||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509ExtendedTrustManager;
|
||||
import java.time.Duration;
|
||||
|
@ -95,8 +94,6 @@ public class SamlAuthenticationSecurityConfiguration {
|
|||
|
||||
private final LogoutRequestManager logoutRequestManager;
|
||||
|
||||
private final SSLContext sslContext;
|
||||
|
||||
private final X509ExtendedKeyManager keyManager;
|
||||
|
||||
private final X509ExtendedTrustManager trustManager;
|
||||
|
@ -105,14 +102,12 @@ public class SamlAuthenticationSecurityConfiguration {
|
|||
@Autowired final NiFiProperties properties,
|
||||
@Autowired final BearerTokenProvider bearerTokenProvider,
|
||||
@Autowired final LogoutRequestManager logoutRequestManager,
|
||||
@Autowired(required = false) final SSLContext sslContext,
|
||||
@Autowired(required = false) final X509ExtendedKeyManager keyManager,
|
||||
@Autowired(required = false) final X509ExtendedTrustManager trustManager
|
||||
) {
|
||||
this.properties = Objects.requireNonNull(properties, "Properties required");
|
||||
this.bearerTokenProvider = Objects.requireNonNull(bearerTokenProvider, "Bearer Token Provider required");
|
||||
this.logoutRequestManager = Objects.requireNonNull(logoutRequestManager, "Logout Request Manager required");
|
||||
this.sslContext = sslContext;
|
||||
this.keyManager = keyManager;
|
||||
this.trustManager = trustManager;
|
||||
}
|
||||
|
@ -320,7 +315,7 @@ public class SamlAuthenticationSecurityConfiguration {
|
|||
@Bean
|
||||
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
|
||||
return properties.isSamlEnabled()
|
||||
? new StandardRelyingPartyRegistrationRepository(properties, sslContext, keyManager, trustManager)
|
||||
? new StandardRelyingPartyRegistrationRepository(properties, keyManager, trustManager)
|
||||
: getDisabledRelyingPartyRegistrationRepository();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,26 +16,27 @@
|
|||
*/
|
||||
package org.apache.nifi.web.security.saml2.registration;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import org.apache.nifi.util.FormatUtils;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.web.client.StandardWebClientService;
|
||||
import org.apache.nifi.web.client.api.HttpResponseEntity;
|
||||
import org.apache.nifi.web.client.api.HttpResponseStatus;
|
||||
import org.apache.nifi.web.client.api.WebClientService;
|
||||
import org.apache.nifi.web.client.ssl.TlsContext;
|
||||
import org.apache.nifi.web.security.saml2.SamlConfigurationException;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -46,21 +47,23 @@ class StandardRegistrationBuilderProvider implements RegistrationBuilderProvider
|
|||
|
||||
private static final String HTTP_SCHEME_PREFIX = "http";
|
||||
|
||||
private static final String TLS_PROTOCOL = "TLS";
|
||||
|
||||
private static final ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
|
||||
private final NiFiProperties properties;
|
||||
|
||||
private final SSLContext sslContext;
|
||||
private final X509KeyManager keyManager;
|
||||
|
||||
private final X509TrustManager trustManager;
|
||||
|
||||
public StandardRegistrationBuilderProvider(
|
||||
final NiFiProperties properties,
|
||||
final SSLContext sslContext,
|
||||
final X509KeyManager keyManager,
|
||||
final X509TrustManager trustManager
|
||||
) {
|
||||
this.properties = Objects.requireNonNull(properties, "Properties required");
|
||||
this.sslContext = sslContext;
|
||||
this.keyManager = keyManager;
|
||||
this.trustManager = trustManager;
|
||||
}
|
||||
|
||||
|
@ -91,25 +94,26 @@ class StandardRegistrationBuilderProvider implements RegistrationBuilderProvider
|
|||
}
|
||||
|
||||
private InputStream getRemoteInputStream(final String metadataUrl) {
|
||||
final OkHttpClient client = getHttpClient();
|
||||
final WebClientService webClientService = getWebClientService();
|
||||
|
||||
final URI uri = URI.create(metadataUrl);
|
||||
|
||||
final Request request = new Request.Builder().get().url(metadataUrl).build();
|
||||
final Call call = client.newCall(request);
|
||||
try {
|
||||
final Response response = call.execute();
|
||||
if (response.isSuccessful()) {
|
||||
final ResponseBody body = Objects.requireNonNull(response.body(), "SAML Metadata response not found");
|
||||
return body.byteStream();
|
||||
final HttpResponseEntity responseEntity = webClientService.get().uri(uri).retrieve();
|
||||
final int statusCode = responseEntity.statusCode();
|
||||
|
||||
if (HttpResponseStatus.OK.getCode() == statusCode) {
|
||||
return responseEntity.body();
|
||||
} else {
|
||||
response.close();
|
||||
throw new SamlConfigurationException(String.format("SAML Metadata retrieval failed [%s] HTTP %d", metadataUrl, response.code()));
|
||||
responseEntity.close();
|
||||
throw new SamlConfigurationException(String.format("SAML Metadata retrieval failed [%s] HTTP %d", metadataUrl, statusCode));
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new SamlConfigurationException(String.format("SAML Metadata retrieval failed [%s]", metadataUrl), e);
|
||||
}
|
||||
}
|
||||
|
||||
private OkHttpClient getHttpClient() {
|
||||
private WebClientService getWebClientService() {
|
||||
final Duration connectTimeout = Duration.ofMillis(
|
||||
(long) FormatUtils.getPreciseTimeDuration(properties.getSamlHttpClientConnectTimeout(), TimeUnit.MILLISECONDS)
|
||||
);
|
||||
|
@ -117,15 +121,29 @@ class StandardRegistrationBuilderProvider implements RegistrationBuilderProvider
|
|||
(long) FormatUtils.getPreciseTimeDuration(properties.getSamlHttpClientReadTimeout(), TimeUnit.MILLISECONDS)
|
||||
);
|
||||
|
||||
final OkHttpClient.Builder builder = new OkHttpClient.Builder()
|
||||
.connectTimeout(connectTimeout)
|
||||
.readTimeout(readTimeout);
|
||||
final StandardWebClientService webClientService = new StandardWebClientService();
|
||||
webClientService.setConnectTimeout(connectTimeout);
|
||||
webClientService.setReadTimeout(readTimeout);
|
||||
|
||||
if (NIFI_TRUST_STORE_STRATEGY.equals(properties.getSamlHttpClientTruststoreStrategy())) {
|
||||
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||
builder.sslSocketFactory(sslSocketFactory, trustManager);
|
||||
webClientService.setTlsContext(new TlsContext() {
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
return TLS_PROTOCOL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509TrustManager getTrustManager() {
|
||||
return trustManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<X509KeyManager> getKeyManager() {
|
||||
return Optional.ofNullable(keyManager);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
return webClientService;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.springframework.security.saml2.core.Saml2X509Credential;
|
|||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509ExtendedTrustManager;
|
||||
import java.security.Principal;
|
||||
|
@ -34,6 +33,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Standard implementation of Relying Party Registration Repository based on NiFi Properties
|
||||
*/
|
||||
|
@ -52,8 +52,6 @@ public class StandardRelyingPartyRegistrationRepository implements RelyingPartyR
|
|||
|
||||
private final NiFiProperties properties;
|
||||
|
||||
private final SSLContext sslContext;
|
||||
|
||||
private final X509ExtendedTrustManager trustManager;
|
||||
|
||||
private final X509ExtendedKeyManager keyManager;
|
||||
|
@ -63,19 +61,16 @@ public class StandardRelyingPartyRegistrationRepository implements RelyingPartyR
|
|||
/**
|
||||
* Standard implementation builds a Registration based on NiFi Properties and returns the same instance for all queries
|
||||
*
|
||||
* @param sslContext SSL Context loaded from properties
|
||||
* @param keyManager Key Manager loaded from properties
|
||||
* @param trustManager Trust manager loaded from properties
|
||||
* @param properties NiFi Application Properties
|
||||
*/
|
||||
public StandardRelyingPartyRegistrationRepository(
|
||||
final NiFiProperties properties,
|
||||
final SSLContext sslContext,
|
||||
final X509ExtendedKeyManager keyManager,
|
||||
final X509ExtendedTrustManager trustManager
|
||||
) {
|
||||
this.properties = properties;
|
||||
this.sslContext = sslContext;
|
||||
this.keyManager = keyManager;
|
||||
this.trustManager = trustManager;
|
||||
this.relyingPartyRegistration = getRelyingPartyRegistration();
|
||||
|
@ -87,7 +82,7 @@ public class StandardRelyingPartyRegistrationRepository implements RelyingPartyR
|
|||
}
|
||||
|
||||
private RelyingPartyRegistration getRelyingPartyRegistration() {
|
||||
final RegistrationBuilderProvider registrationBuilderProvider = new StandardRegistrationBuilderProvider(properties, sslContext, trustManager);
|
||||
final RegistrationBuilderProvider registrationBuilderProvider = new StandardRegistrationBuilderProvider(properties, keyManager, trustManager);
|
||||
final RelyingPartyRegistration.Builder builder = registrationBuilderProvider.getRegistrationBuilder();
|
||||
|
||||
builder.registrationId(Saml2RegistrationProperty.REGISTRATION_ID.getProperty());
|
||||
|
|
|
@ -20,10 +20,12 @@ import okhttp3.HttpUrl;
|
|||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.nifi.security.util.SslContextFactory;
|
||||
import org.apache.nifi.security.ssl.StandardKeyManagerBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardTrustManagerBuilder;
|
||||
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
|
||||
import org.apache.nifi.security.util.TlsConfiguration;
|
||||
import org.apache.nifi.security.util.TlsException;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.web.security.saml2.SamlConfigurationException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
@ -34,11 +36,16 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes
|
|||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509ExtendedTrustManager;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
|
@ -102,10 +109,15 @@ class StandardRegistrationBuilderProviderTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetRegistrationBuilderHttpsUrl() throws IOException, TlsException {
|
||||
void testGetRegistrationBuilderHttpsUrl() throws IOException {
|
||||
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
|
||||
final SSLContext sslContext = Objects.requireNonNull(SslContextFactory.createSslContext(tlsConfiguration));
|
||||
final X509TrustManager trustManager = SslContextFactory.getX509TrustManager(tlsConfiguration);
|
||||
final X509KeyManager keyManager = getKeyManager(tlsConfiguration);
|
||||
final X509TrustManager trustManager = getTrustManager(tlsConfiguration);
|
||||
final SSLContext sslContext = new StandardSslContextBuilder()
|
||||
.keyManager(keyManager)
|
||||
.keyPassword(tlsConfiguration.getKeyPassword().toCharArray())
|
||||
.trustManager(trustManager)
|
||||
.build();
|
||||
|
||||
final SSLSocketFactory sslSocketFactory = Objects.requireNonNull(sslContext.getSocketFactory());
|
||||
mockWebServer.useHttps(sslSocketFactory, PROXY_DISABLED);
|
||||
|
@ -117,7 +129,7 @@ class StandardRegistrationBuilderProviderTest {
|
|||
|
||||
final NiFiProperties properties = getProperties(metadataUrl, tlsConfiguration);
|
||||
|
||||
assertRegistrationFound(properties, sslContext, trustManager);
|
||||
assertRegistrationFound(properties, keyManager, trustManager);
|
||||
}
|
||||
|
||||
private String getMetadataUrl() {
|
||||
|
@ -125,14 +137,41 @@ class StandardRegistrationBuilderProviderTest {
|
|||
return url.toString();
|
||||
}
|
||||
|
||||
private void assertRegistrationFound(final NiFiProperties properties, final SSLContext sslContext, final X509TrustManager trustManager) {
|
||||
final StandardRegistrationBuilderProvider provider = new StandardRegistrationBuilderProvider(properties, sslContext, trustManager);
|
||||
private void assertRegistrationFound(final NiFiProperties properties, final X509KeyManager keyManager, final X509TrustManager trustManager) {
|
||||
final StandardRegistrationBuilderProvider provider = new StandardRegistrationBuilderProvider(properties, keyManager, trustManager);
|
||||
final RelyingPartyRegistration.Builder builder = provider.getRegistrationBuilder();
|
||||
|
||||
final RelyingPartyRegistration registration = builder.build();
|
||||
assertEquals(Saml2MessageBinding.POST, registration.getAssertionConsumerServiceBinding());
|
||||
}
|
||||
|
||||
private X509ExtendedKeyManager getKeyManager(final TlsConfiguration tlsConfiguration) throws IOException {
|
||||
try (InputStream inputStream = new FileInputStream(tlsConfiguration.getKeystorePath())) {
|
||||
final KeyStore keyStore = new StandardKeyStoreBuilder()
|
||||
.inputStream(inputStream)
|
||||
.password(tlsConfiguration.getKeystorePassword().toCharArray())
|
||||
.type(tlsConfiguration.getKeystoreType().getType())
|
||||
.build();
|
||||
|
||||
return new StandardKeyManagerBuilder()
|
||||
.keyStore(keyStore)
|
||||
.keyPassword(tlsConfiguration.getFunctionalKeyPassword().toCharArray())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private X509ExtendedTrustManager getTrustManager(final TlsConfiguration tlsConfiguration) throws IOException {
|
||||
try (InputStream inputStream = new FileInputStream(tlsConfiguration.getTruststorePath())) {
|
||||
final KeyStore trustStore = new StandardKeyStoreBuilder()
|
||||
.inputStream(inputStream)
|
||||
.password(tlsConfiguration.getTruststorePassword().toCharArray())
|
||||
.type(tlsConfiguration.getTruststoreType().getType())
|
||||
.build();
|
||||
|
||||
return new StandardTrustManagerBuilder().trustStore(trustStore).build();
|
||||
}
|
||||
}
|
||||
|
||||
private NiFiProperties getProperties(final String metadataUrl) {
|
||||
final Properties properties = new Properties();
|
||||
properties.setProperty(NiFiProperties.SECURITY_USER_SAML_IDP_METADATA_URL, metadataUrl);
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.apache.nifi.web.security.saml2.registration;
|
|||
|
||||
import org.apache.nifi.security.ssl.StandardKeyManagerBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardTrustManagerBuilder;
|
||||
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
|
||||
import org.apache.nifi.security.util.TlsConfiguration;
|
||||
|
@ -28,7 +27,6 @@ import org.opensaml.xmlsec.signature.support.SignatureConstants;
|
|||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509ExtendedTrustManager;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
@ -59,7 +57,7 @@ class StandardRelyingPartyRegistrationRepositoryTest {
|
|||
@Test
|
||||
void testFindByRegistrationId() {
|
||||
final NiFiProperties properties = getProperties();
|
||||
final StandardRelyingPartyRegistrationRepository repository = new StandardRelyingPartyRegistrationRepository(properties, null, null, null);
|
||||
final StandardRelyingPartyRegistrationRepository repository = new StandardRelyingPartyRegistrationRepository(properties, null, null);
|
||||
|
||||
final RelyingPartyRegistration registration = repository.findByRegistrationId(Saml2RegistrationProperty.REGISTRATION_ID.getProperty());
|
||||
|
||||
|
@ -81,10 +79,9 @@ class StandardRelyingPartyRegistrationRepositoryTest {
|
|||
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
|
||||
final X509ExtendedKeyManager keyManager = getKeyManager(tlsConfiguration);
|
||||
final X509ExtendedTrustManager trustManager = getTrustManager(tlsConfiguration);
|
||||
final SSLContext sslContext = new StandardSslContextBuilder().keyManager(keyManager).trustManager(trustManager).build();
|
||||
|
||||
final NiFiProperties properties = getSingleLogoutProperties(tlsConfiguration);
|
||||
final StandardRelyingPartyRegistrationRepository repository = new StandardRelyingPartyRegistrationRepository(properties, sslContext, keyManager, trustManager);
|
||||
final StandardRelyingPartyRegistrationRepository repository = new StandardRelyingPartyRegistrationRepository(properties, keyManager, trustManager);
|
||||
|
||||
final RelyingPartyRegistration registration = repository.findByRegistrationId(Saml2RegistrationProperty.REGISTRATION_ID.getProperty());
|
||||
|
||||
|
|
Loading…
Reference in New Issue