|
|
|
|
@ -0,0 +1,195 @@
|
|
|
|
|
/** |
|
|
|
|
* Stolen from |
|
|
|
|
* https://github.com/project-ncl/sbomer/blob/3b2ef857e8c0cefe9324ea401fa3fbe53499c615/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/service/PncService.java
|
|
|
|
|
*/ |
|
|
|
|
package com.redhat.pctsec.model.api.service; |
|
|
|
|
|
|
|
|
|
//import jakarta.annotation.PostConstruct;
|
|
|
|
|
//import jakarta.annotation.PreDestroy;
|
|
|
|
|
import jakarta.enterprise.context.ApplicationScoped; |
|
|
|
|
import jakarta.ws.rs.WebApplicationException; |
|
|
|
|
import org.eclipse.microprofile.config.inject.ConfigProperty; |
|
|
|
|
import org.jboss.logging.Logger; |
|
|
|
|
import org.jboss.pnc.client.*; |
|
|
|
|
import org.jboss.pnc.dto.Artifact; |
|
|
|
|
import org.jboss.pnc.dto.Build; |
|
|
|
|
import org.jboss.pnc.dto.BuildConfiguration; |
|
|
|
|
import org.jboss.pnc.dto.ProductVersionRef; |
|
|
|
|
|
|
|
|
|
import java.util.Optional; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* A service to interact with the PNC build system. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
//@ApplicationScoped
|
|
|
|
|
public class PncService { |
|
|
|
|
|
|
|
|
|
private static final Logger log = Logger.getLogger(PncService.class); |
|
|
|
|
|
|
|
|
|
public PncService() { |
|
|
|
|
artifactClient = new ArtifactClient(getConfiguration()); |
|
|
|
|
buildClient = new BuildClient(getConfiguration()); |
|
|
|
|
buildConfigurationClient = new BuildConfigurationClient(getConfiguration()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String getApiUrl() { |
|
|
|
|
return apiUrl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ConfigProperty(name = "pnc.api-url") |
|
|
|
|
String apiUrl; |
|
|
|
|
|
|
|
|
|
ArtifactClient artifactClient; |
|
|
|
|
|
|
|
|
|
BuildClient buildClient; |
|
|
|
|
|
|
|
|
|
BuildConfigurationClient buildConfigurationClient; |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
@PostConstruct |
|
|
|
|
void init() { |
|
|
|
|
artifactClient = new ArtifactClient(getConfiguration()); |
|
|
|
|
buildClient = new BuildClient(getConfiguration()); |
|
|
|
|
buildConfigurationClient = new BuildConfigurationClient(getConfiguration()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PreDestroy |
|
|
|
|
void cleanup() { |
|
|
|
|
artifactClient.close(); |
|
|
|
|
buildClient.close(); |
|
|
|
|
buildConfigurationClient.close(); |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Setup basic configuration to be able to talk to PNC. |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public Configuration getConfiguration() { |
|
|
|
|
return Configuration.builder().host(apiUrl).protocol("http").build(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* <p> |
|
|
|
|
* Fetch information about the PNC {@link Build} identified by the particular {@code buildId}. |
|
|
|
|
* </p> |
|
|
|
|
* |
|
|
|
|
* <p> |
|
|
|
|
* In case the {@link Build} with provided identifier cannot be found {@code null} is returned. |
|
|
|
|
* </p> |
|
|
|
|
* |
|
|
|
|
* @param buildId Tbe {@link Build} identifier in PNC |
|
|
|
|
* @return The {@link Build} object or {@code null} in case the {@link Build} could not be found. |
|
|
|
|
*/ |
|
|
|
|
public Build getBuild(String buildId) { |
|
|
|
|
log.debugv("Fetching Build from PNC with id '{}'", buildId); |
|
|
|
|
try { |
|
|
|
|
return buildClient.getSpecific(buildId); |
|
|
|
|
} catch (RemoteResourceNotFoundException ex) { |
|
|
|
|
log.warnv("Build with id '{}' was not found in PNC", buildId); |
|
|
|
|
return null; |
|
|
|
|
} catch (RemoteResourceException ex) { |
|
|
|
|
throw new WebApplicationException("Build could not be retrieved because PNC responded with an error", ex); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* <p> |
|
|
|
|
* Fetch information about the PNC {@link BuildConfiguration} identified by the particular {@code buildConfigId}. |
|
|
|
|
* </p> |
|
|
|
|
* |
|
|
|
|
* <p> |
|
|
|
|
* In case the {@link BuildConfiguration} with provided identifier cannot be found {@code null} is returned. |
|
|
|
|
* </p> |
|
|
|
|
* |
|
|
|
|
* @param buildId Tbe {@link BuildConfiguration} identifier in PNC |
|
|
|
|
* @return The {@link BuildConfiguration} object or {@code null} in case the {@link BuildConfiguration} could not be |
|
|
|
|
* found. |
|
|
|
|
*/ |
|
|
|
|
public BuildConfiguration getBuildConfig(String buildConfigId) { |
|
|
|
|
log.debugv("Fetching BuildConfig from PNC with id '{}'", buildConfigId); |
|
|
|
|
try { |
|
|
|
|
return buildConfigurationClient.getSpecific(buildConfigId); |
|
|
|
|
} catch (RemoteResourceNotFoundException ex) { |
|
|
|
|
log.warnv("BuildConfig with id '{}' was not found in PNC", buildConfigId); |
|
|
|
|
return null; |
|
|
|
|
} catch (RemoteResourceException ex) { |
|
|
|
|
throw new WebApplicationException( |
|
|
|
|
"BuildConfig could not be retrieved because PNC responded with an error", |
|
|
|
|
ex); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* <p> |
|
|
|
|
* Obtains the {@link ProductVersionRef} for a given PNC {@link Build} identifier. |
|
|
|
|
* <p> |
|
|
|
|
* |
|
|
|
|
* @param buildId The {@link Build} identifier to get the Product Version for. |
|
|
|
|
* @return The {@link ProductVersionRef} object for the related or {@code null} in case it is not possible to obtain |
|
|
|
|
* it. |
|
|
|
|
*/ |
|
|
|
|
public ProductVersionRef getProductVersion(String buildId) { |
|
|
|
|
log.debugv("Fetching Product Version information from PNC for build '{}'", buildId); |
|
|
|
|
|
|
|
|
|
if (buildId == null) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
Build build = getBuild(buildId); |
|
|
|
|
|
|
|
|
|
if (build == null) { |
|
|
|
|
log.warn("Build related to the SBOM could not be found in PNC, interrupting processing"); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
BuildConfiguration buildConfig = getBuildConfig(build.getBuildConfigRevision().getId()); |
|
|
|
|
|
|
|
|
|
if (buildConfig == null) { |
|
|
|
|
log.warn("BuildConfig related to the SBOM could not be found in PNC, interrupting processing"); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ProductVersionRef productVersion = buildConfig.getProductVersion(); |
|
|
|
|
|
|
|
|
|
if (productVersion == null) { |
|
|
|
|
log.warn( |
|
|
|
|
"BuildConfig related to the SBOM does not provide product version information, interrupting processing"); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return productVersion; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Fetch information about the PNC {@link Artifact} identified by the particular purl. |
|
|
|
|
* |
|
|
|
|
* @param purl |
|
|
|
|
* @return The {@link Artifact} object or {@code null} if it cannot be found. |
|
|
|
|
*/ |
|
|
|
|
public Artifact getArtifact(String purl) { |
|
|
|
|
log.debugv("Fetching artifact from PNC for purl '{}'", purl); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
String artifactQuery = "purl==\"" + purl + "\""; |
|
|
|
|
RemoteCollection<Artifact> artifacts = artifactClient |
|
|
|
|
.getAll(null, null, null, Optional.empty(), Optional.of(artifactQuery)); |
|
|
|
|
if (artifacts.size() == 0) { |
|
|
|
|
log.debugv("Artifact with purl '{}' was not found in PNC", purl); |
|
|
|
|
return null; |
|
|
|
|
} else if (artifacts.size() > 1) { |
|
|
|
|
throw new IllegalStateException("There should exist only one artifact with purl " + purl); |
|
|
|
|
} |
|
|
|
|
return artifacts.iterator().next(); |
|
|
|
|
} catch (RemoteResourceNotFoundException ex) { |
|
|
|
|
throw new WebApplicationException("Artifact with purl" + purl + "was not found in PNC", ex); |
|
|
|
|
} catch (RemoteResourceException ex) { |
|
|
|
|
throw new WebApplicationException( |
|
|
|
|
"Artifact with purl" + purl + "could not be retrieved because PNC responded with an error", |
|
|
|
|
ex); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |