package org.cagrid.cds.inttest; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features; import java.io.File; import java.security.KeyPair; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.net.ssl.KeyManager; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import org.apache.cxf.configuration.security.KeyStoreType; import org.apache.cxf.headers.Header; import org.apache.cxf.jaxb.JAXBDataBinding; import org.cagrid.cds.model.AllowedParties; import org.cagrid.cds.model.CertificateChain; import org.cagrid.cds.model.DelegationIdentifier; import org.cagrid.cds.model.DelegationRequest; import org.cagrid.cds.model.DelegationSigningRequest; import org.cagrid.cds.model.DelegationSigningResponse; import org.cagrid.cds.model.IdentityDelegationPolicy; import org.cagrid.cds.model.ProxyLifetime; import org.cagrid.cds.service.CredentialDelegationService; import org.cagrid.cds.soapclient.CDSSoapClientFactory; import org.cagrid.cds.soapclient.DCSSoapClientFactory; import org.cagrid.cds.util.Utils; import org.cagrid.cds.wsrf.stubs.ApproveDelegationRequest; import org.cagrid.cds.wsrf.stubs.ApproveDelegationResponse; import org.cagrid.cds.wsrf.stubs.CredentialDelegationServicePortType; import org.cagrid.cds.wsrf.stubs.InitiateDelegationRequest; import org.cagrid.cds.wsrf.stubs.InitiateDelegationRequest.Req; import org.cagrid.cds.wsrf.stubs.InitiateDelegationResponse; import org.cagrid.core.common.JAXBUtils; import org.cagrid.core.soapclient.SingleEntityKeyManager; import org.cagrid.delegatedcredential.types.DelegatedCredentialReference; import org.cagrid.delegatedcredential.wsrf.stubs.DelegatedCredentialPortType; import org.cagrid.delegatedcredential.wsrf.stubs.GetDelegatedCredentialRequest; import org.cagrid.delegatedcredential.wsrf.stubs.GetDelegatedCredentialResponse; import org.cagrid.delegatedcredential.wsrf.stubs.PermissionDeniedFaultFaultMessage; import org.cagrid.dorian.DorianPortType; import org.cagrid.dorian.FindGridUsersRequest; import org.cagrid.dorian.FindGridUsersRequest.Filter; import org.cagrid.dorian.FindGridUsersResponse; import org.cagrid.dorian.FindLocalUsersRequest; import org.cagrid.dorian.FindLocalUsersResponse; import org.cagrid.dorian.RegisterLocalUserRequest; import org.cagrid.dorian.RequestUserCertificateRequest; import org.cagrid.dorian.RequestUserCertificateRequest.Key; import org.cagrid.dorian.RequestUserCertificateRequest.Lifetime; import org.cagrid.dorian.RequestUserCertificateRequest.Saml; import org.cagrid.dorian.RequestUserCertificateResponse; import org.cagrid.dorian.UpdateLocalUserRequest; import org.cagrid.dorian.UpdateLocalUserRequest.User; import org.cagrid.dorian.model.federation.CertificateLifetime; import org.cagrid.dorian.model.federation.GridUser; import org.cagrid.dorian.model.federation.GridUserFilter; import org.cagrid.dorian.model.federation.PublicKey; import org.cagrid.dorian.model.idp.Application; import org.cagrid.dorian.model.idp.CountryCode; import org.cagrid.dorian.model.idp.LocalUser; import org.cagrid.dorian.model.idp.LocalUserFilter; import org.cagrid.dorian.model.idp.LocalUserStatus; import org.cagrid.dorian.model.idp.StateCode; import org.cagrid.dorian.service.Dorian; import org.cagrid.dorian.service.tools.DorianTestBootstrapper; import org.cagrid.dorian.soapclient.DorianSoapClientFactory; import org.cagrid.gaards.authentication.AuthenticateUserRequest; import org.cagrid.gaards.authentication.AuthenticateUserRequest.Credential; import org.cagrid.gaards.authentication.AuthenticateUserResponse; import org.cagrid.gaards.authentication.BasicAuthentication; import org.cagrid.gaards.pki.CertUtil; import org.cagrid.gaards.pki.KeyUtil; import org.cagrid.gaards.pki.ProxyCreator; import org.cagrid.systest.ContextLoader; import org.cagrid.systest.TestBase; import org.junit.Assert; import org.junit.Test; import org.oasis.names.tc.saml.assertion.AssertionType; import org.ops4j.pax.exam.MavenUtils; import org.ops4j.pax.exam.Option; import org.osgi.framework.Bundle; import org.w3c.dom.Node; import org.xmlsoap.schemas.ws._2004._03.addressing.EndpointReferenceType; public class CDSIT extends TestBase { private final static String USERNAME = "dorian"; private final static String PASSWORD = "DorianAdmin$1"; @Inject private Dorian dorian; @Inject CredentialDelegationService cds; @Override protected void prePAX() { DorianTestBootstrapper dorianTestBootstrapper = null; try { dorianTestBootstrapper = new DorianTestBootstrapper(); dorianTestBootstrapper.createKeyAndTrustStores(); } catch (Exception e) { throw new RuntimeException("Exception bootstrapping Dorian", e); } finally { if (dorianTestBootstrapper != null) { dorianTestBootstrapper.close(); } } } @Override @SuppressWarnings("rawtypes") public List<Class> getAdditionalClasses() { List<Class> additionalClasses = new ArrayList<Class>(2); additionalClasses.add(DorianTestBootstrapper.class); additionalClasses.add(UserInfo.class); return additionalClasses; } @Override public List<Option> getTestBundles() { List<Option> options = new ArrayList<Option>(); String featureVersion = MavenUtils.getArtifactVersion("org.cagrid", "cagrid-features"); String featureURL = "mvn:org.cagrid/cagrid-features/" + featureVersion + "/xml/features"; options.add(features(featureURL, "cagrid-dorian", "cagrid-gridgrouper", "cagrid-cds")); return options; } /* * What actually needs to be tested: create 3 users (a,b,c) login as a, identity-delegate to b try to get delegated cred as c (should fail) login as b, get * delegated cred a destroy the delegated cred, b try to get the delegated cred again (should fail) * * do the same thing with group delegation */ @Test public void testCDS() throws Exception { Assert.assertNotNull(bundleContext); for (Bundle bundle : bundleContext.getBundles()) { String bundleState = bundleStates.get(bundle.getState()); System.out.println(bundle.getBundleId() + ": " + bundle.getSymbolicName() + " - " + bundle.getLocation() + " [" + bundleState + "]"); } System.out.println("X509_CERT_DIR=" + System.getProperty("X509_CERT_DIR")); for (File certFile : new File(System.getProperty("X509_CERT_DIR")).listFiles()) { System.out.println(certFile); } final String dorianURL = "https://localhost:7734/dorian"; final String cdsURL = "https://localhost:7736/cds"; final String dcsURL = "https://localhost:7736/DelegatedCredential"; Assert.assertNotNull(dorian); Assert.assertNotNull(cds); String karafBase = System.getProperty(ContextLoader.KARAF_BASE_KEY); KeyStoreType truststore = new KeyStoreType(); truststore.setFile(karafBase + "/etc/dorian/truststore.jks"); truststore.setType("JKS"); truststore.setPassword("changeit"); // login as Dorian admin using the anon soap client DorianPortType dorianSoapAnon = DorianSoapClientFactory.createSoapClient(dorianURL, truststore, (KeyManager) null); UserInfo adminUserInfo = login(dorianSoapAnon, USERNAME, PASSWORD); Assert.assertNotNull(adminUserInfo.x509Certificate); // make a new soap client using the X.509 obtained from logging in KeyManager keyManager = new SingleEntityKeyManager("client", new X509Certificate[] { adminUserInfo.x509Certificate }, adminUserInfo.privateKey); DorianPortType dorianSoapAuth = DorianSoapClientFactory.createSoapClient(dorianURL, truststore, keyManager); // Create the users as the Dorian Admin // Delegator delegates to Delegatee; BadUser shouldn't be able to access anything UserInfo endUserInfoDelegator = createLocalUser(dorianSoapAuth, "Delegator", "Delegator"); Assert.assertNotNull(endUserInfoDelegator.gridId); UserInfo proxyUserInfo = createLocalUser(dorianSoapAuth, "Delgatee", "Delgatee"); Assert.assertNotNull(proxyUserInfo.gridId); UserInfo endUserInfoBad = createLocalUser(dorianSoapAuth, "BadUser", "BadUser"); Assert.assertNotNull(endUserInfoBad.gridId); // create a CDS soap client for the delegator KeyManager endKeyManager = new SingleEntityKeyManager("client", new X509Certificate[] { endUserInfoDelegator.x509Certificate }, endUserInfoDelegator.privateKey); CredentialDelegationServicePortType delegatorCDSSoapEnd = CDSSoapClientFactory.createSoapClient(cdsURL, truststore, endKeyManager); // send CDS the delegation policy (delegatee can become delegator) InitiateDelegationRequest initiateDelegationRequest = createDelegationPolicy(proxyUserInfo); InitiateDelegationResponse initiateDelegationResponse = delegatorCDSSoapEnd.initiateDelegation(initiateDelegationRequest); DelegationSigningRequest delegationSigningRequest = initiateDelegationResponse.getDelegationSigningRequest(); Assert.assertNotNull(delegationSigningRequest); // approve the delegation policy, signing the cert from the initiate request using the delegator's private key DelegationIdentifier delegationIdentifier = delegationSigningRequest.getDelegationIdentifier(); System.out.println("Delegation Id:" + delegationIdentifier); org.cagrid.cds.model.PublicKey cdsPublicKey = delegationSigningRequest.getPublicKey(); // java.security.PublicKey publicKey = KeyUtil.loadPublicKey(cdsPublicKey.getKeyAsString()); X509Certificate[] cdsX509Certificates = ProxyCreator.createImpersonationProxyCertificate(endUserInfoDelegator.x509Certificate, endUserInfoDelegator.privateKey, KeyUtil.loadPublicKey(cdsPublicKey.getKeyAsString()), 3, 0, 0); CertificateChain cdsX509CertificateChain = Utils.toCertificateChain(cdsX509Certificates); DelegationSigningResponse delegationSigningResponse = new DelegationSigningResponse(); delegationSigningResponse.setDelegationIdentifier(delegationIdentifier); delegationSigningResponse.setCertificateChain(cdsX509CertificateChain); ApproveDelegationRequest.DelegationSigningResponse _delegationSigningResponse = new ApproveDelegationRequest.DelegationSigningResponse(); _delegationSigningResponse.setDelegationSigningResponse(delegationSigningResponse); ApproveDelegationRequest approveDelegationRequest = new ApproveDelegationRequest(); approveDelegationRequest.setDelegationSigningResponse(_delegationSigningResponse); ApproveDelegationResponse approveDelegationResponse = delegatorCDSSoapEnd.approveDelegation(approveDelegationRequest); DelegatedCredentialReference delegatedCredentialReference = approveDelegationResponse.getDelegatedCredentialReference(); Assert.assertNotNull(delegatedCredentialReference); EndpointReferenceType dcEPR = delegatedCredentialReference.getEndpointReference(); //System.out.println(JAXBUtils.marshal(dcEPR)); /** * Delegatee using the dcEPR should pass */ KeyManager delegateeKeyManager = new SingleEntityKeyManager("client", new X509Certificate[] { proxyUserInfo.x509Certificate }, proxyUserInfo.privateKey); DelegatedCredentialPortType dcs = DCSSoapClientFactory.createSoapClient(dcsURL, truststore, delegateeKeyManager); GetDelegatedCredentialRequest dcr = new GetDelegatedCredentialRequest(); dcr.setPublicKey(new GetDelegatedCredentialRequest.PublicKey()); dcr.getPublicKey().setPublicKey(cdsPublicKey); ((BindingProvider) dcs).getRequestContext().put(Header.HEADER_LIST, makeDelegationIdHeader(dcEPR)); GetDelegatedCredentialResponse cred = dcs.getDelegatedCredential(dcr); Assert.assertNotNull(cred); Assert.assertNotNull(cred.getCertificateChain()); List<org.cagrid.cds.model.X509Certificate> certChain = cred.getCertificateChain().getX509Certificate(); Assert.assertNotNull(certChain); Assert.assertEquals(3, certChain.size()); // last cert should be the delegator X509Certificate x509Certificate = CertUtil.loadCertificate(certChain.get(2).getCertificateAsString()); Assert.assertEquals(endUserInfoDelegator.x509Certificate.getIssuerDN(), x509Certificate.getIssuerDN()); Assert.assertEquals(endUserInfoDelegator.x509Certificate.getSubjectDN().getName(), x509Certificate.getSubjectDN().getName()); // second cert should be the proxy cert sent to CDS x509Certificate = CertUtil.loadCertificate(certChain.get(1).getCertificateAsString()); Assert.assertEquals(cdsX509Certificates[0].getIssuerDN().getName(), x509Certificate.getIssuerDN().getName()); Assert.assertEquals(cdsX509Certificates[0].getSubjectDN().getName(), x509Certificate.getSubjectDN().getName()); // first cert should be the delegated proxy x509Certificate = CertUtil.loadCertificate(certChain.get(0).getCertificateAsString()); // the subject of the proxy should be the issuer of the delgated proxy Assert.assertEquals(cdsX509Certificates[0].getSubjectDN().getName(), x509Certificate.getIssuerDN().getName()); // we don't really know what the final subject will be, but it should be a superstring of the delegated proxy DN Assert.assertEquals(0, x509Certificate.getSubjectDN().getName().indexOf(cdsX509Certificates[0].getSubjectDN().getName())); /** * Bad user using the dcEPR should fail */ KeyManager badUserKeyManager = new SingleEntityKeyManager("client", new X509Certificate[] { endUserInfoBad.x509Certificate }, endUserInfoBad.privateKey); dcs = DCSSoapClientFactory.createSoapClient(dcsURL, truststore, badUserKeyManager); ((BindingProvider) dcs).getRequestContext().put(Header.HEADER_LIST, makeDelegationIdHeader(dcEPR)); try { dcs.getDelegatedCredential(dcr); Assert.fail("Should not be able to get delegated credential"); } catch (PermissionDeniedFaultFaultMessage e) { // expected // System.out.println("Expected " + e.toString()); } /** * good user with bad EPR should fail; not inadvertantly return the wrong cred */ //change the EPR Object o=((org.xmlsoap.schemas.ws._2004._03.addressing.ReferencePropertiesType) dcEPR.getReferenceProperties()).getAny().get(0); ((Node) o).getChildNodes().item(0).getChildNodes().item(0).setNodeValue("10000000"); //System.out.println(JAXBUtils.marshal(dcEPR)); List<Header> badHeader = makeDelegationIdHeader(dcEPR); ((BindingProvider) dcs).getRequestContext().put(Header.HEADER_LIST, badHeader); try { cred = dcs.getDelegatedCredential(dcr); Assert.fail("Should not have been able to obtain a credential for a bad EPR."); } catch (Exception e) { // expected //e.printStackTrace(); } } private List<Header> makeDelegationIdHeader(EndpointReferenceType epr) throws JAXBException { List<Header> headers = new ArrayList<Header>(); Header delegationIdHeader = new Header(new QName("http://cds.gaards.cagrid.org/CredentialDelegationService/DelegatedCredential", "DelegatedCredentialKey"), epr, new JAXBDataBinding(EndpointReferenceType.class)); headers.add(delegationIdHeader); return headers; } private InitiateDelegationRequest createDelegationPolicy(UserInfo proxyUserInfo) { AllowedParties allowedParties = new AllowedParties(); allowedParties.getGridIdentity().add(proxyUserInfo.gridId); IdentityDelegationPolicy delegationPolicy = new IdentityDelegationPolicy(); delegationPolicy.setAllowedParties(allowedParties); DelegationRequest delegationRequest = new DelegationRequest(); delegationRequest.setDelegationPolicy(delegationPolicy); ProxyLifetime proxyLifetime = new ProxyLifetime(); proxyLifetime.setHours(6); delegationRequest.setIssuedCredentialLifetime(proxyLifetime); delegationRequest.setIssuedCredentialPathLength(0); delegationRequest.setKeyLength(2048); Req req = new InitiateDelegationRequest.Req(); req.setDelegationRequest(delegationRequest); InitiateDelegationRequest initiateDelegationRequest = new InitiateDelegationRequest(); initiateDelegationRequest.setReq(req); return initiateDelegationRequest; } private UserInfo createLocalUser(DorianPortType dorianSoap, String userId, String firstName) throws Exception { final String password = "$D0ct0rC0de$"; Application application = new Application(); application.setUserId(userId); application.setPassword(password); application.setFirstName(firstName); application.setLastName("User"); application.setEmail(firstName + ".User@test.org"); application.setAddress("123 Fake St."); application.setCity("Columbus"); application.setState(StateCode.OH); application.setCountry(CountryCode.US); application.setZipcode("43210"); application.setPhoneNumber("614-555-5555"); application.setOrganization("organization"); RegisterLocalUserRequest.A a = new RegisterLocalUserRequest.A(); a.setApplication(application); RegisterLocalUserRequest registerLocalUserRequest = new RegisterLocalUserRequest(); registerLocalUserRequest.setA(a); dorianSoap.registerLocalUser(registerLocalUserRequest); LocalUserFilter localUserFilter = new LocalUserFilter(); localUserFilter.setUserId(userId); FindLocalUsersRequest.F f = new FindLocalUsersRequest.F(); f.setLocalUserFilter(localUserFilter); FindLocalUsersRequest findLocalUsersRequest = new FindLocalUsersRequest(); findLocalUsersRequest.setF(f); FindLocalUsersResponse findLocalUsersResponse = dorianSoap.findLocalUsers(findLocalUsersRequest); List<LocalUser> localUsers = findLocalUsersResponse.getLocalUser(); if (localUsers.size() != 1) { throw new Exception("findLocalUsers returned " + localUsers.size() + " users!"); } LocalUser localUser = localUsers.get(0); localUser.setStatus(LocalUserStatus.ACTIVE); User user = new User(); user.setLocalUser(localUser); UpdateLocalUserRequest updateLocalUserRequest = new UpdateLocalUserRequest(); updateLocalUserRequest.setUser(user); dorianSoap.updateLocalUser(updateLocalUserRequest); UserInfo userInfo0 = login(dorianSoap, userId, password); GridUserFilter gridUserFilter = new GridUserFilter(); gridUserFilter.setUID(userId); Filter filter = new Filter(); filter.setGridUserFilter(gridUserFilter); FindGridUsersRequest findGridUsersRequest = new FindGridUsersRequest(); findGridUsersRequest.setFilter(filter); FindGridUsersResponse findGridUsersResponse = dorianSoap.findGridUsers(findGridUsersRequest); List<GridUser> gridUsers = findGridUsersResponse.getGridUser(); if (gridUsers.size() != 1) { throw new Exception("findGridUsers returned " + gridUsers.size() + " users!"); } GridUser gridUser = gridUsers.get(0); String gridId = gridUser.getGridId(); UserInfo userInfo = new UserInfo(gridId, userInfo0.x509Certificate, userInfo0.privateKey); return userInfo; } private UserInfo login(DorianPortType dorianSoap, String userId, String password) throws Exception { BasicAuthentication basicAuthentication = new BasicAuthentication(); basicAuthentication.setUserId(userId); basicAuthentication.setPassword(password); Credential credential = new Credential(); credential.setCredential(basicAuthentication); AuthenticateUserRequest authenticateUserRequest = new AuthenticateUserRequest(); authenticateUserRequest.setCredential(credential); AuthenticateUserResponse authenticateUserResponse = dorianSoap.authenticateUser(authenticateUserRequest); AssertionType assertion = authenticateUserResponse.getAssertion(); Assert.assertNotNull(assertion); KeyPair keyPair = KeyUtil.generateRSAKeyPair(2048); Saml saml = new Saml(); saml.setAssertion(assertion); PublicKey caPublicKey = new PublicKey(); caPublicKey.setKeyAsString(KeyUtil.writePublicKey(keyPair.getPublic())); RequestUserCertificateRequest userCertificateRequest = new RequestUserCertificateRequest(); userCertificateRequest.setSaml(saml); Key caKey = new Key(); caKey.setPublicKey(caPublicKey); userCertificateRequest.setKey(caKey); CertificateLifetime certificateLifetime = new CertificateLifetime(); certificateLifetime.setHours(6); Lifetime lifetime = new Lifetime(); lifetime.setCertificateLifetime(certificateLifetime); userCertificateRequest.setLifetime(lifetime); RequestUserCertificateResponse requestUserCertificateResponse = dorianSoap.requestUserCertificate(userCertificateRequest); String certificateString = requestUserCertificateResponse.getX509Certificate().getCertificateAsString(); X509Certificate x509Certificate = CertUtil.loadCertificate(certificateString); UserInfo userInfo = new UserInfo(null, x509Certificate, keyPair.getPrivate()); return userInfo; } }