Search in sources :

Example 1 with TeamCitySshKey

use of jetbrains.buildServer.ssh.TeamCitySshKey in project teamcity-git by JetBrains.

the class FetchCommandImpl method getTeamCityPrivateKey.

private File getTeamCityPrivateKey(@NotNull AuthSettings authSettings) throws VcsException {
    if (authSettings.getAuthMethod() != AuthenticationMethod.TEAMCITY_SSH_KEY)
        return null;
    String keyId = authSettings.getTeamCitySshKeyId();
    if (keyId == null)
        return null;
    VcsRoot root = authSettings.getRoot();
    if (root == null)
        return null;
    TeamCitySshKey privateKey = mySshKeyManager.getKey(root);
    if (privateKey == null)
        return null;
    try {
        File privateKeyFile = FileUtil.createTempFile("private", "key");
        FileUtil.writeToFile(privateKeyFile, privateKey.getPrivateKey());
        return privateKeyFile;
    } catch (IOException e) {
        throw new VcsException(e);
    }
}
Also used : VcsException(jetbrains.buildServer.vcs.VcsException) VcsRoot(jetbrains.buildServer.vcs.VcsRoot) IOException(java.io.IOException) TeamCitySshKey(jetbrains.buildServer.ssh.TeamCitySshKey) File(java.io.File)

Example 2 with TeamCitySshKey

use of jetbrains.buildServer.ssh.TeamCitySshKey in project teamcity-git by JetBrains.

the class SshAuthenticationTest method do_ssh_test.

