Beispiel #1
0
        public void MergeComponentsTest()
        {
            var sbom1 = new Bom
            {
                Components = new List <Component>
                {
                    new Component
                    {
                        Name    = "Component1",
                        Version = "1"
                    }
                }
            };
            var sbom2 = new Bom
            {
                Components = new List <Component>
                {
                    new Component
                    {
                        Name    = "Component2",
                        Version = "1"
                    }
                }
            };

            var result = CycloneDXUtils.Merge(sbom1, sbom2);

            Assert.Equal(2, result.Components.Count);
        }
        public void MetadataPropertiesTest()
        {
            var bom = new Bom
            {
                Metadata = new Metadata
                {
                    Properties = new List <Property>
                    {
                        new Property
                        {
                            Name  = "cdx:test",
                            Value = "test",
                        },
                        new Property
                        {
                            Name  = "internal:test",
                            Value = "test",
                        },
                    }
                }
            };

            CycloneDXUtils.RemoveInternalProperties(bom);

            Assert.Collection <Property>(
                bom.Metadata.Properties,
                item =>
            {
                Assert.Equal("cdx:test", item.Name);
                Assert.Equal("test", item.Value);
            }
                );
        }
        public void FlatMergeComponentsTest()
        {
            var sbom1 = new Bom
            {
                Components = new List <Component>
                {
                    new Component
                    {
                        Name    = "Component1",
                        Version = "1"
                    }
                }
            };
            var sbom2 = new Bom
            {
                Components = new List <Component>
                {
                    new Component
                    {
                        Name    = "Component2",
                        Version = "1"
                    }
                }
            };

            var result = CycloneDXUtils.FlatMerge(sbom1, sbom2);

            Snapshot.Match(result);
        }
Beispiel #4
0
        public void MergeToolsTest()
        {
            var sbom1 = new Bom
            {
                Metadata = new Metadata
                {
                    Tools = new List <Tool>
                    {
                        new Tool
                        {
                            Name    = "Tool1",
                            Version = "1"
                        }
                    }
                }
            };
            var sbom2 = new Bom
            {
                Metadata = new Metadata
                {
                    Tools = new List <Tool>
                    {
                        new Tool
                        {
                            Name    = "Tool2",
                            Version = "1"
                        }
                    }
                }
            };

            var result = CycloneDXUtils.Merge(sbom1, sbom2);

            Assert.Equal(2, result.Metadata.Tools.Count);
        }
        public void FlatMergeToolsTest()
        {
            var sbom1 = new Bom
            {
                Metadata = new Metadata
                {
                    Tools = new List <Tool>
                    {
                        new Tool
                        {
                            Name    = "Tool1",
                            Version = "1"
                        }
                    }
                }
            };
            var sbom2 = new Bom
            {
                Metadata = new Metadata
                {
                    Tools = new List <Tool>
                    {
                        new Tool
                        {
                            Name    = "Tool2",
                            Version = "1"
                        }
                    }
                }
            };

            var result = CycloneDXUtils.FlatMerge(sbom1, sbom2);

            Snapshot.Match(result);
        }
        public void SerialNumbersAreUnique()
        {
            var serialNumber1 = CycloneDXUtils.GenerateSerialNumber();
            var serialNumber2 = CycloneDXUtils.GenerateSerialNumber();

            Assert.NotEqual(serialNumber1, serialNumber2);
        }
        public void MultipleComponentVersionTest()
        {
            var bom = Helpers.ComponentBomHelper(new List <string> {
                "component@1", "component@2"
            });

            var result = CycloneDXUtils.MultipleComponentVersions(bom);

            Assert.Equal(2, result["component"].Count);
        }
