Example #1
0
        public async Task ExtractOwnershipFromK8sAudit()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();

            var cache     = new OwnershipCache(context, new MemoryCache(new MemoryCacheOptions()));
            var processor = new ExtractOwnershipProcessor(context, cache);

            context.Ownership.Count().Should().Be(0, "ownership list should be empty");

            var auditMetaPath = Path.Combine("audits", "samples", "k8s_audit.json");

            var audit = new Audit
            {
                MetadataKube = new MetadataKube
                {
                    Id      = 1,
                    AuditId = string.Empty,
                    Date    = DateTime.Now,
                    JSON    = File.ReadAllText(auditMetaPath),
                },
            };

            await processor.Process(audit, CancellationToken.None);

            var list = context.Ownership.ToList();

            context.Ownership.Count().Should().Be(2, "ownership list should have 2 items");
        }
Example #2
0
        public async Task ExtractOwnershipFromAzskAudit()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();

            context.Ownership.Count().Should().Be(0, "ownership list should be empty");

            var cache         = new OwnershipCache(context, new MemoryCache(new MemoryCacheOptions()));
            var processor     = new ExtractOwnershipProcessor(context, cache);
            var auditMetaPath = Path.Combine("audits", "samples", "azsk_audit.json");

            var audit = new Audit
            {
                MetadataAzure = new MetadataAzure
                {
                    Id      = 1,
                    AuditId = string.Empty,
                    Date    = DateTime.Now,
                    JSON    = File.ReadAllText(auditMetaPath),
                },
            };

            await processor.Process(audit, CancellationToken.None);

            var list = context.Ownership.ToList();

            context.Ownership.Count().Should().Be(17, "ownership list should have 17 items");

            foreach (var expectedComponentId in azskAuditComponentIds)
            {
                var item = context.Ownership.FirstOrDefault(x => x.ComponentId == expectedComponentId);
                item.Should().NotBe(null, expectedComponentId);
            }
        }
        public async Task SaveInProgressImageScanSavesCorrectEntity()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser = new ConfigurationParser("config.sample.yaml");
            var db     = new MssqlJosekiDatabase(context, parser);
            var scan   = new ImageScanResultWithCVEs
            {
                Date        = DateTime.UtcNow,
                Id          = Guid.NewGuid().ToString(),
                Description = Guid.NewGuid().ToString(),
                ImageTag    = Guid.NewGuid().ToString(),
                Status      = ImageScanStatus.Queued,
            };

            // Act & Assert
            context.ImageScanResult.Should().HaveCount(0);
            await db.SaveInProgressImageScan(scan);

            context.ImageScanResult.Should().HaveCount(1);

            var actual = await context.ImageScanResult.FirstAsync();

            actual.Date.Should().Be(scan.Date);
            actual.ExternalId.Should().Be(scan.Id);
            actual.Description.Should().Be(scan.Description);
            actual.ImageTag.Should().Be(scan.ImageTag);
            actual.Status.Should().Be(joseki.db.entities.ImageScanStatus.Queued);
        }
Example #4
0
        public async Task GetLastMonthAuditsReturnsOnlyRequestedComponentAudits()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var auditDate         = DateTime.UtcNow.Date.AddDays(-1);
            var expectedComponent = this.GenerateComponent();
            var anotherComponent  = this.GenerateComponent();
            await context.Audit.AddRangeAsync(new[]
            {
                new AuditEntity {
                    Date = auditDate, ComponentId = expectedComponent.ComponentId, InfrastructureComponent = expectedComponent
                },
                new AuditEntity {
                    Date = DateTime.UtcNow.AddDays(-2), ComponentId = anotherComponent.ComponentId, InfrastructureComponent = anotherComponent
                },
            });

            await context.SaveChangesAsync();

            // Act & Assert
            var audits = await wrapper.GetLastMonthAudits(expectedComponent.ComponentId);

            audits.Should().ContainSingle(a => a.ComponentId == expectedComponent.ComponentId && a.Date == auditDate);
        }
        public async Task SaveAuditResultSavesKubeMetadata()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser = new ConfigurationParser("config.sample.yaml");
            var db     = new MssqlJosekiDatabase(context, parser);
            var audit  = new Audit
            {
                MetadataKube = new MetadataKube
                {
                    Date = DateTime.UtcNow,
                    JSON = Guid.NewGuid().ToString(),
                },
            };

            // Act & Assert
            context.MetadataKube.Should().HaveCount(0);
            await db.SaveAuditResult(audit);

            context.MetadataKube.Should().HaveCount(1);

            var actual = await context.MetadataKube.FirstAsync();

            actual.JSON.Should().Be(audit.MetadataKube.JSON);
            actual.Date.Should().Be(audit.MetadataKube.Date);
        }
