Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for vulnerability data to entities model #6875

Merged
merged 16 commits into from
Feb 8, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/NuGet.Services.Entities/CVE.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace NuGet.Services.Entities
{
/// <summary>
/// Represents a Common Vulnerability and Exposure (CVE).
/// </summary>
public class CVE
: IEntity
{
/// <summary>
/// Gets or sets the primary key for the entity.
/// </summary>
public int Key { get; set; }

/// <summary>
/// Gets or sets the unique CVE ID.
/// The CVE ID number has four or more digits in the sequence number portion of the ID (e.g., "CVE-1999-0067", "CVE-2014-12345", "CVE-2016-7654321").
/// </summary>
// sources:
// * https://cve.mitre.org/cve/identifiers/syntaxchange.html
// * https://cve.mitre.org/about/faqs.html#what_is_cve_id
[Index(IsUnique = true)]
[Required]
[MaxLength(20)]
public string CVEId { get; set; }
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets or sets the description of the CVE.
/// The description is a plain language field that describes the vulnerability with sufficient detail as to demonstrate that the vulnerability is unique.
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
[MaxLength(4000)]
[Required]
public string Description { get; set; }
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved

public virtual ICollection<PackageDeprecation> PackageDeprecations { get; set; }
}
}
45 changes: 45 additions & 0 deletions src/NuGet.Services.Entities/CWE.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace NuGet.Services.Entities
{
/// <summary>
/// Represents a Common Weakness Enumeration (CWE).
/// </summary>
public class CWE
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved
: IEntity
{
/// <summary>
/// Gets or sets the primary key for the entity.
/// </summary>
public int Key { get; set; }

/// <summary>
/// Gets or sets the unique CWE-ID.
/// </summary>
[Index(IsUnique = true)]
[Required]
[MaxLength(20)]
public string CWEId { get; set; }

/// <summary>
/// Gets or sets the name of the CWE.
/// </summary>
[MaxLength(200)]
[Required]
public string Name { get; set; }
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets or sets the description of the CWE.
/// </summary>
[MaxLength(600)]
[Required]
public string Description { get; set; }
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved

public virtual ICollection<PackageDeprecation> PackageDeprecations { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/NuGet.Services.Entities/NuGet.Services.Entities.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
<Compile Include="Credential.cs" />
<Compile Include="CuratedFeed.cs" />
<Compile Include="CuratedPackage.cs" />
<Compile Include="CVE.cs" />
<Compile Include="CWE.cs" />
<Compile Include="EmailMessage.cs" />
<Compile Include="EmbeddedLicenseFileType.cs" />
<Compile Include="EntityException.cs" />
Expand Down
11 changes: 5 additions & 6 deletions src/NuGet.Services.Entities/PackageDeprecation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

Expand Down Expand Up @@ -93,15 +94,13 @@ public class PackageDeprecation
public decimal? CVSSRating { get; set; }
xavierdecoster marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets or sets the serialized JSON object containing an array of CVE ID's related to this deprecation.
/// The JSON object should have a version property that defines the version of its schema.
/// Gets or sets the collection of CVE's related to this deprecation.
/// </summary>
public string CVEIds { get; set; }
public virtual ICollection<CVE> CVEs { get; set; }

/// <summary>
/// Gets or sets the serialized JSON object containing an array of CWE ID's related to this deprecation.
/// The JSON object should have a version property that defines the version of its schema.
/// Gets or sets the collection of CWE's related to this deprecation.
/// </summary>
public string CWEIds { get; set; }
public virtual ICollection<CWE> CWEs { get; set; }
}
}
39 changes: 39 additions & 0 deletions src/NuGetGallery.Core/Entities/EntitiesContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public EntitiesContext(DbConnection connection, bool readOnly)
/// User or organization accounts.
/// </summary>
public IDbSet<User> Users { get; set; }
public IDbSet<CVE> CVEs { get; set; }
public IDbSet<CWE> CWEs { get; set; }

IDbSet<T> IEntitiesContext.Set<T>()
{
Expand Down Expand Up @@ -371,6 +373,35 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Entity<PackageDeprecation>()
.HasKey(d => d.Key);

modelBuilder.Entity<CVE>()
.HasKey(d => d.Key)
.Property(e => e.CVEId)
.HasColumnType("varchar")
.HasMaxLength(20)
.IsRequired();

modelBuilder.Entity<CVE>()
.Property(e => e.Description)
.HasMaxLength(4000)
.IsRequired();

modelBuilder.Entity<CWE>()
.HasKey(d => d.Key)
.Property(e => e.CWEId)
.HasColumnType("varchar")
.HasMaxLength(20)
.IsRequired();

modelBuilder.Entity<CWE>()
.Property(e => e.Name)
.HasMaxLength(200)
.IsRequired();

modelBuilder.Entity<CWE>()
.Property(e => e.Description)
.HasMaxLength(600)
.IsRequired();

modelBuilder.Entity<Package>()
.HasMany(p => p.Deprecations)
.WithRequired(d => d.Package)
Expand Down Expand Up @@ -398,6 +429,14 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Entity<PackageDeprecation>()
.Property(v => v.CVSSRating)
.HasPrecision(3, 1);

modelBuilder.Entity<PackageDeprecation>()
.HasMany(p => p.CVEs)
.WithMany(c => c.PackageDeprecations);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we verified that when

  • a PackageDeprecation is deleted, it deletes the corresponding rows in the PackageDeprecationCVE/PackageDeprecationCWEs tables?
  • a CVE/CWE is deleted, it deletes the corresponding rows in the PackageDeprecationCVE/PackageDeprecationCWEs tables?

Or is this not the behavior we want to have?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a key insight.

This is quite important because we need to understand what to do when a CVE/CWE is not longer present in the data source or if some "delete" signal is presented to us. I think the easiest approach is to mandate that CVE/CWEs are never deleted. If this is already the case in the data source, then we're fine. Otherwise, we need to verify that it's okay for us to keep a deleted CVE/CWE in our database forever.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can assume these ID's are never hard-deleted, although I couldn't find an official statement on that.

In general, MITRE will maintain CWE as long as it serves the community to do so.

As for CVE IDs, these will be marked with a "reject" state and the "description" field will be labeled as such in the data source, according to this source.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified delete behavior:

  • when deleting a PackageDeprecation, it properly deletes the corresponding rows in the PackageDeprecationCwe and PackageDeprecationCve tables, but doesn't delete the CWE or CVE record.
  • when deleting a CVE or CWE, it properly deletes the corresponding rows in the PackageDeprecationCwe and PackageDeprecationCve tables, but doesn't delete the PackageDeprecation record.

However, we should never delete CVE or CWE records (adding a Status column to those entities for when a CVE/CWE gets rejected after publication, so we can filter them out).


modelBuilder.Entity<PackageDeprecation>()
.HasMany(p => p.CWEs)
.WithMany(c => c.PackageDeprecations);
}
#pragma warning restore 618
}
Expand Down
2 changes: 2 additions & 0 deletions src/NuGetGallery.Core/Entities/IEntitiesContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public interface IEntitiesContext
IDbSet<ReservedNamespace> ReservedNamespaces { get; set; }
IDbSet<UserCertificate> UserCertificates { get; set; }
IDbSet<SymbolPackage> SymbolPackages { get; set; }
IDbSet<CVE> CVEs { get; set; }
IDbSet<CWE> CWEs { get; set; }