Beispiel #8
0
        public void ComponentAddedTest()
        {
            var fromBom = Helpers.ComponentBomHelper(new List <string>());
            var toBom   = Helpers.ComponentBomHelper(new List <string> {
                "component@1"
            });

            var result = CycloneDXUtils.ComponentVersionDiff(fromBom, toBom);

            Assert.Single(result["component"].Added);
        }
        public void SubComponentPropertiesTest()
        {
            var bom = new Bom
            {
                Components = new List <Component>
                {
                    new Component
                    {
                        Components = new List <Component>
                        {
                            new Component
                            {
                                Properties = new List <Property>
                                {
                                    new Property
                                    {
                                        Name  = "cdx:test",
                                        Value = "test",
                                    },
                                    new Property
                                    {
                                        Name  = "internal:test",
                                        Value = "test",
                                    },
                                }
                            },
                        },
                    },
                }
            };

            CycloneDXUtils.RemoveInternalProperties(bom);

            Assert.Collection <Property>(
                bom.Components[0].Components[0].Properties,
                item =>
            {
                Assert.Equal("cdx:test", item.Name);
                Assert.Equal("test", item.Value);
            }
                );
        }
        public void ServicePropertiesTest()
        {
            var bom = new Bom
            {
                Services = new List <Service>
                {
                    new Service
                    {
                        Properties = new List <Property>
                        {
                            new Property
                            {
                                Name  = "cdx:test",
                                Value = "test",
                            },
                            new Property
                            {
                                Name  = "internal:test",
                                Value = "test",
                            },
                        }
                    },
                }
            };

            CycloneDXUtils.RemoveInternalProperties(bom);

            Assert.Collection <Property>(
                bom.Services[0].Properties,
                item =>
            {
                Assert.Equal("cdx:test", item.Name);
                Assert.Equal("test", item.Value);
            }
                );
        }
Beispiel #11
0
        public static async Task <int> Diff(
            string fromFile, string toFile, InputFormat fromFormat, InputFormat toFormat, StandardOutputFormat outputFormat,
            bool componentVersions)
        {
            var fromBomFormat = InputFormatHelper(fromFile, fromFormat);
            var toBomFormat   = InputFormatHelper(toFile, toFormat);

            if (fromBomFormat == BomFormat.Unsupported || toBomFormat == BomFormat.Unsupported)
            {
                return((int)ExitCode.ParameterValidationError);
            }

            var fromBomString = await File.ReadAllTextAsync(fromFile);

            var toBomString = await File.ReadAllTextAsync(toFile);

            var fromBom = CLIUtils.BomDeserializer(fromBomString, fromBomFormat);
            var toBom   = CLIUtils.BomDeserializer(toBomString, toBomFormat);

            var result = new DiffResult();

            if (componentVersions)
            {
                result.ComponentVersions = CycloneDXUtils.ComponentVersionDiff(fromBom, toBom);
            }

            if (outputFormat == StandardOutputFormat.json)
            {
                var options = new JsonSerializerOptions
                {
                    WriteIndented        = true,
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    IgnoreNullValues     = true,
                };

                options.Converters.Add(new Json.Converters.v1_2.ComponentTypeConverter());
                options.Converters.Add(new Json.Converters.v1_2.DataFlowConverter());
                options.Converters.Add(new Json.Converters.v1_2.DateTimeConverter());
                options.Converters.Add(new Json.Converters.v1_2.DependencyConverter());
                options.Converters.Add(new Json.Converters.v1_2.ExternalReferenceTypeConverter());
                options.Converters.Add(new Json.Converters.v1_2.HashAlgorithmConverter());
                options.Converters.Add(new Json.Converters.v1_2.IssueClassificationConverter());
                options.Converters.Add(new Json.Converters.v1_2.LicenseConverter());
                options.Converters.Add(new Json.Converters.v1_2.PatchClassificationConverter());

                Console.WriteLine(JsonSerializer.Serialize(result, options));
            }
            else
            {
                if (result.ComponentVersions != null)
                {
                    Console.WriteLine("Component versions that have changed:");
                    Console.WriteLine();

                    var changes = false;
                    foreach (var entry in result.ComponentVersions)
                    {
                        var componentDiffItem = entry.Value;
                        if (componentDiffItem.Added.Count > 0 || componentDiffItem.Removed.Count > 0)
                        {
                            changes = true;
                            foreach (var component in componentDiffItem.Removed)
                            {
                                Console.WriteLine($"- {component.Group} {component.Name} @ {component.Version}");
                            }
                            foreach (var component in componentDiffItem.Unchanged)
                            {
                                Console.WriteLine($"= {component.Group} {component.Name} @ {component.Version}");
                            }
                            foreach (var component in componentDiffItem.Added)
                            {
                                Console.WriteLine($"+ {component.Group} {component.Name} @ {component.Version}");
                            }
                            Console.WriteLine();
                        }
                    }

                    if (!changes)
                    {
                        Console.WriteLine("None");
                    }

                    Console.WriteLine();
                }
            }

            return((int)ExitCode.Ok);
        }
Beispiel #12
0
        public static async Task <int> Merge(MergeCommandOptions options)
        {
            Contract.Requires(options != null);

            var outputToConsole = string.IsNullOrEmpty(options.OutputFile);

            var outputFormat = options.OutputFormat;

            if (outputFormat == StandardInputOutputSbomFormat.autodetect)
            {
                if (options.OutputFile != null && options.OutputFile.EndsWith(".json", StringComparison.InvariantCulture))
                {
                    outputFormat = StandardInputOutputSbomFormat.json;
                }
                else if (options.OutputFile != null && options.OutputFile.EndsWith(".xml", StringComparison.InvariantCulture))
                {
                    outputFormat = StandardInputOutputSbomFormat.xml;
                }
                else
                {
                    Console.WriteLine($"Unable to auto-detect output format");
                    return((int)ExitCode.ParameterValidationError);
                }
            }

            var outputBom = new Bom();

            foreach (var inputFilename in options.InputFiles)
            {
                if (!outputToConsole)
                {
                    Console.WriteLine($"Processing input file {inputFilename}");
                }
                var inputFormat = options.InputFormat;
                if (inputFormat == StandardInputOutputSbomFormat.autodetect)
                {
                    if (inputFilename.EndsWith(".json", StringComparison.InvariantCulture))
                    {
                        inputFormat = StandardInputOutputSbomFormat.json;
                    }
                    else if (inputFilename.EndsWith(".xml", StringComparison.InvariantCulture))
                    {
                        inputFormat = StandardInputOutputSbomFormat.xml;
                    }
                    else
                    {
                        Console.WriteLine($"Unable to auto-detect format of {inputFilename}");
                        return((int)ExitCode.ParameterValidationError);
                    }
                }

                var bomContents = await File.ReadAllTextAsync(inputFilename);

                Bom inputBom;
                if (inputFormat == StandardInputOutputSbomFormat.json)
                {
                    inputBom = Json.Deserializer.Deserialize(bomContents);
                }
                else
                {
                    inputBom = Xml.Deserializer.Deserialize(bomContents);
                }

                outputBom = CycloneDXUtils.Merge(outputBom, inputBom);
                if (inputBom.Components != null && !outputToConsole)
                {
                    Console.WriteLine($"    Contains {inputBom.Components.Count} components");
                }
            }

            string outputBomString;

            if (outputFormat == StandardInputOutputSbomFormat.json)
            {
                outputBomString = Json.Serializer.Serialize(outputBom);
            }
            else
            {
                outputBomString = Xml.Serializer.Serialize(outputBom);
            }

            if (outputToConsole)
            {
                Console.WriteLine(outputBomString);
            }
            else
            {
                Console.WriteLine("Writing output file...");
                Console.WriteLine($"    Total {outputBom.Components.Count} components");
                await File.WriteAllTextAsync(options.OutputFile, outputBomString);
            }

            return((int)ExitCode.Ok);
        }
        public void HierarchicalMergeComponentsTest()
        {
            var subject = new Component
            {
                Name    = "Thing",
                Version = "1",
            };

            var sbom1 = new Bom
            {
                Metadata = new Metadata
                {
                    Component = new Component
                    {
                        Name    = "System1",
                        Version = "1",
                        BomRef  = "System1@1"
                    }
                },
                Components = new List <Component>
                {
                    new Component
                    {
                        Name    = "Component1",
                        Version = "1",
                        BomRef  = "Component1@1"
                    }
                },
                Dependencies = new List <Dependency>
                {
                    new Dependency
                    {
                        Ref          = "System1@1",
                        Dependencies = new List <Dependency>
                        {
                            new Dependency
                            {
                                Ref = "Component1@1"
                            }
                        }
                    }
                },
                Compositions = new List <Composition>
                {
                    new Composition
                    {
                        Aggregate  = Composition.AggregateType.Complete,
                        Assemblies = new List <string>
                        {
                            "System1@1"
                        },
                        Dependencies = new List <string>
                        {
                            "System1@1"
                        }
                    }
                }
            };
            var sbom2 = new Bom
            {
                Metadata = new Metadata
                {
                    Component = new Component
                    {
                        Name    = "System2",
                        Version = "1",
                        BomRef  = "System2@1"
                    }
                },
                Components = new List <Component>
                {
                    new Component
                    {
                        Name    = "Component2",
                        Version = "1",
                        BomRef  = "Component2@1"
                    }
                },
                Dependencies = new List <Dependency>
                {
                    new Dependency
                    {
                        Ref          = "System2@1",
                        Dependencies = new List <Dependency>
                        {
                            new Dependency
                            {
                                Ref = "Component2@1"
                            }
                        }
                    }
                },
                Compositions = new List <Composition>
                {
                    new Composition
                    {
                        Aggregate  = Composition.AggregateType.Complete,
                        Assemblies = new List <string>
                        {
                            "System2@1"
                        },
                        Dependencies = new List <string>
                        {
                            "System2@1"
                        }
                    }
                }
            };

            var result = CycloneDXUtils.HierarchicalMerge(new [] { sbom1, sbom2 }, subject);

            Snapshot.Match(result);
        }
        public static async Task <int> Analyze(
            string inputFile, InputFormat inputFormat, StandardOutputFormat outputFormat,
            bool multipleComponentVersions)
        {
            var inputBomFormat = InputFormatHelper(inputFile, inputFormat);

            if (inputBomFormat == BomFormat.Unsupported)
            {
                return((int)ExitCode.ParameterValidationError);
            }

            var inputBomString = await InputFileHelper(inputFile);

            if (inputBomString == null)
            {
                return((int)ExitCode.ParameterValidationError);
            }

            var inputBom = CLIUtils.BomDeserializer(inputBomString, inputBomFormat);

            var result = new AnalyzeResult();

            if (multipleComponentVersions)
            {
                result.MultipleComponentVersions = CycloneDXUtils.MultipleComponentVersions(inputBom);
            }

            if (outputFormat == StandardOutputFormat.json)
            {
                var options = new JsonSerializerOptions
                {
                    WriteIndented        = true,
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    IgnoreNullValues     = true,
                };

                options.Converters.Add(new Json.Converters.v1_2.ComponentTypeConverter());
                options.Converters.Add(new Json.Converters.v1_2.DataFlowConverter());
                options.Converters.Add(new Json.Converters.v1_2.DateTimeConverter());
                options.Converters.Add(new Json.Converters.v1_2.DependencyConverter());
                options.Converters.Add(new Json.Converters.v1_2.ExternalReferenceTypeConverter());
                options.Converters.Add(new Json.Converters.v1_2.HashAlgorithmConverter());
                options.Converters.Add(new Json.Converters.v1_2.IssueClassificationConverter());
                options.Converters.Add(new Json.Converters.v1_2.LicenseConverter());
                options.Converters.Add(new Json.Converters.v1_2.PatchClassificationConverter());

                Console.WriteLine(JsonSerializer.Serialize(result, options));
            }
            else
            {
                if (inputBom.Metadata?.Component != null)
                {
                    var component = inputBom.Metadata.Component;
                    Console.WriteLine($"Analysis results for {component.Name}@{component.Version}:");
                }
                else
                {
                    Console.WriteLine("Analysis results:");
                }
                Console.WriteLine();

                if (result.MultipleComponentVersions != null)
                {
                    Console.WriteLine("Components with multiple versions:");
                    Console.WriteLine();
                    if (result.MultipleComponentVersions.Count == 0)
                    {
                        Console.WriteLine("None");
                    }
                    else
                    {
                        foreach (var componentEntry in result.MultipleComponentVersions)
                        {
                            Console.Write(componentEntry.Key);
                            Console.Write(" versions:");
                            foreach (var component in componentEntry.Value)
                            {
                                Console.Write(" ");
                                Console.Write(component.Version);
                            }
                            Console.WriteLine();
                        }
                    }
                    Console.WriteLine();
                }
            }

            return((int)ExitCode.Ok);
        }