wso2 / kubernetes-is

Kubernetes and Helm resources for WSO2 Identity Server
Apache License 2.0
65 stars 114 forks source link

Improvement #241

Open angeloimm opened 4 years ago

angeloimm commented 4 years ago

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:

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