Example #6
0
        public async Task GetAuditsReturnsOnlyLatestAuditAtRequestedDate()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            // create three audits a day before at 00:00, 08:00, 16:00
            var component = this.GenerateComponent();
            var auditDate = DateTime.UtcNow.Date.AddDays(-1);
            var entities  = Enumerable
                            .Range(0, 3)
                            .Select(i => new AuditEntity {
                Date = auditDate.AddHours(i * 8), ComponentId = component.ComponentId, InfrastructureComponent = component
            });
            await context.Audit.AddRangeAsync(entities);

            await context.SaveChangesAsync();

            // Act
            var audits = await wrapper.GetAudits(auditDate);

            // Assert
            // returned audit should be the latest one at requested day
            audits.Should().ContainSingle(i => i.Date.Hour == 16);
        }
Example #7
0
        public async Task GetLastMonthAuditsReturnsOnlyLatestAuditAtAnyGivenDay()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            // create three audits at each day at 00:00, 08:00, 16:00
            var expectedComponent = this.GenerateComponent();
            var today             = DateTime.UtcNow.Date;

            foreach (var auditDate in Enumerable.Range(0, 31).Select(i => today.AddDays(-i)))
            {
                var entities = Enumerable
                               .Range(0, 3)
                               .Select(i => new AuditEntity {
                    Date = auditDate.AddHours(i * 8), ComponentId = expectedComponent.ComponentId, InfrastructureComponent = expectedComponent
                });
                await context.Audit.AddRangeAsync(entities);
            }

            await context.SaveChangesAsync();

            // Act
            var audits = await wrapper.GetLastMonthAudits(expectedComponent.ComponentId);

            // Assert
            // returned audit should be the latest one at each day
            audits.Should().HaveCount(31);
            audits.All(i => i.Date.Hour == 16).Should().BeTrue();
        }
Example #8
0
        public async Task GetAuditReturnsOnlyAuditAtRequestedDay()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var auditDate = DateTime.UtcNow.Date.AddDays(-1);
            var component = this.GenerateComponent();
            await context.Audit.AddRangeAsync(new[]
            {
                new AuditEntity {
                    Date = auditDate, ComponentId = component.ComponentId, InfrastructureComponent = component
                },
                new AuditEntity {
                    Date = auditDate.AddDays(-1), ComponentId = component.ComponentId, InfrastructureComponent = component
                },
            });

            await context.SaveChangesAsync();

            // Act
            var audit = await wrapper.GetAudit(component.ComponentId, auditDate);

            // Assert
            audit.ComponentId.Should().Be(component.ComponentId);
            audit.Date.Should().Be(auditDate);
        }
Example #9
0
        public async Task GetCounterSummariesForAuditReturnsZeroSummaryForNotExistingId()
        {
            // Arrange
            var randomizer = new Random();

            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var auditId = randomizer.Next();
            await context.CheckResult.AddRangeAsync(new[]
            {
                new CheckResultEntity {
                    AuditId = auditId - 1, Value = CheckValue.Succeeded, Check = new CheckEntity {
                        Severity = CheckSeverity.Critical
                    }
                },
                new CheckResultEntity {
                    AuditId = auditId + 1, Value = CheckValue.Succeeded, Check = new CheckEntity {
                        Severity = CheckSeverity.Critical
                    }
                },
            });

            await context.SaveChangesAsync();

            // Act
            var summary = await wrapper.GetCounterSummariesForAudit(auditId);

            // Assert
            summary.Failed.Should().Be(0);
            summary.Warning.Should().Be(0);
            summary.NoData.Should().Be(0);
            summary.Passed.Should().Be(0);
        }
Example #10
0
        public async Task GetLastMonthAuditsReturnsOnlyLast31DaysAudits()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var expectedComponent = this.GenerateComponent();
            var today             = DateTime.UtcNow.Date;
            var entities          = Enumerable
                                    .Range(0, 35)
                                    .Select(i => new AuditEntity {
                Date = today.AddDays(-i), ComponentId = expectedComponent.ComponentId, InfrastructureComponent = expectedComponent
            });

            await context.Audit.AddRangeAsync(entities);

            await context.SaveChangesAsync();

            // Act
            var audits = await wrapper.GetLastMonthAudits(expectedComponent.ComponentId);

            // Assert
            var oneMonthAgo = today.AddDays(-30);

            audits.Should().HaveCount(31);
            audits.All(i => i.Date >= oneMonthAgo).Should().BeTrue();
        }
Example #11
0
        public async Task GetCounterSummariesForAuditCountsNoDataAndInProgressAsNoData()
        {
            // Arrange
            var randomizer = new Random();

            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var auditId = randomizer.Next();
            await context.CheckResult.AddRangeAsync(new[]
            {
                new CheckResultEntity {
                    AuditId = auditId, Value = CheckValue.NoData, Check = new CheckEntity {
                        Severity = CheckSeverity.Critical
                    }
                },
                new CheckResultEntity {
                    AuditId = auditId, Value = CheckValue.InProgress, Check = new CheckEntity {
                        Severity = CheckSeverity.High
                    }
                },
            });

            await context.SaveChangesAsync();

            // Act
            var summary = await wrapper.GetCounterSummariesForAudit(auditId);

            // Assert
            summary.Failed.Should().Be(0);
            summary.Warning.Should().Be(0);
            summary.NoData.Should().Be(2);
            summary.Passed.Should().Be(0);
        }
Example #12
0
        public async Task TestCascadedOwnership_BlankObjectAndGroupOwnerShouldReturnRootLevel()
        {
            await using var context = JosekiTestsDb.CreateUniqueContext();

            const string rootLevelId   = "/subscriptions/0000-000-000-0000";
            const string groupLevelId  = "/subscriptions/0000-000-000-0000/resource_group/das-rg";
            const string objectLevelId = "/subscriptions/0000-000-000-0000/resource_group/das-rg/VirtualNetwork/das-vn";

            context.Ownership.AddRange(new OwnershipEntity[]
            {
                new OwnershipEntity
                {
                    ComponentId = rootLevelId,
                    Owner       = "*****@*****.**",
                },
                new OwnershipEntity
                {
                    ComponentId = groupLevelId,
                    Owner       = string.Empty,
                },
                new OwnershipEntity
                {
                    ComponentId = objectLevelId,
                    Owner       = string.Empty,
                },
            });
            await context.SaveChangesAsync();

            var ownershipCache = new OwnershipCache(context, new MemoryCache(new MemoryCacheOptions()));

            var owner = await ownershipCache.GetOwner(objectLevelId);

            owner.Should().Be("*****@*****.**");
        }
        public async Task SaveAuditResultSavesCorrectAudit()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser = new ConfigurationParser("config.sample.yaml");
            var db     = new MssqlJosekiDatabase(context, parser);
            var audit  = new Audit
            {
                ComponentId   = Guid.NewGuid().ToString(),
                ComponentName = Guid.NewGuid().ToString(),
                Date          = DateTime.UtcNow,
                ScannerId     = Guid.NewGuid().ToString(),
                Id            = Guid.NewGuid().ToString(),
            };

            // Act & Assert
            context.Audit.Should().HaveCount(0);
            await db.SaveAuditResult(audit);

            context.Audit.Should().HaveCount(1);

            var actual = await context.Audit.FirstAsync();

            actual.AuditId.Should().Be(audit.Id);
            actual.Date.Should().Be(audit.Date);
            actual.ComponentId.Should().Be(audit.ComponentId);
        }
Example #14
0
        public async Task GetAuditsReturnsOnlyUniqueComponentAudits()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var auditDate  = DateTime.UtcNow.Date.AddDays(-1);
            var component1 = this.GenerateComponent();
            var component2 = this.GenerateComponent();
            var component3 = this.GenerateComponent();
            await context.Audit.AddRangeAsync(new[]
            {
                new AuditEntity {
                    Id = 1, Date = auditDate, ComponentId = component1.ComponentId, InfrastructureComponent = component1
                },                                                                                                                        // this one should be ignored
                new AuditEntity {
                    Id = 2, Date = auditDate.AddHours(6), ComponentId = component1.ComponentId, InfrastructureComponent = component1
                },
                new AuditEntity {
                    Id = 3, Date = auditDate.AddHours(12), ComponentId = component2.ComponentId, InfrastructureComponent = component2
                },
                new AuditEntity {
                    Id = 4, Date = auditDate.AddHours(23), ComponentId = component3.ComponentId, InfrastructureComponent = component3
                },
            });

            await context.SaveChangesAsync();

            // Act
            var audits = await wrapper.GetAudits(auditDate);

            // Assert
            audits.Should().HaveCount(3);
            audits.All(i => i.Id > 1).Should().BeTrue();
        }
        public async Task GetAuditedComponentsWithHistoryReturnsOnlyOneMonthData()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();

            var parser = new ConfigurationParser("config.sample.yaml");
            var db     = new MssqlJosekiDatabase(context, parser);

            var componentId = Guid.NewGuid().ToString();
            var today       = DateTime.UtcNow;

            // create more than 31 entries, which the oldest ones would be filtered-out
            var entities = Enumerable.Range(0, 35)
                           .Select(i => today.AddDays(-i)).Select(i => new AuditEntity
            {
                Date                    = i,
                ComponentId             = componentId,
                InfrastructureComponent = new InfrastructureComponentEntity(),
            });

            context.AddRange(entities);
            await context.SaveChangesAsync();

            // Act & Assert
            var audits = await db.GetAuditedComponentsWithHistory(today);

            audits.Should().HaveCount(31);
            audits.All(i => i.Date >= today.AddDays(-30)).Should().BeTrue("All audits should be not earlier than 30 days ago");
        }
Example #16
0
        public async Task GetAllComponentsIdsReturnsOnlyUniqueIds()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var today       = DateTime.UtcNow.Date;
            var componentId = Guid.NewGuid().ToString();
            var audits      = new[]
            {
                new AuditEntity {
                    Date = today, ComponentId = componentId
                },
                new AuditEntity {
                    Date = today.AddDays(-1), ComponentId = componentId
                },
            };
            await context.Audit.AddRangeAsync(audits);

            await context.SaveChangesAsync();

            // Act & Assert
            var allComponentsIds = await wrapper.GetAllComponentsIds();

            // returned array should have the only one componentId
            allComponentsIds.Should().ContainSingle(componentId);
        }
        public async Task GetNotExpiredImageScansReturnsTheLatestScan()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();

            var parser = new ConfigurationParser("config.sample.yaml");
            var db     = new MssqlJosekiDatabase(context, parser);

            var tag   = Guid.NewGuid().ToString();
            var scans = new[]
            {
                new ImageScanResultEntity {
                    ImageTag = tag, Date = DateTime.UtcNow.AddHours(-5), Status = joseki.db.entities.ImageScanStatus.Failed
                },
                new ImageScanResultEntity {
                    ImageTag = tag, Date = DateTime.UtcNow, Status = joseki.db.entities.ImageScanStatus.Queued
                },
                new ImageScanResultEntity {
                    ImageTag = tag, Date = DateTime.UtcNow.AddHours(-3), Status = joseki.db.entities.ImageScanStatus.Succeeded
                },
            };

            context.ImageScanResult.AddRange(scans);
            await context.SaveChangesAsync();

            // Act & Assert
            var notExpiredScans = await db.GetNotExpiredImageScans(new[] { tag });

            notExpiredScans.Should().HaveCount(1);
            notExpiredScans.First().Status.Should().Be(ImageScanStatus.Queued);
        }
Example #18
0
        public async Task GetAuditsReturnsOnlyAuditsAtRequestedDay()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var wrapper = new InfraScoreDbWrapper(context);

            var auditDate  = DateTime.UtcNow.Date.AddDays(-1);
            var component1 = this.GenerateComponent();
            var component2 = this.GenerateComponent();
            var component3 = this.GenerateComponent();
            await context.Audit.AddRangeAsync(new[]
            {
                new AuditEntity {
                    Date = auditDate, ComponentId = component1.ComponentId, InfrastructureComponent = component1
                },
                new AuditEntity {
                    Date = auditDate.AddDays(-1), ComponentId = component2.ComponentId, InfrastructureComponent = component2
                },
                new AuditEntity {
                    Date = auditDate.AddDays(1), ComponentId = component3.ComponentId, InfrastructureComponent = component3
                },
            });

            await context.SaveChangesAsync();

            // Act
            var audits = await wrapper.GetAudits(auditDate);

            // Assert
            audits.Should().ContainSingle(i => i.Date == auditDate);
        }
        public async Task ProcessAuditHappyPath()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser      = new ConfigurationParser("config.sample.yaml");
            var checksCache = new ChecksCache(parser, context, new MemoryCache(new MemoryCacheOptions()));

            var blobsMock = new Mock <IBlobStorageProcessor>(MockBehavior.Strict);
            var dbMock    = new Mock <IJosekiDatabase>();
            var queueMock = new Mock <IQueue>();

            var ownershipCache = new OwnershipCache(context, new MemoryCache(new MemoryCacheOptions()));
            var postProcessor  = new Mock <ExtractOwnershipProcessor>(context, ownershipCache);
            var processor      = new PolarisAuditProcessor(blobsMock.Object, dbMock.Object, checksCache, queueMock.Object, postProcessor.Object);

            var container = new ScannerContainer(Path.Combine("audits", "samples", "polaris"))
            {
                Metadata = new ScannerMetadata
                {
                    Type = ScannerType.Polaris,
                    Id   = Guid.NewGuid().ToString(),
                },
            };
            var audit = new AuditBlob {
                Name = "meta.json", ParentContainer = container
            };

            blobsMock
            .Setup(i => i.GetUnprocessedAudits(container))
            .ReturnsAsync(new[] { audit })
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/{audit.Name}"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/{audit.Name}"))
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/audit.json"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/audit.json"))
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/k8s-meta.json"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/k8s-meta.json"))
            .Verifiable();
            blobsMock
            .Setup(i => i.MarkAsProcessed(audit))
            .Returns(Task.CompletedTask)
            .Verifiable();

            // Act & Assert
            await processor.Process(container, CancellationToken.None);

            blobsMock.Verify();

            dbMock.Verify(i => i.GetNotExpiredImageScans(It.Is <string[]>(tags => tags.Length == UniqueImageTagCount)));
            dbMock.Verify(i => i.SaveInProgressImageScan(It.IsAny <ImageScanResultWithCVEs>()), Times.Exactly(UniqueImageTagCount));
            queueMock.Verify(i => i.EnqueueImageScanRequest(It.IsAny <ImageScanResultWithCVEs>()), Times.Exactly(UniqueImageTagCount));

            dbMock.Verify(i => i.SaveAuditResult(It.Is <Audit>(a => VerifyHappyPathAudit(a, container))));
        }
        public async Task ProcessAuditHappyPath()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser = new ConfigurationParser("config.sample.yaml");

            var checksCache = new ChecksCache(parser, context, new MemoryCache(new MemoryCacheOptions()));

            var blobsMock = new Mock <IBlobStorageProcessor>(MockBehavior.Strict);
            var dbMock    = new Mock <IJosekiDatabase>();

            var ownershipCache = new OwnershipCache(context, new MemoryCache(new MemoryCacheOptions()));
            var postProcessor  = new Mock <ExtractOwnershipProcessor>(context, ownershipCache);
            var processor      = new AzskAuditProcessor(blobsMock.Object, dbMock.Object, checksCache, postProcessor.Object);

            var container = new ScannerContainer(Path.Combine("audits", "samples", "azsk"))
            {
                Metadata = new ScannerMetadata
                {
                    Type = ScannerType.Azsk,
                    Id   = Guid.NewGuid().ToString(),
                },
            };
            var audit = new AuditBlob {
                Name = "meta.json", ParentContainer = container
            };

            blobsMock
            .Setup(i => i.GetUnprocessedAudits(container))
            .ReturnsAsync(new[] { audit })
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/{audit.Name}"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/{audit.Name}"))
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/resources.json"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/resources.json"))
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/subscription.json"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/subscription.json"))
            .Verifiable();
            blobsMock
            .Setup(i => i.MarkAsProcessed(audit))
            .Returns(Task.CompletedTask)
            .Verifiable();

            // Act & Assert
            await processor.Process(container, CancellationToken.None);

            blobsMock.Verify();
            dbMock.Verify(i => i.SaveAuditResult(It.Is <Audit>(a => VerifyHappyPathAudit(a, container))));
        }
Example #21
0
        public async Task InvalidComponentId_ShouldThrowException()
        {
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var ownershipCache = new OwnershipCache(context, new MemoryCache(new MemoryCacheOptions()));

            const string invalidId_missingSlashPrefix = "subscription/0000-000-000-0000/";

            var owner1 = await ownershipCache.GetOwner(invalidId_missingSlashPrefix);

            owner1.Should().Be(string.Empty);
        }
Example #22
0
        public async Task EmptyComponentId_ShouldThrowException()
        {
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var ownershipCache = new OwnershipCache(context, new MemoryCache(new MemoryCacheOptions()));

            string emptyComponentId = string.Empty;

            var owner1 = await ownershipCache.GetOwner(emptyComponentId);

            owner1.Should().Be(string.Empty);
        }
        public async Task SaveImageScanResultCouldSaveNewEntity()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser = new ConfigurationParser("config.sample.yaml");
            var db     = new MssqlJosekiDatabase(context, parser);
            var cves   = new List <ImageScanToCve>
            {
                new ImageScanToCve {
                    InternalCveId = 1, Target = Guid.NewGuid().ToString(), UsedPackage = Guid.NewGuid().ToString(), UsedPackageVersion = Guid.NewGuid().ToString()
                },
                new ImageScanToCve {
                    InternalCveId = 2, Target = Guid.NewGuid().ToString(), UsedPackage = Guid.NewGuid().ToString(), UsedPackageVersion = Guid.NewGuid().ToString()
                },
                new ImageScanToCve {
                    InternalCveId = 3, Target = Guid.NewGuid().ToString(), UsedPackage = Guid.NewGuid().ToString(), UsedPackageVersion = Guid.NewGuid().ToString()
                },
            };
            var scan = new ImageScanResultWithCVEs
            {
                Date        = DateTime.UtcNow,
                Id          = Guid.NewGuid().ToString(),
                Description = Guid.NewGuid().ToString(),
                ImageTag    = Guid.NewGuid().ToString(),
                Status      = ImageScanStatus.Succeeded,
                FoundCVEs   = cves,
            };

            // Act & Assert
            context.ImageScanResult.Should().HaveCount(0);
            context.ImageScanResultToCve.Should().HaveCount(0);

            await db.SaveImageScanResult(scan);

            context.ImageScanResult.Should().HaveCount(1);
            context.ImageScanResultToCve.Should().HaveCount(cves.Count);

            var actual = await context.ImageScanResult.FirstAsync();

            actual.Date.Should().Be(scan.Date);
            actual.ExternalId.Should().Be(scan.Id);
            actual.Description.Should().Be(scan.Description);
            actual.ImageTag.Should().Be(scan.ImageTag);
            actual.Status.Should().Be(joseki.db.entities.ImageScanStatus.Succeeded);

            foreach (var actualCve in await context.ImageScanResultToCve.ToArrayAsync())
            {
                var expectedCve = cves.First(i => i.InternalCveId == actualCve.CveId);
                actualCve.Target.Should().Be(expectedCve.Target);
                actualCve.UsedPackage.Should().Be(expectedCve.UsedPackage);
                actualCve.UsedPackageVersion.Should().Be(expectedCve.UsedPackageVersion);
            }
        }
Example #24
0
        public async Task ExpiredThresholdCausesRecordUpdate()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser   = new ConfigurationParser("config.sample.yaml");
            var cveCache = new CveCache(parser, context, new MemoryCache(new MemoryCacheOptions()));

            var id             = this.GetCveId();
            var now            = DateTime.UtcNow;
            var expirationDate = now.AddDays(-(parser.Get().Cache.CveTtl + 1));
            var oldCve         = new CveEntity
            {
                CveId       = id,
                Severity    = joseki.db.entities.CveSeverity.Medium,
                PackageName = Guid.NewGuid().ToString(),
                Title       = Guid.NewGuid().ToString(),
                Description = Guid.NewGuid().ToString(),
                Remediation = Guid.NewGuid().ToString(),
                References  = Guid.NewGuid().ToString(),
                DateUpdated = expirationDate,
                DateCreated = expirationDate,
            };

            // this is the hack -_-
            // Use sync version, because it does not update DateUpdated & DateCreated
            context.Cve.Add(oldCve);
            context.SaveChanges();

            var newCve = new CVE
            {
                Id          = id,
                Description = Guid.NewGuid().ToString(),
                Remediation = Guid.NewGuid().ToString(),
                Severity    = CveSeverity.High,
                PackageName = Guid.NewGuid().ToString(),
                Title       = Guid.NewGuid().ToString(),
                References  = Guid.NewGuid().ToString(),
            };

            // Act & Assert
            context.Cve.Count().Should().Be(1, "context should have the only one record before GetOrAddItem");
            await cveCache.GetOrAddItem(id, () => newCve);

            var actualEntity = await context.Cve.FirstAsync(i => i.CveId == id);

            actualEntity.Description.Should().Be(newCve.Description);
            actualEntity.Remediation.Should().Be(newCve.Remediation);
            actualEntity.PackageName.Should().Be(newCve.PackageName);
            actualEntity.Title.Should().Be(newCve.Title);
            actualEntity.References.Should().Be(newCve.References);
            actualEntity.Severity.Should().Be(joseki.db.entities.CveSeverity.High);
            actualEntity.DateUpdated.Should().BeOnOrAfter(now);
        }
        public async Task GetAuditedComponentsWithHistoryReturnsEmptyArrayIfNoAudits()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();

            var parser = new ConfigurationParser("config.sample.yaml");
            var db     = new MssqlJosekiDatabase(context, parser);

            // Act & Assert
            var audits = await db.GetAuditedComponentsWithHistory(DateTime.UtcNow);

            audits.Should().BeEmpty();
        }
        private async Task <(GetKnowledgebaseItemsHandler, string)> getUniqueHandlerAsync()
        {
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var path = Path.Combine(BaseTestPath, Guid.NewGuid().ToString());

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            var handler = new GetKnowledgebaseItemsHandler(context, path);

            return(handler, path);
        }
        public async Task QueryComponentHistoryThrowsExceptionIfNoAudits()
        {
            // Arrange
            var componentId = Guid.NewGuid().ToString();

            await using var context = JosekiTestsDb.CreateUniqueContext();
            var cacheMock = new Mock <IInfrastructureScoreCache>();
            var handler   = new GetInfrastructureHistoryHandler(context, cacheMock.Object);

            // Act & Assert
            await handler
            .Invoking(h => h.GetHistory(componentId))
            .Should()
            .ThrowAsync <ComponentNotFoundException>();
        }
        public async Task ProcessScanResultWithoutCVEs()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser   = new ConfigurationParser("config.sample.yaml");
            var cveCache = new CveCache(parser, context, new MemoryCache(new MemoryCacheOptions()));

            var blobsMock = new Mock <IBlobStorageProcessor>(MockBehavior.Strict);
            var dbMock    = new Mock <IJosekiDatabase>();

            var processor = new TrivyAuditProcessor(blobsMock.Object, dbMock.Object, cveCache);

            var container = new ScannerContainer(Path.Combine("audits", "samples", "trivy"))
            {
                Metadata = new ScannerMetadata
                {
                    Type = ScannerType.Trivy,
                    Id   = Guid.NewGuid().ToString(),
                },
            };
            var audit = new AuditBlob {
                Name = "meta_no_cve.json", ParentContainer = container
            };

            blobsMock
            .Setup(i => i.GetUnprocessedAudits(container))
            .ReturnsAsync(new[] { audit })
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/{audit.Name}"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/{audit.Name}"))
            .Verifiable();
            blobsMock
            .Setup(i => i.DownloadFile($"{container.Name}/result_no_cves.json"))
            .ReturnsAsync(File.OpenRead($"{container.Name}/result_no_cves.json"))
            .Verifiable();
            blobsMock
            .Setup(i => i.MarkAsProcessed(audit))
            .Returns(Task.CompletedTask)
            .Verifiable();

            // Act & Assert
            await processor.Process(container, CancellationToken.None);

            blobsMock.Verify();

            dbMock.Verify(i => i.SaveImageScanResult(It.Is <ImageScanResultWithCVEs>(a => VerifyNoCveScan(a))));
        }
        public async Task ExpiredThresholdCausesAzskRecordUpdate()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser      = new ConfigurationParser("config.sample.yaml");
            var checksCache = new ChecksCache(parser, context, new MemoryCache(new MemoryCacheOptions()));

            var id             = $"azsk.{Guid.NewGuid().ToString()}";
            var now            = DateTime.UtcNow;
            var expirationDate = now.AddDays(-(parser.Get().Cache.AzureCheckTtl + 1));
            var oldCheck       = new CheckEntity
            {
                CheckId     = id,
                Category    = Guid.NewGuid().ToString(),
                Description = Guid.NewGuid().ToString(),
                Severity    = joseki.db.entities.CheckSeverity.Medium,
                DateUpdated = expirationDate,
                DateCreated = expirationDate,
            };

            // this is the hack -_-
            // Use sync version, because it does not update DateUpdated & DateCreated
            context.Check.Add(oldCheck);
            context.SaveChanges();

            var newCheck = new Check
            {
                Id          = id,
                Category    = Guid.NewGuid().ToString(),
                Description = Guid.NewGuid().ToString(),
                Remediation = Guid.NewGuid().ToString(),
                Severity    = CheckSeverity.High,
            };

            // Act & Assert
            context.Check.Count().Should().Be(1, "context should have the only one record before GetOrAddItem");
            await checksCache.GetOrAddItem(id, () => newCheck);

            var actualEntity = await context.Check.FirstAsync(i => i.CheckId == id);

            actualEntity.Category.Should().Be(newCheck.Category);
            actualEntity.Description.Should().Be(newCheck.Description);
            actualEntity.Remediation.Should().Be(newCheck.Remediation);
            actualEntity.Severity.Should().Be(joseki.db.entities.CheckSeverity.High);
            actualEntity.DateUpdated.Should().BeOnOrAfter(now);
        }
Example #30
0
        public async Task GetNotExistingItemAddOneRecordToDb()
        {
            // Arrange
            await using var context = JosekiTestsDb.CreateUniqueContext();
            var parser   = new ConfigurationParser("config.sample.yaml");
            var cveCache = new CveCache(parser, context, new MemoryCache(new MemoryCacheOptions()));

            var id  = this.GetCveId();
            var cve = new CVE {
                Id = id, Description = Guid.NewGuid().ToString(),
            };

            // Act & Assert
            context.Cve.Count().Should().Be(0, "context should be empty before GetOrAddItem");
            await cveCache.GetOrAddItem(id, () => cve);

            context.Cve.Count().Should().Be(1, "context should have a single value after GetOrAddItem");
        }