From 7b312857939aba90218586f43e2f8bb5344ae7b7 Mon Sep 17 00:00:00 2001 From: Yevhen Zavhorodnii Date: Fri, 31 May 2024 13:54:10 +0100 Subject: [PATCH] Cover push instead of pull deployment rule with tests --- ...sh_instead_of_pull_deployment_rule_test.go | 370 ++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 pkg/security/risks/builtin/push_instead_of_pull_deployment_rule_test.go diff --git a/pkg/security/risks/builtin/push_instead_of_pull_deployment_rule_test.go b/pkg/security/risks/builtin/push_instead_of_pull_deployment_rule_test.go new file mode 100644 index 00000000..30f43ca4 --- /dev/null +++ b/pkg/security/risks/builtin/push_instead_of_pull_deployment_rule_test.go @@ -0,0 +1,370 @@ +package builtin + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/threagile/threagile/pkg/security/types" +) + +func TestPushInsteadPullDeploymentRuleGenerateRisksEmptyModelNotRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + + risks, err := rule.GenerateRisks(&types.Model{}) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestPushInsteadPullDeploymentRuleGenerateRisksNoBuildPipelineNoRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Title: "Build Pipeline Technical Asset", + OutOfScope: true, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: false, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestPushInsteadPullDeploymentRuleGenerateRisksNoCommunicationWithBuildPipelineNoRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Title: "Build Pipeline Technical Asset", + OutOfScope: true, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: true, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestPushInsteadPullDeploymentRuleGenerateRisksReadOnlyCommunicationWithBuildPipelineNoRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Build Pipeline Technical Asset", + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: true, + }, + }, + }, + CommunicationLinks: []*types.CommunicationLink{ + { + TargetId: "ta2", + Readonly: true, + Usage: types.Business, + }, + }, + }, + "ta2": { + Id: "ta2", + Title: "Target Pipeline Technical Asset", + OutOfScope: false, + Usage: types.Business, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.IsDevelopmentRelevant: false, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestPushInsteadPullDeploymentRuleGenerateRisksTargetOutOfScopeWithBuildPipelineNoRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Build Pipeline Technical Asset", + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: true, + }, + }, + }, + CommunicationLinks: []*types.CommunicationLink{ + { + TargetId: "ta2", + Readonly: false, + Usage: types.Business, + }, + }, + }, + "ta2": { + Id: "ta2", + Title: "Target Pipeline Technical Asset", + OutOfScope: true, + Usage: types.Business, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.IsDevelopmentRelevant: false, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestPushInsteadPullDeploymentRuleGenerateRisksDevOpsUsageNoRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Build Pipeline Technical Asset", + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: true, + }, + }, + }, + CommunicationLinks: []*types.CommunicationLink{ + { + TargetId: "ta2", + Readonly: false, + Usage: types.DevOps, + }, + }, + }, + "ta2": { + Id: "ta2", + Title: "Target Pipeline Technical Asset", + Usage: types.DevOps, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.IsDevelopmentRelevant: false, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestPushInsteadPullDeploymentRuleGenerateRisksTargetIsDevOpsUsageNoRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Build Pipeline Technical Asset", + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: true, + }, + }, + }, + CommunicationLinks: []*types.CommunicationLink{ + { + TargetId: "ta2", + Readonly: false, + Usage: types.DevOps, + }, + }, + }, + "ta2": { + Id: "ta2", + Title: "Target Pipeline Technical Asset", + Usage: types.DevOps, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.IsDevelopmentRelevant: false, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestPushInsteadPullDeploymentRuleGenerateRisksTargetIsDevelopmentRelatedNoRisksCreated(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Build Pipeline Technical Asset", + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: true, + }, + }, + }, + CommunicationLinks: []*types.CommunicationLink{ + { + TargetId: "ta2", + Readonly: false, + Usage: types.DevOps, + }, + }, + }, + "ta2": { + Id: "ta2", + Title: "Target Pipeline Technical Asset", + Usage: types.Business, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.IsDevelopmentRelevant: true, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +type PushInsteadOfPullRuleTest struct { + confidentiality types.Confidentiality + integrity types.Criticality + availability types.Criticality + + expectedImpact types.RiskExploitationImpact +} + +func TestPushInsteadOfPullRuleGenerateRisksRiskCreated(t *testing.T) { + testCases := map[string]PushInsteadOfPullRuleTest{ + "low impact": { + confidentiality: types.Restricted, + integrity: types.Important, + availability: types.Important, + expectedImpact: types.LowImpact, + }, + "confidential medium impact": { + confidentiality: types.Confidential, + integrity: types.Important, + availability: types.Important, + expectedImpact: types.MediumImpact, + }, + "critical integrity medium impact": { + confidentiality: types.Restricted, + integrity: types.Critical, + availability: types.Important, + expectedImpact: types.MediumImpact, + }, + "critical availability medium impact": { + confidentiality: types.Restricted, + integrity: types.Important, + availability: types.Critical, + expectedImpact: types.MediumImpact, + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + rule := NewPushInsteadPullDeploymentRule() + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Build Pipeline Technical Asset", + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.BuildPipeline: true, + }, + }, + }, + CommunicationLinks: []*types.CommunicationLink{ + { + Title: "Test Communication Link", + TargetId: "ta2", + Readonly: false, + Usage: types.DevOps, + }, + }, + }, + "ta2": { + Id: "ta2", + Title: "Target Pipeline Technical Asset", + Usage: types.Business, + Technologies: types.TechnologyList{ + { + Name: "build pipeline", + Attributes: map[string]bool{ + types.IsDevelopmentRelevant: false, + }, + }, + }, + Confidentiality: testCase.confidentiality, + Integrity: testCase.integrity, + Availability: testCase.availability, + }, + }, + }) + + assert.Nil(t, err) + assert.Len(t, risks, 1) + assert.Equal(t, testCase.expectedImpact, risks[0].ExploitationImpact) + + expTitle := "Push instead of Pull Deployment at Target Pipeline Technical Asset via build pipeline asset Build Pipeline Technical Asset" + assert.Equal(t, expTitle, risks[0].Title) + }) + } +}