package cz.trask.adfs; import java.io.FileInputStream; import java.net.InetSocketAddress; import java.security.KeyStore; import java.util.List; import java.util.concurrent.Executors; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.fasterxml.jackson.databind.ObjectMapper; import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsServer; import cz.trask.adfs.config.AppConfig; import cz.trask.adfs.config.AppConfig.ContextConfig; import cz.trask.adfs.config.ConfigurationManager; import cz.trask.adfs.context.BaseContextHandler; import cz.trask.adfs.service.AdfsTokenService; public class AdfsAuthMsServer { private static final Logger logger = LogManager.getLogger(AdfsAuthMsServer.class); private final HttpServer server; public AdfsAuthMsServer() throws Exception { logger.debug("Initializing AdfsAuthMsServer"); ConfigurationManager configurationManager = ConfigurationManager.load(); AppConfig config = configurationManager.getConfig(); ObjectMapper objectMapper = new ObjectMapper(); AdfsTokenService tokenService = new AdfsTokenService(config.getAdfs(), objectMapper); this.server = createServer(config); applySslTrustProperties(config); List contexts = config.getServer().getContexts().getContext(); for (ContextConfig contextConfig : contexts) { logger.debug("Creating context: {} -> {}", contextConfig.getPath(), contextConfig.getClassName()); BaseContextHandler handler = instantiateHandler(contextConfig.getClassName()); handler.init(config, tokenService, objectMapper); server.createContext(contextConfig.getPath(), handler); } server.setExecutor(Executors.newFixedThreadPool(config.getServer().getThreads())); } public static void main(String[] args) throws Exception { try { AdfsAuthMsServer server = new AdfsAuthMsServer(); server.start(); } catch (Exception e) { logger.error("Failed to start ADFS auth microservice", e); System.exit(1); } } public void start() { server.start(); logger.info("ADFS auth microservice started on {}", server.getAddress()); } private void applySslTrustProperties(AppConfig config) { if (config.getTrustStore() != null && !config.getTrustStore().isBlank()) { logger.info("Setting javax.net.ssl.trustStore to {}", config.getTrustStore()); System.setProperty("javax.net.ssl.trustStore", config.getTrustStore()); if (config.getTrustStorePassword() != null) { System.setProperty("javax.net.ssl.trustStorePassword", config.getTrustStorePassword()); } } } private HttpServer createServer(AppConfig config) throws Exception { String type = config.getServer().getType(); int port = config.getServer().getPort(); if ("https".equalsIgnoreCase(type)) { HttpsServer httpsServer = HttpsServer.create(new InetSocketAddress(port), 0); httpsServer.setHttpsConfigurator(new HttpsConfigurator(buildSslContext(config))); return httpsServer; } return HttpServer.create(new InetSocketAddress(port), 0); } private SSLContext buildSslContext(AppConfig config) throws Exception { AppConfig.TlsConfig tlsConfig = config.getServer().getTls(); if (tlsConfig == null || tlsConfig.getPath() == null || tlsConfig.getPassphrase() == null) { throw new IllegalArgumentException("TLS configuration is required for https server.type"); } KeyStore keyStore = KeyStore.getInstance("JKS"); try (FileInputStream inputStream = new FileInputStream(tlsConfig.getPath())) { keyStore.load(inputStream, tlsConfig.getPassphrase().toCharArray()); } char[] privateKeyPassphrase = tlsConfig.getPrivatekey() != null && tlsConfig.getPrivatekey().getPassphrase() != null ? tlsConfig.getPrivatekey().getPassphrase().toCharArray() : tlsConfig.getPassphrase().toCharArray(); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(keyStore, privateKeyPassphrase); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509"); trustManagerFactory.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext; } private BaseContextHandler instantiateHandler(String className) throws Exception { if (className == null || className.isBlank()) { throw new IllegalArgumentException("Context handler class is missing."); } Class handlerClass = Class.forName(className); Object instance = handlerClass.getDeclaredConstructor().newInstance(); if (!(instance instanceof BaseContextHandler)) { throw new IllegalArgumentException("Class " + className + " is not a BaseContextHandler"); } return (BaseContextHandler) instance; } }