Skip to content

Commit 91c0a95

Browse files
authored
feat!: remove go toolchain from sbom and qualifiers (#191)
## Description Remove architecture-related qualifiers Remove go toolchain dependencies from the sbom **Related issue (if any):** Fix #190 Fix #189 ## Checklist - [x] I have followed this repository's contributing guidelines. - [x] I will adhere to the project's code of conduct. --------- Signed-off-by: Ruben Romero Montes <rromerom@redhat.com>
1 parent 7cc8b93 commit 91c0a95

16 files changed

+2009
-2041
lines changed

src/main/java/com/redhat/exhort/providers/GoModulesProvider.java

Lines changed: 30 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717

1818
import static com.redhat.exhort.impl.ExhortApi.debugLoggingIsNeeded;
1919

20-
import com.fasterxml.jackson.core.JsonProcessingException;
21-
import com.fasterxml.jackson.databind.JsonNode;
22-
import com.fasterxml.jackson.databind.ObjectMapper;
2320
import com.github.packageurl.MalformedPackageURLException;
2421
import com.github.packageurl.PackageURL;
2522
import com.redhat.exhort.Api;
@@ -43,7 +40,6 @@
4340
import java.util.List;
4441
import java.util.Map;
4542
import java.util.Objects;
46-
import java.util.TreeMap;
4743
import java.util.logging.Logger;
4844
import java.util.regex.Pattern;
4945
import java.util.stream.Collectors;
@@ -56,10 +52,7 @@ public final class GoModulesProvider extends Provider {
5652

5753
public static final String PROP_EXHORT_GO_MVS_LOGIC_ENABLED = "EXHORT_GO_MVS_LOGIC_ENABLED";
5854
private static final Logger log = LoggersFactory.getLogger(GoModulesProvider.class.getName());
59-
private static final String GO_HOST_ARCHITECTURE_ENV_NAME = "GOHOSTARCH";
60-
private static final String GO_HOST_OPERATION_SYSTEM_ENV_NAME = "GOHOSTOS";
6155
public static final String DEFAULT_MAIN_VERSION = "v0.0.0";
62-
private final TreeMap<String, String> goEnvironmentVariableForPurl;
6356
private final String goExecutable;
6457

6558
public String getMainModuleVersion() {
@@ -71,7 +64,6 @@ public String getMainModuleVersion() {
7164
public GoModulesProvider(Path manifest) {
7265
super(Type.GOLANG, manifest);
7366
this.goExecutable = Operations.getExecutable("go", "version");
74-
this.goEnvironmentVariableForPurl = getQualifiers();
7567
this.mainModuleVersion = getDefaultMainModuleVersion();
7668
}
7769

@@ -97,34 +89,32 @@ public Content provideComponent() throws IOException {
9789
sbom.getAsJsonString().getBytes(StandardCharsets.UTF_8), Api.CYCLONEDX_MEDIA_TYPE);
9890
}
9991

100-
private PackageURL toPurl(
101-
String dependency, String delimiter, TreeMap<String, String> qualifiers) {
92+
private PackageURL toPurl(String dependency, String delimiter) {
10293
try {
10394
int lastSlashIndex = dependency.lastIndexOf("/");
10495
// there is no '/' char in module/package, so there is no namespace, only name
10596
if (lastSlashIndex == -1) {
10697
String[] splitParts = dependency.split(delimiter);
10798
if (splitParts.length == 2) {
10899
return new PackageURL(
109-
Type.GOLANG.getType(), null, splitParts[0], splitParts[1], qualifiers, null);
100+
Type.GOLANG.getType(), null, splitParts[0], splitParts[1], null, null);
110101
} else {
111102
return new PackageURL(
112-
Type.GOLANG.getType(), null, splitParts[0], this.mainModuleVersion, qualifiers, null);
103+
Type.GOLANG.getType(), null, splitParts[0], this.mainModuleVersion, null, null);
113104
}
114105
}
115106
String namespace = dependency.substring(0, lastSlashIndex);
116107
String dependencyAndVersion = dependency.substring(lastSlashIndex + 1);
117108
String[] parts = dependencyAndVersion.split(delimiter);
118109

119110
if (parts.length == 2) {
120-
return new PackageURL(
121-
Type.GOLANG.getType(), namespace, parts[0], parts[1], qualifiers, null);
111+
return new PackageURL(Type.GOLANG.getType(), namespace, parts[0], parts[1], null, null);
122112
// in this case, there is no version (happens with main module), thus need to take it from
123113
// precalculated
124114
// main module version.
125115
} else {
126116
return new PackageURL(
127-
Type.GOLANG.getType(), namespace, parts[0], this.mainModuleVersion, qualifiers, null);
117+
Type.GOLANG.getType(), namespace, parts[0], this.mainModuleVersion, null, null);
128118
}
129119
} catch (MalformedPackageURLException e) {
130120
throw new IllegalArgumentException(
@@ -294,17 +284,19 @@ private Sbom buildSbomFromGraph(
294284
// Build Sbom
295285
String rootPackage = getParentVertex(linesList.get(0));
296286

297-
PackageURL root = toPurl(rootPackage, "@", this.goEnvironmentVariableForPurl);
287+
PackageURL root = toPurl(rootPackage, "@");
298288
Sbom sbom = SbomFactory.newInstance(Sbom.BelongingCondition.PURL, "sensitive");
299289
sbom.addRoot(root);
300290
edges.forEach(
301291
(key, value) -> {
302-
PackageURL source = toPurl(key, "@", this.goEnvironmentVariableForPurl);
303-
value.forEach(
304-
dep -> {
305-
PackageURL targetPurl = toPurl(dep, "@", this.goEnvironmentVariableForPurl);
306-
sbom.addDependency(source, targetPurl, null);
307-
});
292+
PackageURL source = toPurl(key, "@");
293+
value.stream()
294+
.filter(dep -> !isGoToolchainEntry(dep))
295+
.forEach(
296+
dep -> {
297+
PackageURL targetPurl = toPurl(dep, "@");
298+
sbom.addDependency(source, targetPurl, null);
299+
});
308300
});
309301
List<String> ignoredDepsPurl =
310302
ignoredDeps.stream().map(PackageURL::getCoordinates).collect(Collectors.toList());
@@ -379,41 +371,14 @@ private static List<String> collectAllDirectDependencies(List<String> targetLine
379371
return targetLines.stream()
380372
.filter(line -> getParentVertex(line).equals(getParentVertex(edge)))
381373
.map(GoModulesProvider::getChildVertex)
374+
.filter(dep -> !isGoToolchainEntry(dep))
382375
.collect(Collectors.toList());
383376
}
384377

385-
private TreeMap<String, String> getQualifiers() {
386-
var goEnvironmentVariables = getGoEnvironmentVariables();
387-
var qualifiers = new TreeMap<String, String>();
388-
qualifiers.put("type", "module");
389-
if (goEnvironmentVariables.containsKey(GO_HOST_ARCHITECTURE_ENV_NAME)) {
390-
qualifiers.put("goarch", goEnvironmentVariables.get(GO_HOST_ARCHITECTURE_ENV_NAME));
391-
}
392-
if (goEnvironmentVariables.containsKey(GO_HOST_OPERATION_SYSTEM_ENV_NAME)) {
393-
qualifiers.put("goos", goEnvironmentVariables.get(GO_HOST_OPERATION_SYSTEM_ENV_NAME));
394-
}
395-
396-
return qualifiers;
397-
}
398-
399-
private Map<String, String> getGoEnvironmentVariables() {
400-
String goEnvironmentVariables =
401-
Operations.runProcessGetOutput(null, goExecutable, "env", "--json");
402-
JsonNode tree;
403-
try {
404-
tree = new ObjectMapper().readTree(goEnvironmentVariables);
405-
} catch (JsonProcessingException e) {
406-
throw new RuntimeException("Failed to parse go environment variables: " + e.getMessage());
407-
}
408-
var envMap = new HashMap<String, String>();
409-
tree.fields()
410-
.forEachRemaining(
411-
entry -> {
412-
String key = entry.getKey();
413-
String value = entry.getValue().asText();
414-
envMap.put(key, value);
415-
});
416-
return envMap;
378+
private static boolean isGoToolchainEntry(String dependency) {
379+
// Filter out Go toolchain entries like "go@1.18", "go@1.19", etc.
380+
// These are not actual dependencies but the Go toolchain itself
381+
return dependency.startsWith("go@");
417382
}
418383

419384
private String buildGoModulesDependencies(Path manifestPath) {
@@ -435,19 +400,21 @@ private String buildGoModulesDependencies(Path manifestPath) {
435400
private Sbom buildSbomFromList(String golangDeps, List<PackageURL> ignoredDeps) {
436401
String[] allModulesFlat = golangDeps.split(Operations.GENERIC_LINE_SEPARATOR);
437402
String parentVertex = getParentVertex(allModulesFlat[0]);
438-
PackageURL root = toPurl(parentVertex, "@", this.goEnvironmentVariableForPurl);
403+
PackageURL root = toPurl(parentVertex, "@");
439404
// Get only direct dependencies of root package/module, and that's it.
440405
List<String> deps = collectAllDirectDependencies(Arrays.asList(allModulesFlat), parentVertex);
441406

442407
Sbom sbom = SbomFactory.newInstance(Sbom.BelongingCondition.PURL, "sensitive");
443408
sbom.addRoot(root);
444-
deps.forEach(
445-
dep -> {
446-
PackageURL targetPurl = toPurl(dep, "@", this.goEnvironmentVariableForPurl);
447-
if (dependencyNotToBeIgnored(ignoredDeps, targetPurl)) {
448-
sbom.addDependency(root, targetPurl, null);
449-
}
450-
});
409+
deps.stream()
410+
.filter(dep -> !isGoToolchainEntry(dep))
411+
.forEach(
412+
dep -> {
413+
PackageURL targetPurl = toPurl(dep, "@");
414+
if (dependencyNotToBeIgnored(ignoredDeps, targetPurl)) {
415+
sbom.addDependency(root, targetPurl, null);
416+
}
417+
});
451418
List<String> ignoredDepsByName = new ArrayList<>();
452419
ignoredDeps.forEach(
453420
purl -> {
@@ -467,7 +434,7 @@ private List<PackageURL> getIgnoredDeps(Path manifestPath) throws IOException {
467434
goModlines.stream()
468435
.filter(this::IgnoredLine)
469436
.map(this::extractPackageName)
470-
.map(dep -> toPurl(dep, "\\s{1,3}", this.goEnvironmentVariableForPurl))
437+
.map(dep -> toPurl(dep, "\\s{1,3}"))
471438
.collect(Collectors.toList());
472439
return ignored;
473440
}

src/main/java/com/redhat/exhort/vcs/GitVersionControlSystemImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ public String getNextTagVersion(TagInfo tagInfo) {
121121
}
122122

123123
public String getPseudoVersion(TagInfo tagInfo, String newTagVersion) {
124-
String stringTS = tagInfo.getCommitTimestamp().toString().replaceAll("[:-]|T", "");
124+
String stringTS =
125+
tagInfo.getCommitTimestamp().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
125126
String commitHash12 = tagInfo.getCurrentCommitDigest().substring(0, 12);
126127
return String.format("%s.%s-%s", newTagVersion, stringTS, commitHash12);
127128
}

src/test/resources/msc/golang/expected_sbom_ca.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"group" : "github.com/sample",
1010
"name" : "demo-app",
1111
"version" : "v0.0.0",
12-
"purl" : "pkg:golang/github.com/sample/demo-app@v0.0.0?goarch=amd64&goos=linux&type=module"
12+
"purl" : "pkg:golang/github.com/sample/demo-app@v0.0.0"
1313
}
1414
},
1515
"components" : [
@@ -19,71 +19,71 @@
1919
"group" : "github.com/sample",
2020
"name" : "demo-app",
2121
"version" : "v0.0.0",
22-
"purl" : "pkg:golang/github.com/sample/demo-app@v0.0.0?goarch=amd64&goos=linux&type=module"
22+
"purl" : "pkg:golang/github.com/sample/demo-app@v0.0.0"
2323
},
2424
{
2525
"type" : "library",
2626
"bom-ref" : "pkg:golang/github.com/gin-gonic/gin@v1.6.0",
2727
"group" : "github.com/gin-gonic",
2828
"name" : "gin",
2929
"version" : "v1.6.0",
30-
"purl" : "pkg:golang/github.com/gin-gonic/gin@v1.6.0?goarch=amd64&goos=linux&type=module"
30+
"purl" : "pkg:golang/github.com/gin-gonic/gin@v1.6.0"
3131
},
3232
{
3333
"type" : "library",
3434
"bom-ref" : "pkg:golang/github.com/go-logr/zapr@v1.2.0",
3535
"group" : "github.com/go-logr",
3636
"name" : "zapr",
3737
"version" : "v1.2.0",
38-
"purl" : "pkg:golang/github.com/go-logr/zapr@v1.2.0?goarch=amd64&goos=linux&type=module"
38+
"purl" : "pkg:golang/github.com/go-logr/zapr@v1.2.0"
3939
},
4040
{
4141
"type" : "library",
4242
"bom-ref" : "pkg:golang/github.com/google/uuid@v1.1.1",
4343
"group" : "github.com/google",
4444
"name" : "uuid",
4545
"version" : "v1.1.1",
46-
"purl" : "pkg:golang/github.com/google/uuid@v1.1.1?goarch=amd64&goos=linux&type=module"
46+
"purl" : "pkg:golang/github.com/google/uuid@v1.1.1"
4747
},
4848
{
4949
"type" : "library",
5050
"bom-ref" : "pkg:golang/github.com/ipld/go-car@v0.3.0",
5151
"group" : "github.com/ipld",
5252
"name" : "go-car",
5353
"version" : "v0.3.0",
54-
"purl" : "pkg:golang/github.com/ipld/go-car@v0.3.0?goarch=amd64&goos=linux&type=module"
54+
"purl" : "pkg:golang/github.com/ipld/go-car@v0.3.0"
5555
},
5656
{
5757
"type" : "library",
5858
"bom-ref" : "pkg:golang/github.com/json-iterator/go@v1.1.12",
5959
"group" : "github.com/json-iterator",
6060
"name" : "go",
6161
"version" : "v1.1.12",
62-
"purl" : "pkg:golang/github.com/json-iterator/go@v1.1.12?goarch=amd64&goos=linux&type=module"
62+
"purl" : "pkg:golang/github.com/json-iterator/go@v1.1.12"
6363
},
6464
{
6565
"type" : "library",
6666
"bom-ref" : "pkg:golang/github.com/labstack/echo/v4@v4.1.18-0.20201215153152-4422e3b66b9f",
6767
"group" : "github.com/labstack/echo",
6868
"name" : "v4",
6969
"version" : "v4.1.18-0.20201215153152-4422e3b66b9f",
70-
"purl" : "pkg:golang/github.com/labstack/echo/v4@v4.1.18-0.20201215153152-4422e3b66b9f?goarch=amd64&goos=linux&type=module"
70+
"purl" : "pkg:golang/github.com/labstack/echo/v4@v4.1.18-0.20201215153152-4422e3b66b9f"
7171
},
7272
{
7373
"type" : "library",
7474
"bom-ref" : "pkg:golang/github.com/russellhaering/goxmldsig@v1.1.0",
7575
"group" : "github.com/russellhaering",
7676
"name" : "goxmldsig",
7777
"version" : "v1.1.0",
78-
"purl" : "pkg:golang/github.com/russellhaering/goxmldsig@v1.1.0?goarch=amd64&goos=linux&type=module"
78+
"purl" : "pkg:golang/github.com/russellhaering/goxmldsig@v1.1.0"
7979
},
8080
{
8181
"type" : "library",
8282
"bom-ref" : "pkg:golang/go.elastic.co/apm@v1.11.0",
8383
"group" : "go.elastic.co",
8484
"name" : "apm",
8585
"version" : "v1.11.0",
86-
"purl" : "pkg:golang/go.elastic.co/apm@v1.11.0?goarch=amd64&goos=linux&type=module"
86+
"purl" : "pkg:golang/go.elastic.co/apm@v1.11.0"
8787
}
8888
],
8989
"dependencies" : [

0 commit comments

Comments
 (0)