/* * The MIT License * * Copyright (c) 2011, Oracle Corporation, Nikita Levyankov, Anton Kozak * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package hudson.scm; import hudson.Proc; import hudson.matrix.AxisList; import hudson.matrix.MatrixConfiguration; import hudson.matrix.MatrixProject; import hudson.matrix.TextAxis; import hudson.model.FreeStyleProject; import hudson.model.Result; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.Collection; import org.jvnet.hudson.test.Bug; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; import static hudson.scm.SubversionSCM.compareSVNAuthentications; /** * @author Kohsuke Kawaguchi * @author Nikita Levyankov */ public class PerJobCredentialStoreTest extends AbstractSubversionTest { private static final String testSvnUser = "user"; private static final String testSvnPassword = "userpass"; private static final String testSvnRealm = "Test realm"; private static final String GUEST_ACCESS_REPOSITORY_RESOURCE = "guest_access_svn.zip"; private static final String realm = "<svn://localhost:3690>"; private static final String SVN_URL = "svn://localhost/bob"; private static final String GUEST_USER_LOGIN = "guest"; private static final String GUEST_USER_PASSWORD = "guestpass"; private static final String BOGUS_USER_LOGIN = "bogus"; private static final String BOGUS_USER_PASSWORD = "boguspass"; private PerJobCredentialStore credentialStore; public void testAcknowledgeNonEmptyCredentials() throws IOException { FreeStyleProject p = createFreeStyleProject(); credentialStore = new PerJobCredentialStore(p, null); assertFalse(credentialStore.getSaveableListener().isFileChanged()); SubversionSCM.DescriptorImpl.Credential credential = new SubversionSCM.DescriptorImpl.PasswordCredential( testSvnUser, testSvnPassword); credentialStore.acknowledgeAuthentication(testSvnRealm, credential); assertTrue(credentialStore.getSaveableListener().isFileChanged()); } public void testAcknowledgeEmptyCredentials() throws IOException { FreeStyleProject p = createFreeStyleProject(); credentialStore = new PerJobCredentialStore(p, null); SubversionSCM.DescriptorImpl.Credential credential = new SubversionSCM.DescriptorImpl.PasswordCredential( testSvnUser, testSvnPassword); //Store password credentials credentialStore.acknowledgeAuthentication(testSvnRealm, credential); //Reset file changed status flag in order to acknowledge null credentials credentialStore.getSaveableListener().resetChangedStatus(); //Emulate call from slave. credentialStore.acknowledgeAuthentication(testSvnRealm, null); assertFalse(credentialStore.getSaveableListener().isFileChanged()); } // @Bug(3) public void testMatrixConfigurationCredentialsFileNamePath() throws IOException { MatrixProject p = createMatrixProject("matrix"); p.setScm(new SubversionSCM("https://datacard.googlecode.com/svn/trunk")); Collection<MatrixConfiguration> configurations = p.getItems(); assertEquals(configurations.size(), 2); MatrixConfiguration configuration = configurations.iterator().next(); SubversionSCM scm = (SubversionSCM) configuration.getScm(); SubversionSCM.DescriptorImpl.SVNAuthenticationProviderImpl provider = (SubversionSCM.DescriptorImpl.SVNAuthenticationProviderImpl) scm.getDescriptor(). createAuthenticationProvider(configuration); PerJobCredentialStore perJobCredentialStore = (PerJobCredentialStore) provider.getLocal(); String correctPath = "matrix" + File.separator + "subversion.credentials"; assertTrue(perJobCredentialStore.getXmlFile(configuration).getFile().getCanonicalPath().endsWith(correctPath)); } // /** * There was a bug that credentials stored in the remote call context was * serialized wrongly. */ @Bug(8061) public void ignore_testRemoteBuild() throws Exception { Proc svnserveProcess = runSvnServe(getClass().getResource("HUDSON-1379.zip"));; if (svnserveProcess != null) { try { FreeStyleProject b = createFreeStyleProject(); b.setScm(new SubversionSCM(SVN_URL)); b.setAssignedNode(createSlave()); descriptor.postCredential(b, SVN_URL, "alice", "alice", null, new PrintWriter(System.out)); buildAndAssertSuccess(b); PerJobCredentialStore store = new PerJobCredentialStore(b, SVN_URL); assertFalse(store.isEmpty()); // credential store should contain a valid entry } finally { svnserveProcess.kill(); } } else { System.out.println("Skipping testRemoteBuild. Light weight SVN Server (svnserve) could not be started."); } } /** * Even if the default providers remember bogus passwords, Hudson should * still attempt what it knows. */ @Bug(3936) public void ignore_test3936() throws Exception { //Start local svn repository Proc server = runSvnServe(getClass().getResource(GUEST_ACCESS_REPOSITORY_RESOURCE)); if (server != null) { SVNURL repo = SVNURL.parseURIDecoded(SVN_URL); try { // creates a purely in memory auth manager ISVNAuthenticationManager m = createInMemoryManager(); // double check that it really knows nothing about the fake repo try { m.getFirstAuthentication(kind, realm, repo); fail(); } catch (SVNCancelException e) { // yep } // teach a bogus credential and have SVNKit store it. SVNPasswordAuthentication bogus = new SVNPasswordAuthentication(BOGUS_USER_LOGIN, BOGUS_USER_PASSWORD, true, null, false); m.acknowledgeAuthentication(true, kind, realm, null, bogus); assertTrue(compareSVNAuthentications(m.getFirstAuthentication(kind, realm, repo), bogus)); try { attemptAccess(repo, m); fail("SVNKit shouldn't yet know how to access"); } catch (SVNCancelException e) { } // make sure the failure didn't clean up the cache, // since what we want to test here is Hudson trying to supply its credential, despite the failed cache assertTrue(compareSVNAuthentications(m.getFirstAuthentication(kind, realm, repo), bogus)); // now let Hudson have the real credential // can we now access the repo? descriptor.postCredential(null, repo.toDecodedString(), GUEST_USER_LOGIN, GUEST_USER_PASSWORD, null, new PrintWriter(System.out)); attemptAccess(repo, m); } finally { server.kill(); } } else { System.out.println("Skipping test3936. Light weight SVN Server (svnserve) could not be started."); } } @Bug(1379) public void ignore_testMultipleCredentialsPerRepo() throws Exception { Proc serverProc = runSvnServe(getClass().getResource("HUDSON-1379.zip")); if (serverProc != null) { try { FreeStyleProject b = createFreeStyleProject(); b.setScm(new SubversionSCM(SVN_URL)); FreeStyleProject c = createFreeStyleProject(); c.setScm(new SubversionSCM("svn://localhost/charlie")); // should fail without a credential assertBuildStatus(Result.FAILURE, b.scheduleBuild2(0).get()); descriptor.postCredential(b, SVN_URL, "bob", "bob", null, new PrintWriter(System.out)); buildAndAssertSuccess(b); assertBuildStatus(Result.FAILURE, c.scheduleBuild2(0).get()); descriptor.postCredential(c, "svn://localhost/charlie", "charlie", "charlie", null, new PrintWriter(System.out)); buildAndAssertSuccess(c); // b should still build fine. buildAndAssertSuccess(b); } finally { serverProc.kill(); } } else { System.out.println("Skipping testMultipleCredentialsPerRepo. Light weight SVN Server (svnserve) could not be started."); } } @Bug(1379) public void ignore_testSuperUserForAllRepos() throws Exception { Proc p = runSvnServe(getClass().getResource("HUDSON-1379.zip")); if (p != null) { try { FreeStyleProject b = createFreeStyleProject(); b.setScm(new SubversionSCM(SVN_URL)); FreeStyleProject c = createFreeStyleProject(); c.setScm(new SubversionSCM("svn://localhost/charlie")); // should fail without a credential assertBuildStatus(Result.FAILURE, b.scheduleBuild2(0).get()); assertBuildStatus(Result.FAILURE, c.scheduleBuild2(0).get()); // but with the super user credential both should work now descriptor.postCredential(b, SVN_URL, "alice", "alice", null, new PrintWriter(System.out)); buildAndAssertSuccess(b); buildAndAssertSuccess(c); } finally { p.kill(); } } else { System.out.println("Skipping testSuperUserForAllRepos. Light weight SVN Server (svnserve) could not be started."); } } private void attemptAccess(SVNURL repo, ISVNAuthenticationManager m) throws SVNException { SVNRepository repository = SVNRepositoryFactory.create(repo); repository.setAuthenticationManager(m); repository.testConnection(); } @Override protected MatrixProject createMatrixProject(String name) throws IOException { MatrixProject p = super.createMatrixProject(name); AxisList axes = new AxisList(); axes.add(new TextAxis("db", "mysql", "oracle")); p.setAxes(axes); return p; } }