madrob commented on a change in pull request #139:
URL: https://github.com/apache/solr/pull/139#discussion_r636972401
##########
File path: solr/core/src/java/org/apache/solr/security/JWTAuthPlugin.java
##########
@@ -199,6 +237,28 @@ public void init(Map<String, Object> pluginConfig) {
lastInitTime = Instant.now();
}
+ /**
+ * Tries for find X509 certificates in the input stream in DER or PEM format.
+ * Supports multiple certs in same stream if multiple PEM certs are
concatenated.
+ * @param trustedCertsStream input stream with the contents of either PEM
(plaintext) or DER (binary) certs
+ * @return collection of found certificates, else throws exception
+ */
+ static Collection<X509Certificate> parsePemToX509Certs(InputStream
trustedCertsStream) {
Review comment:
Maybe this belongs in CryptoKeys? Or some other util class?
##########
File path: solr/core/src/java/org/apache/solr/security/JWTIssuerConfig.java
##########
@@ -335,33 +346,49 @@ public boolean isValid() {
return jwkConfigured > 0;
}
+ public void setTrustedCerts(Collection<X509Certificate> trustedCerts) {
+ this.trustedCerts = trustedCerts;
+ }
+
/**
*
*/
static class HttpsJwksFactory {
private final long jwkCacheDuration;
private final long refreshReprieveThreshold;
+ private Collection<X509Certificate> trustedCerts;
public HttpsJwksFactory(long jwkCacheDuration, long
refreshReprieveThreshold) {
this.jwkCacheDuration = jwkCacheDuration;
this.refreshReprieveThreshold = refreshReprieveThreshold;
}
-
+
+ public HttpsJwksFactory(long jwkCacheDuration, long
refreshReprieveThreshold, Collection<X509Certificate> trustedCerts) {
+ this.jwkCacheDuration = jwkCacheDuration;
+ this.refreshReprieveThreshold = refreshReprieveThreshold;
+ this.trustedCerts = trustedCerts;
+ }
+
/**
* While the class name is HttpsJwks, it actually works with plain http
formatted url as well.
+ *
* @param url the Url to connect to for JWK details.
*/
private HttpsJwks create(String url) {
try {
URL jwksUrl = new URL(url);
checkAllowOutboundHttpConnections(PARAM_JWKS_URL, jwksUrl);
-
} catch (MalformedURLException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Url " +
url + " configured in " + PARAM_JWKS_URL + " is not a valid URL");
}
HttpsJwks httpsJkws = new HttpsJwks(url);
httpsJkws.setDefaultCacheDuration(jwkCacheDuration);
httpsJkws.setRefreshReprieveThreshold(refreshReprieveThreshold);
+ if (trustedCerts != null) {
+ Get getWithCustomTrust = new Get();
+ getWithCustomTrust.setTrustedCertificates(trustedCerts);
+ log.info("Trusting custom SSL certificate(s) for the IdP");
Review comment:
How often does this happen? Is it per user request? Per user session?
Might be too verbose.
##########
File path: solr/solr-ref-guide/src/jwt-authentication-plugin.adoc
##########
@@ -54,6 +54,8 @@ rolesClaim ; What claim id to pull user roles from.
The claim must the
claimsMatch ; JSON object of claims (key) that must match a regular
expression (value). Example: `{ "foo" : "A|B" }` will require the `foo` claim
to be either "A" or "B". ;
adminUiScope ; Define what scope is requested when logging in from
Admin UI ; If not defined, the first scope from `scope` parameter is used
redirectUris ; Valid location(s) for redirect after external
authentication. Takes a string or array of strings. Must be the base URL of
Solr, e.g., https://solr1.example.com:8983/solr/ and must match the list of
redirect URIs registered with the Identity Provider beforehand. ; Defaults to
empty list, i.e., any node is assumed to be a valid redirect target.
+trustedCerts ; One or more X.509 SSL certificates in plaintext PEM or
PKCS#7 formats, that should be trusted when talking to IdPs. Newlines must be
replaced with `\n`. ; Defaults to Java truststore
Review comment:
I'd like to see more explanation when somebody would need this, similar
to what was described in the JIRA, e.g. explain that Jetty's TrustStore is
ignored if running with HTTP with an SSL-terminating proxy/LB/ingress in front.
##########
File path: solr/core/src/test/org/apache/solr/security/JWTAuthPluginTest.java
##########
@@ -477,4 +484,51 @@ public void initWithToplevelAndIssuersCombined() {
// Top-level (name=PRIMARY) issuer config does not need "iss" for back
compat
assertNull(plugin.getPrimaryIssuer().getIss());
}
+
+ @Test
+ public void initWithIdpCertString() {
+ HashMap<String, Object> authConf = new HashMap<>();
+ authConf.put("jwksUrl", "https://127.0.0.1:9999/foo.jwk");
+ authConf.put("trustedCerts", trustedPemCert);
+ plugin = new JWTAuthPlugin();
+ plugin.init(authConf);
+ }
+
+ @Test
+ public void initWithIdpCertPath() {
+ HashMap<String, Object> authConf = new HashMap<>();
+ authConf.put("jwksUrl", "https://127.0.0.1:9999/foo.jwk");
+ authConf.put("trustedCertsFile",
TEST_PATH().resolve("security").resolve("jwt_idpCert.pem").toString());
+ plugin = new JWTAuthPlugin();
+ plugin.init(authConf);
Review comment:
Anything we can do to assert that the generated factory has the correct
trust store?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]