Task<int> SaveChangesAsync();
IDbSet<T> Set<T>() where T : class;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
namespace NuGetGallery.Migrations
{
using System;
using System.Data.Entity.Migrations;

public partial class AddVulnerabilityEntities : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.CVEs",
c => new
{
Key = c.Int(nullable: false, identity: true),
CVEId = c.String(nullable: false, maxLength: 20, unicode: false),
Description = c.String(nullable: false, maxLength: 4000),
})
.PrimaryKey(t => t.Key)
.Index(t => t.CVEId, unique: true);

CreateTable(
"dbo.CWEs",
c => new
{
Key = c.Int(nullable: false, identity: true),
CWEId = c.String(nullable: false, maxLength: 20, unicode: false),
Name = c.String(nullable: false, maxLength: 200),
Description = c.String(nullable: false, maxLength: 600),
})
.PrimaryKey(t => t.Key)
.Index(t => t.CWEId, unique: true);

CreateTable(
"dbo.PackageDeprecationCVEs",
c => new
{
PackageDeprecation_Key = c.Int(nullable: false),
CVE_Key = c.Int(nullable: false),
})
.PrimaryKey(t => new { t.PackageDeprecation_Key, t.CVE_Key })
.ForeignKey("dbo.PackageDeprecations", t => t.PackageDeprecation_Key, cascadeDelete: true)
.ForeignKey("dbo.CVEs", t => t.CVE_Key, cascadeDelete: true)
.Index(t => t.PackageDeprecation_Key)
.Index(t => t.CVE_Key);

CreateTable(
"dbo.PackageDeprecationCWEs",
c => new
{
PackageDeprecation_Key = c.Int(nullable: false),
CWE_Key = c.Int(nullable: false),
})
.PrimaryKey(t => new { t.PackageDeprecation_Key, t.CWE_Key })
.ForeignKey("dbo.PackageDeprecations", t => t.PackageDeprecation_Key, cascadeDelete: true)
.ForeignKey("dbo.CWEs", t => t.CWE_Key, cascadeDelete: true)
.Index(t => t.PackageDeprecation_Key)
.Index(t => t.CWE_Key);

DropColumn("dbo.PackageDeprecations", "CVEIds");
DropColumn("dbo.PackageDeprecations", "CWEIds");
}

public override void Down()
{
AddColumn("dbo.PackageDeprecations", "CWEIds", c => c.String());
AddColumn("dbo.PackageDeprecations", "CVEIds", c => c.String());
DropForeignKey("dbo.PackageDeprecationCWEs", "CWE_Key", "dbo.CWEs");
DropForeignKey("dbo.PackageDeprecationCWEs", "PackageDeprecation_Key", "dbo.PackageDeprecations");
DropForeignKey("dbo.PackageDeprecationCVEs", "CVE_Key", "dbo.CVEs");
DropForeignKey("dbo.PackageDeprecationCVEs", "PackageDeprecation_Key", "dbo.PackageDeprecations");
DropIndex("dbo.PackageDeprecationCWEs", new[] { "CWE_Key" });
DropIndex("dbo.PackageDeprecationCWEs", new[] { "PackageDeprecation_Key" });
DropIndex("dbo.PackageDeprecationCVEs", new[] { "CVE_Key" });
DropIndex("dbo.PackageDeprecationCVEs", new[] { "PackageDeprecation_Key" });
DropIndex("dbo.CWEs", new[] { "CWEId" });
DropIndex("dbo.CVEs", new[] { "CVEId" });
DropTable("dbo.PackageDeprecationCWEs");
DropTable("dbo.PackageDeprecationCVEs");
DropTable("dbo.CWEs");
DropTable("dbo.CVEs");
}
}
}