001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.maven.scm.provider.git.jgit.command.checkout;
020
021import java.io.File;
022import java.io.IOException;
023import java.io.InputStream;
024import java.net.InetSocketAddress;
025import java.nio.charset.StandardCharsets;
026import java.nio.file.Files;
027import java.nio.file.Path;
028import java.nio.file.StandardCopyOption;
029import java.security.GeneralSecurityException;
030import java.security.PublicKey;
031import java.util.function.Consumer;
032
033import org.apache.commons.io.IOUtils;
034import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
035import org.apache.maven.scm.provider.git.command.checkout.GitSshCheckOutCommandTckTest;
036import org.apache.maven.scm.provider.git.jgit.JGitTestScmProvider;
037import org.apache.maven.scm.provider.git.jgit.command.ScmProviderAwareSshdSessionFactory;
038import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
039import org.apache.maven.scm.repository.ScmRepository;
040import org.apache.sshd.common.config.keys.PublicKeyEntry;
041import org.eclipse.jgit.annotations.NonNull;
042import org.eclipse.jgit.internal.transport.sshd.OpenSshServerKeyDatabase;
043import org.eclipse.jgit.transport.CredentialsProvider;
044import org.eclipse.jgit.transport.sshd.ServerKeyDatabase;
045import org.eclipse.jgit.util.FileUtils;
046import org.junit.Test;
047import org.slf4j.Logger;
048
049/** @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a> */
050public class JGitSshCheckOutCommandTckTest extends GitSshCheckOutCommandTckTest {
051
052    public JGitSshCheckOutCommandTckTest() throws GeneralSecurityException, IOException {
053        super();
054    }
055
056    @Override
057    protected String getScmProvider() {
058        return "jgit";
059    }
060
061    @Override
062    public void initRepo() throws Exception {
063        super.initRepo();
064        JGitTestScmProvider provider =
065                (JGitTestScmProvider) getScmManager().getProviderByRepository(getScmRepository());
066        // accept all hosts
067        provider.registerCheckOutCommandCallback(new Consumer<JGitCheckOutCommand>() {
068            @Override
069            public void accept(JGitCheckOutCommand command) {
070                command.setSshSessionFactorySupplier(AcceptAllHostsSshdSessionFactory::new);
071            }
072        });
073    }
074
075    private static final class AcceptAllHostsSshdSessionFactory extends ScmProviderAwareSshdSessionFactory {
076        public AcceptAllHostsSshdSessionFactory(GitScmProviderRepository repo, Logger logger) {
077            super(repo, logger);
078        }
079
080        @Override
081        protected ServerKeyDatabase createServerKeyDatabase(File homeDir, File sshDir) {
082            return new OpenSshServerKeyDatabase(false, null) {
083                @Override
084                public boolean accept(
085                        @NonNull String connectAddress,
086                        @NonNull InetSocketAddress remoteAddress,
087                        @NonNull PublicKey serverKey,
088                        @NonNull Configuration config,
089                        CredentialsProvider provider) {
090                    return true;
091                }
092            };
093        }
094    }
095
096    @Override
097    protected void deleteDirectory(File directory) throws IOException {
098        if (directory.exists()) {
099            FileUtils.delete(directory, FileUtils.RECURSIVE | FileUtils.RETRY);
100        }
101    }
102
103    @Test
104    public void testCheckOutCommandWithPregeneratedKeysTest() throws Exception {
105        // test key pairs being generated with ssh-keygen (they have a slighly different format than the ones tested
106        // in testCheckOutCommandWithPassphraseTest and testCheckOutCommandTest)
107        configureKeypairFromClasspathResource(getScmRepository(), "sample_rsa", "mySecret");
108        super.testCheckOutCommandTest();
109    }
110
111    private void configureKeypairFromClasspathResource(ScmRepository repository, String resourceName, String passphrase)
112            throws IOException, GeneralSecurityException {
113        // accept public key
114        try (InputStream publicKeyInputStream =
115                this.getClass().getResourceAsStream("/ssh-keypairs/" + resourceName + ".pub")) {
116            PublicKey publicKey = PublicKeyEntry.parsePublicKeyEntry(
117                            IOUtils.toString(publicKeyInputStream, StandardCharsets.US_ASCII))
118                    .resolvePublicKey(null, null, null);
119            acceptedPublicKeys.add(publicKey);
120        }
121        Path privateKeyFile = Files.createTempFile("privateKey", null);
122        // private key into tmp file
123        try (InputStream privateKeyInputStream = this.getClass().getResourceAsStream("/ssh-keypairs/" + resourceName)) {
124            Files.copy(privateKeyInputStream, privateKeyFile, StandardCopyOption.REPLACE_EXISTING);
125        }
126        // configure provider repository with private key details
127        ScmProviderRepositoryWithHost providerRepository =
128                ScmProviderRepositoryWithHost.class.cast(repository.getProviderRepository());
129        providerRepository.setPassphrase(passphrase); // may be null
130        providerRepository.setPrivateKey(privateKeyFile.toString());
131    }
132}