package org.jfrog.hudson.pipeline.steps; import com.google.inject.Inject; import hudson.Extension; import hudson.model.Result; import hudson.model.Run; import hudson.model.TaskListener; import org.apache.commons.cli.MissingArgumentException; import org.apache.commons.lang.StringUtils; import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl; import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl; import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution; import org.jenkinsci.plugins.workflow.steps.StepContextParameter; import org.jfrog.build.api.util.Log; import org.jfrog.build.client.artifactoryXrayResponse.ArtifactoryXrayResponse; import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryXrayClient; import org.jfrog.hudson.CredentialsConfig; import org.jfrog.hudson.pipeline.types.ArtifactoryServer; import org.jfrog.hudson.pipeline.types.XrayScanConfig; import org.jfrog.hudson.pipeline.types.XrayScanResult; import org.jfrog.hudson.util.JenkinsBuildInfoLog; import org.kohsuke.stapler.DataBoundConstructor; public class XrayScanBuildStep extends AbstractStepImpl { private ArtifactoryServer server; private XrayScanConfig xrayScanConfig; @DataBoundConstructor public XrayScanBuildStep(XrayScanConfig xrayScanConfig, ArtifactoryServer server) { this.xrayScanConfig = xrayScanConfig; this.server = server; } public ArtifactoryServer getServer() { return server; } public XrayScanConfig getXrayScanConfig() { return xrayScanConfig; } public static class Execution extends AbstractSynchronousNonBlockingStepExecution<XrayScanResult> { private static final long serialVersionUID = 1L; @StepContextParameter private transient Run build; @StepContextParameter private transient TaskListener listener; @Inject(optional = true) private transient XrayScanBuildStep step; @Override protected XrayScanResult run() throws Exception { XrayScanConfig xrayScanConfig = step.getXrayScanConfig(); if (StringUtils.isEmpty(xrayScanConfig.getBuildName())) { throw new MissingArgumentException("Xray scan build name is mandatory"); } if (StringUtils.isEmpty(xrayScanConfig.getBuildNumber())) { throw new MissingArgumentException("Xray scan build number is mandatory"); } Log log = new JenkinsBuildInfoLog(listener); ArtifactoryServer server = step.getServer(); CredentialsConfig credentialsConfig = server.createCredentialsConfig(); ArtifactoryXrayClient client = new ArtifactoryXrayClient(server.getUrl(), credentialsConfig.provideUsername(build.getParent()), credentialsConfig.providePassword(build.getParent()), log); ArtifactoryXrayResponse buildScanResult = client.xrayScanBuild(xrayScanConfig.getBuildName(), xrayScanConfig.getBuildNumber(), "jenkins"); XrayScanResult xrayScanResult = new XrayScanResult(buildScanResult); if (xrayScanResult.isFoundVulnerable()) { if (xrayScanConfig.getFailBuild()) { build.setResult(Result.FAILURE); } log.error(xrayScanResult.getScanMassege()); } else { log.info(xrayScanResult.getScanMassege()); } if (StringUtils.isNotEmpty(xrayScanResult.getScanUrl())) { log.info("Xray scan details are available at: " + xrayScanResult.getScanUrl()); } return xrayScanResult; } } @Extension public static final class DescriptorImpl extends AbstractStepDescriptorImpl { public DescriptorImpl() { super(XrayScanBuildStep.Execution.class); } @Override // The step is invoked by ArtifactoryServer by the step name public String getFunctionName() { return "xrayScanBuild"; } @Override public String getDisplayName() { return "Xray build scanning"; } @Override public boolean isAdvanced() { return true; } } }