private void do_ssh_test(boolean nativeOperationsEnabled, boolean useSshAskPass, @NotNull String urlFormat, @NotNull String sshdConfig, @Nullable TeamCitySshKey tcKey, @Nullable String publicKey, @NotNull VcsRootConfigurator builder, boolean ignoreKnownHosts) throws Exception {
    if (!nativeOperationsEnabled) {
        JSchConfigInitializer.initJSchConfig(JSch.class);
    }
    final File pub_key = publicKey == null ? null : dataFile(publicKey);
    ssh_test(pub_key, sshdConfig, container -> {
        setInternalProperty("teamcity.git.nativeOperationsEnabled", String.valueOf(nativeOperationsEnabled));
        setInternalProperty("teamcity.git.useSshAskPas", String.valueOf(useSshAskPass));
        setInternalProperty("teamcity.git.debugNativeGit", "true");
        final ServerPaths serverPaths = new ServerPaths(myTempFiles.createTempDir().getAbsolutePath());
        final ServerPluginConfig config = new PluginConfigBuilder(serverPaths).build();
        final VcsRootSshKeyManager keyManager = r -> tcKey;
        final TransportFactoryImpl transportFactory = new TransportFactoryImpl(config, keyManager);
        final GitRepoOperationsImpl repoOperations = new GitRepoOperationsImpl(config, transportFactory, keyManager, new FetchCommandImpl(config, transportFactory, new FetcherProperties(config), keyManager));
        final MirrorManagerImpl mirrorManager = new MirrorManagerImpl(config, new HashCalculatorImpl(), new RemoteRepositoryUrlInvestigatorImpl());
        final RepositoryManagerImpl repositoryManager = new RepositoryManagerImpl(config, mirrorManager);
        final String repoUrl = String.format(urlFormat, container.getContainerIpAddress(), container.getMappedPort(22));
        final GitVcsRoot gitRoot = new GitVcsRoot(mirrorManager, builder.config(VcsRootBuilder.vcsRoot().withFetchUrl(repoUrl).withIgnoreKnownHosts(ignoreKnownHosts)).build(), new URIishHelperImpl());
        JSch.setLogger(JSchLoggers.STD_DEBUG_JSCH_LOGGER);
        // here we test some git operations
        final URIish fetchUrl = new URIish(repoUrl);
        final Repository db = repositoryManager.openRepository(fetchUrl);
        final Map<String, Ref> refs = repoOperations.lsRemoteCommand(repoUrl).lsRemote(db, gitRoot, new FetchSettings(gitRoot.getAuthSettings()));
        assertContains(refs.keySet(), "refs/pull/1");
        final StringBuilder progress = new StringBuilder();
        final List<RefSpec> refSpecs = refs.keySet().stream().map(r -> new RefSpec().setSourceDestination(r, r).setForceUpdate(true)).collect(Collectors.toList());
        repoOperations.fetchCommand(repoUrl).fetch(db, fetchUrl, new FetchSettings(gitRoot.getAuthSettings(), new GitProgress() {

            @Override
            public void reportProgress(@NotNull final String p) {
                progress.append(p).append("\n");
            }

            @Override
            public void reportProgress(final float p, @NotNull final String stage) {
                if (p < 0) {
                    progress.append(stage).append("\n");
                } else {
                    int percents = (int) Math.floor(p * 100);
                    progress.append(stage).append(" ").append(percents).append("%");
                }
            }
        }, refSpecs));
        if (nativeOperationsEnabled) {
            assertContains(progress.toString(), "* [new ref]         refs/pull/1               -> refs/pull/1");
        } else {
            assertContains(progress.toString(), "update ref remote name: refs/pull/1, local name: refs/pull/1, old object id: 0000000000000000000000000000000000000000, new object id: b896070465af79121c9a4eb5300ecff29453c164, result: NEW");
        }
        final GitVcsSupport vcsSupport = GitSupportBuilder.gitSupport().withServerPaths(serverPaths).withPluginConfig(config).withTransportFactory(transportFactory).build();
        repoOperations.tagCommand(vcsSupport, repoUrl).tag(vcsSupport.createContext(gitRoot.getOriginalRoot(), "tag"), "test_tag", "b896070465af79121c9a4eb5300ecff29453c164");
        assertContains(repoOperations.lsRemoteCommand(repoUrl).lsRemote(db, gitRoot, new FetchSettings(gitRoot.getAuthSettings())).keySet(), "refs/tags/test_tag");
    });
}
Also used : SkipException(org.testng.SkipException) GitTestUtil.dataFile(jetbrains.buildServer.buildTriggers.vcs.git.tests.GitTestUtil.dataFile) BindMode(org.testcontainers.containers.BindMode) ImageFromDockerfile(org.testcontainers.images.builder.ImageFromDockerfile) JSch(com.jcraft.jsch.JSch) jetbrains.buildServer.buildTriggers.vcs.git(jetbrains.buildServer.buildTriggers.vcs.git) TestFor(jetbrains.buildServer.util.TestFor) TempFiles(jetbrains.buildServer.TempFiles) Callable(java.util.concurrent.Callable) Test(org.testng.annotations.Test) GitRepoOperationsImpl(jetbrains.buildServer.buildTriggers.vcs.git.command.impl.GitRepoOperationsImpl) FileUtil(jetbrains.buildServer.util.FileUtil) BaseTestCase(jetbrains.buildServer.BaseTestCase) Map(java.util.Map) GeneralCommandLine(com.intellij.execution.configurations.GeneralCommandLine) URIish(org.eclipse.jgit.transport.URIish) GenericContainer(org.testcontainers.containers.GenericContainer) JSchConfigInitializer(jetbrains.buildServer.util.jsch.JSchConfigInitializer) Files(java.nio.file.Files) RefSpec(org.eclipse.jgit.transport.RefSpec) BeforeMethod(org.testng.annotations.BeforeMethod) IOException(java.io.IOException) ServerPaths(jetbrains.buildServer.serverSide.ServerPaths) Collectors(java.util.stream.Collectors) SystemInfo(com.intellij.openapi.util.SystemInfo) File(java.io.File) TeamCitySshKey(jetbrains.buildServer.ssh.TeamCitySshKey) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) ExecResult(jetbrains.buildServer.ExecResult) SimpleCommandLineProcessRunner(jetbrains.buildServer.SimpleCommandLineProcessRunner) Ref(org.eclipse.jgit.lib.Ref) VcsRootSshKeyManager(jetbrains.buildServer.ssh.VcsRootSshKeyManager) NotNull(org.jetbrains.annotations.NotNull) Repository(org.eclipse.jgit.lib.Repository) URIish(org.eclipse.jgit.transport.URIish) GitRepoOperationsImpl(jetbrains.buildServer.buildTriggers.vcs.git.command.impl.GitRepoOperationsImpl) NotNull(org.jetbrains.annotations.NotNull) RefSpec(org.eclipse.jgit.transport.RefSpec) ServerPaths(jetbrains.buildServer.serverSide.ServerPaths) Repository(org.eclipse.jgit.lib.Repository) Ref(org.eclipse.jgit.lib.Ref) VcsRootSshKeyManager(jetbrains.buildServer.ssh.VcsRootSshKeyManager) GitTestUtil.dataFile(jetbrains.buildServer.buildTriggers.vcs.git.tests.GitTestUtil.dataFile) File(java.io.File)

Example 3 with TeamCitySshKey

use of jetbrains.buildServer.ssh.TeamCitySshKey in project teamcity-git by JetBrains.

the class SshAuthenticationTest method ssh_git_ecdsa_encrypted_uploaded_key.

@Test(dataProvider = "true,false")
public void ssh_git_ecdsa_encrypted_uploaded_key(boolean nativeOperationsEnabled) throws Exception {
    final File key = dataFile("keys/id_ecdsa_encrypted");
    do_ssh_test(nativeOperationsEnabled, true, "ssh://git@%s:%s/home/git/repo.git", "", new TeamCitySshKey("test_key", Files.readAllBytes(key.toPath()), true), "keys/id_ecdsa_encrypted.pub", b -> b.withAuthMethod(AuthenticationMethod.TEAMCITY_SSH_KEY).withTeamCitySshKey("test_key").withPassphrase("12345"));
}
Also used : TeamCitySshKey(jetbrains.buildServer.ssh.TeamCitySshKey) GitTestUtil.dataFile(jetbrains.buildServer.buildTriggers.vcs.git.tests.GitTestUtil.dataFile) File(java.io.File) Test(org.testng.annotations.Test)

Example 4 with TeamCitySshKey

use of jetbrains.buildServer.ssh.TeamCitySshKey in project teamcity-git by JetBrains.

the class GitCommandLine method getUploadedPrivateKey.

@NotNull
private File getUploadedPrivateKey(@NotNull AuthSettings authSettings) throws Exception {
    final String keyId = authSettings.getTeamCitySshKeyId();
    final VcsRoot root = authSettings.getRoot();
    if (keyId == null || root == null || mySshKeyManager == null) {
        final String msg = "Failed to locate uploaded SSH key " + keyId + " for vcs root %s " + (mySshKeyManager == null ? ": null ssh key manager" : "");
        Loggers.VCS.warn(String.format(msg, LogUtil.describe(root)));
        throw new VcsException(String.format(msg, root == null ? null : root.getName()));
    }
    final TeamCitySshKey key = mySshKeyManager.getKey(root);
    if (key == null) {
        throw new VcsException("Failed to locate uploaded SSH key " + keyId + " for vcs root " + root.getName());
    }
    final File privateKey = createTmpKeyFile();
    addPostAction(() -> FileUtil.delete(privateKey));
    FileUtil.writeFileAndReportErrors(privateKey, new String(key.getPrivateKey()));
    return privateKey;
}
Also used : VcsException(jetbrains.buildServer.vcs.VcsException) VcsRoot(jetbrains.buildServer.vcs.VcsRoot) TeamCitySshKey(jetbrains.buildServer.ssh.TeamCitySshKey) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with TeamCitySshKey

use of jetbrains.buildServer.ssh.TeamCitySshKey in project teamcity-git by JetBrains.

the class GitUrlSupport method convertToVcsRootProperties.

@Nullable
public Map<String, String> convertToVcsRootProperties(@NotNull VcsUrl url, @NotNull VcsOperationContext operationContext) throws VcsException {
    String scmName = getMavenScmName(url);
    if (// some other scm provider
    scmName != null && !"git".equals(scmName) && !"ssh".equals(scmName))
        return null;
    String fetchUrl = getFetchUrl(url);
    URIish uri = parseURIish(fetchUrl);
    if (fetchUrl.startsWith("https://") && !fetchUrl.endsWith(".git")) {
        VcsHostingRepo gitlabRepo = WellKnownHostingsUtil.getGitlabRepo(uri);
        if (gitlabRepo != null) {
            // for GitLab we need to add .git suffix to the fetch URL, otherwise, for some reason JGit can't work with this repository (although regular git command works)
            fetchUrl = fetchUrl + ".git";
            uri = parseURIish(fetchUrl);
        }
    }
    Map<String, String> props = new HashMap<>(myGitSupport.getDefaultVcsProperties());
    props.put(Constants.FETCH_URL, fetchUrl);
    props.putAll(getAuthSettings(url, uri));
    VcsHostingRepo ghRepo = WellKnownHostingsUtil.getGitHubRepo(uri);
    if (ghRepo != null)
        refineGithubSettings(ghRepo, props);
    int numSshKeysTried = 0;
    final SProject curProject = myProjectManager == null ? null : myProjectManager.findProjectById(operationContext.getCurrentProjectId());
    if (AuthenticationMethod.PRIVATE_KEY_DEFAULT.toString().equals(props.get(Constants.AUTH_METHOD)) && fetchUrl.endsWith(".git") && curProject != null) {
        // SSH access, before using the default private key which may not be accessible on the agent,
        // let's iterate over all SSH keys of the current project, maybe we'll find a working one
        ServerSshKeyManager serverSshKeyManager = getSshKeyManager();
        if (serverSshKeyManager != null) {
            for (TeamCitySshKey key : serverSshKeyManager.getKeys(curProject)) {
                // don't know password, so can't use it
                if (key.isEncrypted())
                    continue;
                Map<String, String> propsCopy = new HashMap<>(props);
                propsCopy.put(Constants.AUTH_METHOD, AuthenticationMethod.TEAMCITY_SSH_KEY.toString());
                propsCopy.put(VcsRootSshKeyManager.VCS_ROOT_TEAMCITY_SSH_KEY_NAME, key.getName());
                try {
                    numSshKeysTried++;
                    return testConnection(propsCopy, curProject);
                } catch (VcsException e) {
                    if (isBranchRelatedError(e))
                        throw e;
                }
            }
        }
        // could not find any valid keys, proceed with default SSH key
        try {
            return testConnection(props, curProject);
        } catch (VcsException e) {
            if (isBranchRelatedError(e))
                throw e;
            String message = "Could not connect to the Git repository by SSH protocol.";
            if (numSshKeysTried > 0) {
                message += " Tried " + numSshKeysTried + " SSH " + StringUtil.pluralize("key", numSshKeysTried) + " accessible from the current project.";
            } else {
                message += " Could not find an SSH key in the current project which would work with this Git repository.";
            }
            throw new VcsException(message + " Error message: " + e.getMessage(), e);
        }
    }
    final boolean defaultBranchKnown = props.get(Constants.BRANCH_NAME) != null;
    if (defaultBranchKnown) {
        // git protocol, or git scm provider
        if ("git".equals(scmName) || "git".equals(uri.getScheme()) || fetchUrl.endsWith(".git"))
            return props;
    }
    // not SSH or URL does not end with .git, still try to connect just for the case
    try {
        return testConnection(props, curProject);
    } catch (VcsException e) {
        if (isBranchRelatedError(e) || GitServerUtil.isAuthError(e) || fetchUrl.toLowerCase().contains("git"))
            throw e;
        // probably not git
        Loggers.VCS.infoAndDebugDetails("Failed to recognize " + url.getUrl() + " as a git repository", e);
        return null;
    }
}
Also used : URIish(org.eclipse.jgit.transport.URIish) HashMap(java.util.HashMap) ServerSshKeyManager(jetbrains.buildServer.ssh.ServerSshKeyManager) SProject(jetbrains.buildServer.serverSide.SProject) TeamCitySshKey(jetbrains.buildServer.ssh.TeamCitySshKey) PositionConstraint(jetbrains.buildServer.util.positioning.PositionConstraint) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

TeamCitySshKey (jetbrains.buildServer.ssh.TeamCitySshKey)11 File (java.io.File)8 GitTestUtil.dataFile (jetbrains.buildServer.buildTriggers.vcs.git.tests.GitTestUtil.dataFile)7 Test (org.testng.annotations.Test)6 IOException (java.io.IOException)2 VcsException (jetbrains.buildServer.vcs.VcsException)2 VcsRoot (jetbrains.buildServer.vcs.VcsRoot)2 URIish (org.eclipse.jgit.transport.URIish)2 NotNull (org.jetbrains.annotations.NotNull)2 Nullable (org.jetbrains.annotations.Nullable)2 GeneralCommandLine (com.intellij.execution.configurations.GeneralCommandLine)1 SystemInfo (com.intellij.openapi.util.SystemInfo)1 JSch (com.jcraft.jsch.JSch)1 Files (java.nio.file.Files)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 Callable (java.util.concurrent.Callable)1 Collectors (java.util.stream.Collectors)1 BaseTestCase (jetbrains.buildServer.BaseTestCase)1