Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement #241

Open
angeloimm opened this issue Jul 23, 2020 · 0 comments
Open

Improvement #241

angeloimm opened this issue Jul 23, 2020 · 0 comments

Comments

@angeloimm
Copy link

Label: Improvement

Descritption: Enabled X509 Authenticator

Hi there. We noticed that the X509 Authenticator is not managed in the helm Chart, so we did some modification to the chart and to the catalilna-server.xml.j2 template according to what suggested here

We modified the following files:

  • identity-server-ingress.yaml: we added
    • a configuration for the nginx ingres controller in order to pass the X509 certificate to the server in http header without checking it (it's server side that is X509Authenticator to verify the certificate). We need to better verify it
    • the port 8443 for the path /x509-certificate-servlet
  • identity-server-service.yaml: we added the port 8443
  • identity-server-deployment.yaml: we added the port 8443
  • the values.yaml in deployment.toml section where we added the X509 Authenticator enabling.
    More deeply, in the values.yml we added the following:
            [custom_trasport.x509.properties]
            #protocols="HTTP/1.1"
            protocol="org.apache.coyote.http11.Http11NioProtocol"
            port="8443"
            maxThreads="200"
            scheme="https"
            secure=true
            SSLEnabled=true
            keystoreFile="wso2_custom.jks"
            keystorePass="pwd"
            truststoreFile="truststore.jks"
            truststorePass="truststore_pwd"
            bindOnInit=false
            clientAuth="want"
            sslProtocol = "TLS"
            proxyPort="443"

            [transport.https.properties]
            proxyPort="443"

            [authentication.authenticator.x509_certificate.parameters]
            name ="x509CertificateAuthenticator"
            enable=true
            AuthenticationEndpoint="https://$ref{server.hostname}/x509-certificate-servlet"
            username= "CN"
            SearchAllUserStores="false"
            EnforceSelfRegistration = "false"
            SearchAndValidateUserLocalStores = "false"
            EidasTruststoreFile="truststore.jks"
            EidasTruststorPass="truststore_pwd"

Lastly we modified the org.wso2.carbon.identity.authenticator.x509Certificate.X509CertificateAuthenticator in order to check is the certificate is present in HTTP header and, if present, to verify it

This is the alpha release of code we added in the org.wso2.carbon.identity.authenticator.x509Certificate.X509CertificateAuthenticator.processAuthenticationResponse(HttpServletRequest, HttpServletResponse, AuthenticationContext) method:

Object object = httpServletRequest.getAttribute(X509CertificateConstants.X_509_CERTIFICATE);
		if( object == null ) {
			if( log.isInfoEnabled() ) {
				log.info("Attributo "+X509CertificateConstants.X_509_CERTIFICATE+" NON trovato in request. Controllo la presenza dell'header");
			}
			String xSslCert = httpServletRequest.getHeader("x-ssl-cert");
			if( xSslCert != null ) {
				if( log.isInfoEnabled() ) {
					log.info("Trovato certificato come header http da decodificare in UTF-8");
				}
				
				FileInputStream fis = null;
				try {
					CertificateFactory cf = CertificateFactory.getInstance("X.509");
					synchronized (cf) {
						String decoded = URLDecoder.decode(xSslCert, "UTF-8");
						Certificate certi = cf.generateCertificate(new ByteArrayInputStream(decoded.getBytes()));
						if (certi instanceof X509Certificate) {
							X509Certificate certificato = (X509Certificate) certi;
							certificato.checkValidity();//Controllo se non scaduto
							String eidasTrustStoreFile = getAuthenticatorConfig().getParameterMap().get("EidasTruststoreFile");
							String eidasTrustStorePwd = getAuthenticatorConfig().getParameterMap().get("EidasTruststorPass");
							fis = new FileInputStream(new File(eidasTrustStoreFile));
							KeyStore ks = KeyStore.getInstance("JKS");
							ks.load(fis, eidasTrustStorePwd.toCharArray());
							Enumeration<String> aliases = ks.aliases();
							boolean verificato = false;
							while (aliases.hasMoreElements()) {
								String alias = (String) aliases.nextElement();
								Certificate cert = ks.getCertificate(alias);
								PublicKey pk = cert.getPublicKey();
								try {
									certificato.verify(pk);
									verificato = true;
									break;
								}catch (Exception e) {

								}
							}
							if( verificato ) {
								if( log.isInfoEnabled() ) {
									log.info("Certificato valido");
								}
								X509Certificate[] certs = new X509Certificate[1];
								certs[0] = certificato;
								object = certs;
							}
						}
						else {
							if( log.isWarnEnabled() ) {
								log.warn("CERTIFICATO RECUPERATO COME HEADER HTTP NON X509 "+certi);
							}
						}
					}
				}catch (Exception e) {

					throw new AuthenticationFailedException("Errore nella validazione del certificato da header HTTP", e);
				}
				finally {
					if( fis != null ) {

						try {
							fis.close();
						} catch (IOException e) {
							// ignoro l'eccezione
						}
					}
				}
			}
		}
                //From here original WSO2 source code
		if (object != null) {
			X509Certificate[] certificates;
			if (object instanceof X509Certificate[]) {
				certificates = (X509Certificate[]) object;
			} else {
				throw new AuthenticationFailedException("Exception while casting the X509Certificate");
			}

I attach to the issue all the files.

I hope this can be useful

Angelo
x509_enabling.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant