/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.rampart;

import static com.google.common.truth.Truth.assertAbout;
import static org.apache.axiom.truth.xml.XMLTruth.xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.testutils.ClientHelper;
import org.apache.axis2.testutils.JettyServer;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.io.IOUtils;
import org.apache.neethi.Policy;
import org.apache.rampart.policy.model.KerberosConfig;
import org.apache.rampart.policy.model.RampartConfig;
import org.apache.rampart.util.KerberosServer;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;

/**
 * Tests Kerberos authentication over transport binding using a Kerberos token as supporting endorsing token.
 * The test will use Apache DS Kerberos server, see {@link KerberosServer}.
 * 
 * The test is tailored for Oracle Java execution since it uses <code>com.sun.security.auth.module.Krb5LoginModule</code> JAAS login module for Kerberos authentication.
 */
public class RampartKerberosTest {

    /**
     * Java system property for setting JAAS configuration file: {@value}
     */
    public static final String JAAS_CONF_SYS_PROP = "java.security.auth.login.config";
    
    /**
     * Java system property for setting Kerberos 5 configuration file: {@value}
     */
    public static final String KRB5_CONF_SYS_PROP = "java.security.krb5.conf";
    
    /**
     * JAAS configuration file to use: {@value}
     * <p>
     * Contains Kerberos login module entries for authenticating client and server principals:
     * </p>
     */
    public static final String KERBEROS_JAAS_CONF = "src/test/resources/kerberos/jaas.conf";
    
    /**
     * Kerberos configuration file <b>template</b> to use: {@value}
     * <p>
     * Specifies the Kerberos realm and KDC server to use, the configuration must contain a <code>KDC_PORT</code> literal
     * which will be replaced with actual KDC server port.
     * </p>
     */
    public static final String KERBEROS_CONF_TEMPLATE = "src/test/resources/kerberos/krb5.conf.template";
    
    /**
     * A token literal in kerberos5 configuration file template that must be replaced with actual KDC port value: {@value}
     */
    public static final String KERBEROS_CONF_KDC_PORT_TOKEN = "KDC_PORT";
    
    @ClassRule
    public static final JettyServer server = new JettyServer("target/test-resources/rampart_service_repo", true);
    
    @ClassRule
    public static final ClientHelper clientHelper = new ClientHelper(server, "target/test-resources/rampart_client_repo") {
        @Override
        protected void configureServiceClient(ServiceClient serviceClient) throws Exception {
            int timeout = 200000;
            serviceClient.getOptions().setTimeOutInMilliSeconds(timeout);
            serviceClient.getOptions().setProperty(HTTPConstants.SO_TIMEOUT, timeout);
            serviceClient.getOptions().setProperty(HTTPConstants.CONNECTION_TIMEOUT, timeout);

            serviceClient.engageModule("addressing");
            serviceClient.engageModule("rampart");
        }
    };
    
    @ClassRule
    public static final KerberosServer kerberosServer = new KerberosServer();
    
    /**
     * Stores any original JAAS configuration set via {@link #JAAS_CONF_SYS_PROP} property to restore it after test execution.
     */
    protected String jaasConf;
    
    /**
     * Stores any original Kerberos 5 configuration set via {@link #KRB5_CONF_SYS_PROP} property to restore it after test execution.
     */
    protected String krb5Conf;
    
    private static OMElement getEchoElement() {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace(
                "http://example1.org/example1", "example1");
        OMElement method = fac.createOMElement("echo", omNs);
        OMElement value = fac.createOMElement("Text", omNs);
        value.addChild(fac.createOMText(value, "Testing Rampart with WS-SecPolicy"));
        method.addChild(value);

        return method;
    }

    @Test
    public void testKerberosOverTransportKeytab() throws Exception {
        final String serviceName = "KerberosOverTransportKeytab";
        
        ServiceClient serviceClient = clientHelper.createServiceClient(serviceName, null, null);

        System.out.println("Testing WS-Sec: Kerberos scenario: " + serviceName);
                
        
        RampartConfig rampartConfig = new RampartConfig();
        KerberosConfig kerberosConfig = new KerberosConfig();
        rampartConfig.setKerberosConfig(kerberosConfig);

        kerberosConfig.setJaasContext(serviceName + "Client");        

        Policy policy = new Policy();
        policy.addAssertion(rampartConfig);                
        serviceClient.getAxisService().getPolicySubject().attachPolicyComponent(policy);
        
        //Blocking invocation
        QName operation = new QName("http://rampart.apache.org", "echo");
        OMElement echoElement = getEchoElement();
        OMElement result = serviceClient.sendReceive(operation, echoElement);
        assertAbout(xml()).that(result).ignoringNamespaceDeclarations().hasSameContentAs(echoElement);
    }
    
    @Test
    public void testKerberosOverTransportPWCB() throws Exception {
        final String serviceName = "KerberosOverTransportPWCB";
        
        ServiceClient serviceClient = clientHelper.createServiceClient(serviceName, null, null);

        System.out.println("Testing WS-Sec: Kerberos scenario: " + serviceName);

        RampartConfig rampartConfig = new RampartConfig();
        rampartConfig.setUser("alice");        
        rampartConfig.setPwCbClass(org.apache.rahas.PWCallback.class.getName());
        
        KerberosConfig kerberosConfig = new KerberosConfig();
        rampartConfig.setKerberosConfig(kerberosConfig);

        kerberosConfig.setJaasContext(serviceName + "Client");

        Policy policy = new Policy();
        policy.addAssertion(rampartConfig);        
        serviceClient.getAxisService().getPolicySubject().attachPolicyComponent(policy);
        
        //Blocking invocation
        QName operation = new QName("http://rampart.apache.org", "echo");
        OMElement echoElement = getEchoElement();
        OMElement result = serviceClient.sendReceive(operation, echoElement);
        assertAbout(xml()).that(result).ignoringNamespaceDeclarations().hasSameContentAs(echoElement);
    }
    
    @Test
    public void testKerberosDelegation() throws Exception {
        final String serviceName = "KerberosDelegation";

        ServiceClient serviceClient = clientHelper.createServiceClient(serviceName, null, null);

        System.out.println("Testing WS-Sec: Kerberos scenario: " + serviceName);
                
        
        RampartConfig rampartConfig = new RampartConfig();
        KerberosConfig kerberosConfig = new KerberosConfig();
        rampartConfig.setKerberosConfig(kerberosConfig);

        kerberosConfig.setJaasContext(serviceName + "Client");  
        kerberosConfig.setRequstCredentialDelegation(true);

        Policy policy = new Policy();
        policy.addAssertion(rampartConfig);                
        serviceClient.getAxisService().getPolicySubject().attachPolicyComponent(policy);
        
        //Blocking invocation
        QName operation = new QName("http://rampart.apache.org", "echo");
        OMElement echoElement = getEchoElement();
        OMElement result = serviceClient.sendReceive(operation, echoElement);
        assertAbout(xml()).that(result).ignoringNamespaceDeclarations().hasSameContentAs(echoElement);
    }
    
    @Before
    public void setUp() throws Exception {
        System.setProperty("sun.security.krb5.debug", "true");
        System.setProperty("sun.security.jgss.debug", "true");
        
        //configure JGSS
        krb5Conf = System.getProperty(KRB5_CONF_SYS_PROP);
        
        File krb5ConfFile = generateKerberosConf();
        System.out.println("Using Kerberos configuration file: " + krb5ConfFile.getAbsolutePath());
        System.setProperty(KRB5_CONF_SYS_PROP, krb5ConfFile.getAbsolutePath());
        
        //configure JAAS
        jaasConf = System.getProperty(JAAS_CONF_SYS_PROP);
        System.out.println("Using Kerberos JAAS configuration file: " + new File(KERBEROS_JAAS_CONF).getAbsolutePath());
        System.setProperty(JAAS_CONF_SYS_PROP, KERBEROS_JAAS_CONF);
    }

    @After
    public void tearDown() throws Exception {
        if (jaasConf != null) {
            System.setProperty(JAAS_CONF_SYS_PROP, jaasConf);
        }
        else {
            System.clearProperty(JAAS_CONF_SYS_PROP);
        }
        
        if (krb5Conf != null) {
            System.setProperty(KRB5_CONF_SYS_PROP, krb5Conf);
        }
        else {
            System.clearProperty(KRB5_CONF_SYS_PROP);
        }
    }
    
    /**
     * Generates a Kerberos configuration file (krb5.conf) out of the {@link #KERBEROS_CONF_TEMPLATE} file,
     * replacing the {@link #KERBEROS_CONF_KDC_PORT_TOKEN} with actual KDC port.
     * 
     * @return The generated Kerberos configuration file. It will be generated under the following path:
     * <code>target/tmp/{thisClassSimpleName}_krb5.conf</code>
     * 
     * @throws IOException 
     */
    protected File generateKerberosConf() throws IOException {
        File tmpDir = new File("target" + File.separator + "tmp");
        if (!tmpDir.exists() && !tmpDir.mkdirs()) {
            throw new RuntimeException("Failed to create temp directory: " + tmpDir.getAbsolutePath());
        }
        
        File krb5ConfTemplate = new File(KERBEROS_CONF_TEMPLATE);
        if (!krb5ConfTemplate.exists()) {
            throw new IllegalArgumentException("Cannot find kerberos configuration file template: " + krb5ConfTemplate.getAbsolutePath());
        }
        
        FileInputStream krb5ConfTemplateIn = null;
        String krb5ConfContent;
        try {
            krb5ConfTemplateIn = new FileInputStream(krb5ConfTemplate);
            krb5ConfContent = IOUtils.toString(krb5ConfTemplateIn);
        }
        finally {
            IOUtils.closeQuietly(krb5ConfTemplateIn);
        }
        
        if (krb5ConfContent.indexOf(KERBEROS_CONF_KDC_PORT_TOKEN) == -1) {
            throw new IllegalArgumentException(String.format("Cannot find any %s token in kerberos configuration file template: %s",
                    KERBEROS_CONF_KDC_PORT_TOKEN, krb5ConfTemplate.getAbsolutePath()));
        }
            
        krb5ConfContent = krb5ConfContent.replace(KERBEROS_CONF_KDC_PORT_TOKEN, String.valueOf(kerberosServer.getPort()));
        
        File krb5Conf = new File(tmpDir, this.getClass().getSimpleName() + "_krb5.conf");
        FileOutputStream krb5ConfOut = null;
        try {
            krb5ConfOut = new FileOutputStream(krb5Conf);
            IOUtils.write(krb5ConfContent, krb5ConfOut);
        }
        finally {
            IOUtils.closeQuietly(krb5ConfOut);
        }
        
        return krb5Conf;
    }
}
