org.wso2.security.tools.scanner.dependency.js.reportpublisher.GitUploader.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.security.tools.scanner.dependency.js.reportpublisher.GitUploader.java

Source

/*
 *
 *   Copyright (c) 2018, WSO2 Inc., WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *   WSO2 Inc. 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.wso2.security.tools.scanner.dependency.js.reportpublisher;

import org.apache.log4j.Logger;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.wso2.security.tools.scanner.dependency.js.constants.JSScannerConstants;
import org.wso2.security.tools.scanner.dependency.js.exception.FileHandlerException;
import org.wso2.security.tools.scanner.dependency.js.model.GitUploaderProperties;
import org.wso2.security.tools.scanner.dependency.js.utils.CommonUtils;
import org.wso2.security.tools.scanner.dependency.js.utils.ReportWriter;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * This class is responsible to upload reports to git repository. The generated reports for each products are pushed
 * into the security artifact repo.
 */
public class GitUploader extends ReportUploader {

    private static final Logger log = Logger.getLogger(GitUploader.class);
    private GitUploaderProperties gitUploaderProperties;
    private Git gitRepo;

    /**
     * Constructor to create GitUploader.
     * In this call GitUploader instance created with username, password and artifact url.
     * Meanwhile It clones the artifact repo from github. If the cloned repository exists in local directory
     * pull command will execute.
     *
     * @param gitUploaderProperties This object holds the value of username, password, and repository URL where the scan
     *                              reports should be uploaded.
     * @throws GitAPIException      Exception occurred when clone or pull action executed.
     * @throws FileHandlerException Exception occurred while creating directory.
     */
    public GitUploader(GitUploaderProperties gitUploaderProperties) throws GitAPIException, FileHandlerException {
        super();
        this.gitUploaderProperties = gitUploaderProperties;
        File artifactFile = new File(JSScannerConstants.SECURITY_ARTIFACT_HOME);
        if (!artifactFile.exists()) {
            CommonUtils.createDirectory(artifactFile);
            gitRepo = Git.cloneRepository().setURI(gitUploaderProperties.getRepoURL())
                    .setDirectory(new File(artifactFile.getAbsolutePath()))
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider(
                            new String(gitUploaderProperties.getGitUsername()),
                            new String(gitUploaderProperties.getGitPassword())))
                    .call();
            log.info("[JS_SEC_DAILY_SCAN]  " + "Security artifact repo cloned successfully.");
        } else {
            // If cloned repository exists in local directory, pull command will be executed,
            if (gitPull(artifactFile)) {
                log.error("[JS_SEC_DAILY_SCAN]  " + "Security artifact repo pull action successful.");
            }
        }
    }

    /**
     * Publish report to any endpoint. This inherited method responsible to upload generated reports to github
     * repository.
     *
     * @param productResponseMapper Mapper for product and scan result.
     * @throws GitAPIException      Exception occurred during github API call.
     * @throws FileHandlerException Exception occurred during report generation.
     */
    @Override
    public void publishReport(HashMap<String, String> productResponseMapper)
            throws GitAPIException, FileHandlerException {
        storeFiles(productResponseMapper);
        gitCommit();
        gitPush();
        CommonUtils.clearCredentialData(gitUploaderProperties.getGitUsername(),
                gitUploaderProperties.getGitPassword());
    }

    /**
     * Add generated reports to cloned github repository.
     *
     * @param productResponseMapper Mapper for product and scan result.
     * @throws GitAPIException      Exception occurred during github API call.
     * @throws FileHandlerException Exception occurred during report generation.
     */
    private void storeFiles(HashMap<String, String> productResponseMapper)
            throws GitAPIException, FileHandlerException {
        Repository repository = gitRepo.getRepository();
        File targetDir = new File(repository.getDirectory().getParentFile().getAbsolutePath()
                + JSScannerConstants.SCN_REPORT_DIRECTORY_PATH);
        HashMap<String, String> fileMapper;
        fileMapper = ReportWriter.callWriter(productResponseMapper, targetDir);
        // Stage all files in the repo including new files
        gitRepo.add().addFilepattern(".").call();
        this.setReportFileMapper(fileMapper);
        log.info("[JS_SEC_DAILY_SCAN]  " + "Added files to Security artifact repo");
    }

    /**
     * perform git commit.
     *
     * @throws GitAPIException Exception occurred during git commit.
     */
    private void gitCommit() throws GitAPIException {
        // Commit the changes.
        gitRepo.commit().setMessage("Added Retire.js vulnerability report " + java.time.LocalDate.now().toString())
                .call();
        log.info("[JS_SEC_DAILY_SCAN]  " + "Commit to Security artifact repo");
    }

    /**
     * Perform git push.
     *
     * @throws GitAPIException Exception occurred during gitcommit.
     */
    private void gitPush() throws GitAPIException {
        gitRepo.push()
                .setCredentialsProvider(
                        new UsernamePasswordCredentialsProvider(new String(gitUploaderProperties.getGitUsername()),
                                new String(gitUploaderProperties.getGitPassword())))
                .call();
        log.info("[JS_SEC_DAILY_SCAN]  " + "Push to Security artifact repo");
    }

    /**
     * Execute git pull command on the given repository.
     * It populates an ArrayList with all the updated files.
     *
     * @param localPath The path where the project is.
     * @return Returns true if you should update plugins, false otherwise.
     */
    private boolean gitPull(File localPath) {
        try {
            Repository localRepo = new FileRepository(localPath.getAbsolutePath() + "/.git");
            gitRepo = new Git(localRepo);
            if (populateDiff()) {
                PullCommand pullCmd = gitRepo.pull();
                pullCmd.setCredentialsProvider(
                        new UsernamePasswordCredentialsProvider(new String(gitUploaderProperties.getGitUsername()),
                                new String(gitUploaderProperties.getGitPassword())))
                        .call();
                return true;
            }
        } catch (GitAPIException | IOException e) {
            log.error("Failed to pull : " + localPath.getName(), e);
            return false;
        }
        return true;
    }

    /**
     * Populate all the files to update, if the system should update.
     */
    private boolean populateDiff() {
        try {
            gitRepo.fetch()
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider(
                            new String(gitUploaderProperties.getGitUsername()),
                            new String(gitUploaderProperties.getGitPassword())))
                    .call();
            Repository repo = gitRepo.getRepository();
            ObjectId fetchHead = repo.resolve("FETCH_HEAD^{tree}");
            ObjectId head = repo.resolve("HEAD^{tree}");
            ObjectReader reader = repo.newObjectReader();
            CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
            oldTreeIter.reset(reader, head);
            CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
            newTreeIter.reset(reader, fetchHead);
            List<DiffEntry> diffs = gitRepo.diff().setShowNameAndStatusOnly(true).setNewTree(newTreeIter)
                    .setOldTree(oldTreeIter).call();
            return !diffs.isEmpty();
        } catch (GitAPIException | IOException e) {
            log.error("[JS_SEC_DAILY_SCAN]  " + "Security artifact repo pull action failed.", e);
        }
        return true;
    }

}