Files
git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Reachability.Tests/IacBoundaryExtractorTests.cs
2026-01-06 19:07:48 +02:00

989 lines
30 KiB
C#

// -----------------------------------------------------------------------------
// IacBoundaryExtractorTests.cs
// Sprint: SPRINT_3800_0002_0004_boundary_iac
// Description: Unit tests for IacBoundaryExtractor.
// -----------------------------------------------------------------------------
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Scanner.Reachability.Boundary;
using StellaOps.Scanner.Reachability.Gates;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Scanner.Reachability.Tests;
public class IacBoundaryExtractorTests
{
private readonly IacBoundaryExtractor _extractor;
public IacBoundaryExtractorTests()
{
_extractor = new IacBoundaryExtractor(
NullLogger<IacBoundaryExtractor>.Instance);
}
#region Priority and CanHandle
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Priority_Returns150_BetweenBaseAndK8s()
{
Assert.Equal(150, _extractor.Priority);
}
[Trait("Category", TestCategories.Unit)]
[Theory]
[InlineData("terraform", true)]
[InlineData("Terraform", true)]
[InlineData("cloudformation", true)]
[InlineData("cfn", true)]
[InlineData("pulumi", true)]
[InlineData("helm", true)]
[InlineData("iac", true)]
[InlineData("k8s", false)]
[InlineData("static", false)]
[InlineData("kong", false)]
public void CanHandle_WithSource_ReturnsExpected(string source, bool expected)
{
var context = BoundaryExtractionContext.CreateEmpty() with { Source = source };
Assert.Equal(expected, _extractor.CanHandle(context));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void CanHandle_WithTerraformAnnotations_ReturnsTrue()
{
var context = BoundaryExtractionContext.CreateEmpty() with
{
Annotations = new Dictionary<string, string>
{
["terraform.resource.aws_security_group"] = "sg-123"
}
};
Assert.True(_extractor.CanHandle(context));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void CanHandle_WithCloudFormationAnnotations_ReturnsTrue()
{
var context = BoundaryExtractionContext.CreateEmpty() with
{
Annotations = new Dictionary<string, string>
{
["cloudformation.AWS::EC2::SecurityGroup"] = "sg-123"
}
};
Assert.True(_extractor.CanHandle(context));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void CanHandle_WithHelmAnnotations_ReturnsTrue()
{
var context = BoundaryExtractionContext.CreateEmpty() with
{
Annotations = new Dictionary<string, string>
{
["helm.values.ingress.enabled"] = "true"
}
};
Assert.True(_extractor.CanHandle(context));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void CanHandle_WithEmptyAnnotations_ReturnsFalse()
{
var context = BoundaryExtractionContext.CreateEmpty();
Assert.False(_extractor.CanHandle(context));
}
#endregion
#region IaC Type Detection
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithTerraformSource_ReturnsTerraformIacSource()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal("iac:terraform", result.Source);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithCloudFormationSource_ReturnsCloudFormationIacSource()
{
var root = new RichGraphRoot("root-1", "cloudformation", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "cloudformation"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal("iac:cloudformation", result.Source);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithCfnSource_ReturnsCloudFormationIacSource()
{
var root = new RichGraphRoot("root-1", "cfn", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "cfn"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal("iac:cloudformation", result.Source);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithPulumiSource_ReturnsPulumiIacSource()
{
var root = new RichGraphRoot("root-1", "pulumi", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "pulumi"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal("iac:pulumi", result.Source);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithHelmSource_ReturnsHelmIacSource()
{
var root = new RichGraphRoot("root-1", "helm", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "helm"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal("iac:helm", result.Source);
}
#endregion
#region Terraform Exposure Detection
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithTerraformPublicSecurityGroup_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_security_group.ingress.cidr"] = "0.0.0.0/0"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithTerraformInternetFacingAlb_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_lb.internal"] = "false"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithTerraformPublicIp_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_eip.public_ip"] = "true"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithTerraformPrivateResource_ReturnsInternalExposure()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_vpc.private_subnets"] = "10.0.0.0/24"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("internal", result.Exposure.Level);
Assert.False(result.Exposure.InternetFacing);
}
#endregion
#region CloudFormation Exposure Detection
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithCloudFormationPublicSecurityGroup_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "cloudformation", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "cloudformation",
Annotations = new Dictionary<string, string>
{
["cloudformation.AWS::EC2::SecurityGroup.Ingress"] = "0.0.0.0/0"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithCloudFormationInternetFacingElb_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "cloudformation", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "cloudformation",
Annotations = new Dictionary<string, string>
{
["cloudformation.AWS::ElasticLoadBalancingV2::LoadBalancer.Scheme"] = "internet-facing"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithCloudFormationApiGateway_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "cloudformation", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "cloudformation",
Annotations = new Dictionary<string, string>
{
["cloudformation.AWS::ApiGateway::RestApi"] = "my-api"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
#endregion
#region Helm Exposure Detection
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithHelmIngressEnabled_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "helm", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "helm",
Annotations = new Dictionary<string, string>
{
["helm.values.ingress.enabled"] = "true"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithHelmLoadBalancerService_ReturnsPublicExposure()
{
var root = new RichGraphRoot("root-1", "helm", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "helm",
Annotations = new Dictionary<string, string>
{
["helm.values.service.type"] = "LoadBalancer"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("public", result.Exposure.Level);
Assert.True(result.Exposure.InternetFacing);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithHelmClusterIpService_ReturnsPrivateExposure()
{
var root = new RichGraphRoot("root-1", "helm", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "helm",
Annotations = new Dictionary<string, string>
{
["helm.values.service.type"] = "ClusterIP"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.Equal("private", result.Exposure.Level);
Assert.False(result.Exposure.InternetFacing);
}
#endregion
#region Auth Detection
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithIamAuth_ReturnsIamAuthType()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_iam_policy.auth"] = "enabled"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Auth);
Assert.True(result.Auth.Required);
Assert.Equal("iam", result.Auth.Type);
Assert.Equal("aws-iam", result.Auth.Provider);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithCognitoAuth_ReturnsOAuth2AuthType()
{
var root = new RichGraphRoot("root-1", "cloudformation", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "cloudformation",
Annotations = new Dictionary<string, string>
{
["cloudformation.AWS::Cognito::UserPool"] = "my-pool"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Auth);
Assert.True(result.Auth.Required);
Assert.Equal("oauth2", result.Auth.Type);
Assert.Equal("cognito", result.Auth.Provider);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithAzureAdAuth_ReturnsOAuth2AuthType()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.azurerm_azure_ad_application"] = "my-app"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Auth);
Assert.True(result.Auth.Required);
Assert.Equal("oauth2", result.Auth.Type);
Assert.Equal("azure-ad", result.Auth.Provider);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithMtlsAuth_ReturnsMtlsAuthType()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_acm_certificate.mtls"] = "enabled"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Auth);
Assert.True(result.Auth.Required);
Assert.Equal("mtls", result.Auth.Type);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithNoAuth_ReturnsNullAuth()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Null(result.Auth);
}
#endregion
#region Controls Detection
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithSecurityGroup_ReturnsSecurityGroupControl()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_security_group.main"] = "sg-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Contains(result.Controls, c => c.Type == "security_group");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithWaf_ReturnsWafControl()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_wafv2_web_acl.main"] = "waf-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Contains(result.Controls, c => c.Type == "waf");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithVpc_ReturnsNetworkIsolationControl()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_vpc.main"] = "vpc-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Contains(result.Controls, c => c.Type == "network_isolation");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithNacl_ReturnsNetworkAclControl()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_network_acl.main"] = "nacl-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Contains(result.Controls, c => c.Type == "network_acl");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithDdosProtection_ReturnsDdosControl()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_shield_protection.main"] = "shield-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Contains(result.Controls, c => c.Type == "ddos_protection");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithTls_ReturnsEncryptionControl()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_acm_certificate.tls"] = "cert-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Contains(result.Controls, c => c.Type == "encryption_in_transit");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithPrivateEndpoint_ReturnsPrivateEndpointControl()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_vpc_endpoint.main"] = "vpce-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Contains(result.Controls, c => c.Type == "private_endpoint");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithMultipleControls_ReturnsAllControls()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_security_group.main"] = "sg-123",
["terraform.aws_wafv2_web_acl.main"] = "waf-123",
["terraform.aws_vpc.main"] = "vpc-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Controls);
Assert.Equal(3, result.Controls.Count);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithNoControls_ReturnsNullControls()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Null(result.Controls);
}
#endregion
#region Surface Detection
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithHelmIngressPath_ReturnsSurfaceWithPath()
{
var root = new RichGraphRoot("root-1", "helm", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "helm",
Annotations = new Dictionary<string, string>
{
["helm.values.ingress.path"] = "/api/v1"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Surface);
Assert.Equal("/api/v1", result.Surface.Path);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithHelmIngressHost_ReturnsSurfaceWithHost()
{
var root = new RichGraphRoot("root-1", "helm", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "helm",
Annotations = new Dictionary<string, string>
{
["helm.values.ingress.host"] = "api.example.com"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Surface);
Assert.Equal("api.example.com", result.Surface.Host);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_DefaultSurfaceType_ReturnsInfrastructure()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Surface);
Assert.Equal("infrastructure", result.Surface.Type);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_DefaultProtocol_ReturnsHttps()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Surface);
Assert.Equal("https", result.Surface.Protocol);
}
#endregion
#region Confidence and Metadata
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_BaseConfidence_Returns0Point6()
{
var root = new RichGraphRoot("root-1", "iac", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "iac"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal(0.6, result.Confidence, precision: 2);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithKnownIacType_IncreasesConfidence()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal(0.7, result.Confidence, precision: 2);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithSecurityResources_IncreasesConfidence()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_security_group.main"] = "sg-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal(0.8, result.Confidence, precision: 2);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_MaxConfidence_CapsAt0Point85()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_security_group.main"] = "sg-123",
["terraform.aws_wafv2_web_acl.main"] = "waf-123",
["terraform.aws_vpc.main"] = "vpc-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.True(result.Confidence <= 0.85);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_ReturnsNetworkKind()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal("network", result.Kind);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_BuildsEvidenceRef_WithIacType()
{
var root = new RichGraphRoot("root-123", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Namespace = "production",
EnvironmentId = "env-456"
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.Equal("iac/terraform/production/env-456/root-123", result.EvidenceRef);
}
#endregion
#region ExtractAsync
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ExtractAsync_ReturnsSameResultAsExtract()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_security_group.main"] = "sg-123"
}
};
var syncResult = _extractor.Extract(root, null, context);
var asyncResult = await _extractor.ExtractAsync(root, null, context);
Assert.NotNull(syncResult);
Assert.NotNull(asyncResult);
Assert.Equal(syncResult.Kind, asyncResult.Kind);
Assert.Equal(syncResult.Source, asyncResult.Source);
Assert.Equal(syncResult.Confidence, asyncResult.Confidence);
}
#endregion
#region Edge Cases
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithNullRoot_ThrowsArgumentNullException()
{
var context = BoundaryExtractionContext.CreateEmpty() with { Source = "terraform" };
Assert.Throws<ArgumentNullException>(() => _extractor.Extract(null!, null, context));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WhenCannotHandle_ReturnsNull()
{
var root = new RichGraphRoot("root-1", "k8s", null);
var context = BoundaryExtractionContext.CreateEmpty() with { Source = "k8s" };
var result = _extractor.Extract(root, null, context);
Assert.Null(result);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Extract_WithLoadBalancer_SetsBehindProxyTrue()
{
var root = new RichGraphRoot("root-1", "terraform", null);
var context = BoundaryExtractionContext.CreateEmpty() with
{
Source = "terraform",
Annotations = new Dictionary<string, string>
{
["terraform.aws_alb.main"] = "alb-123"
}
};
var result = _extractor.Extract(root, null, context);
Assert.NotNull(result);
Assert.NotNull(result.Exposure);
Assert.True(result.Exposure.BehindProxy);
}
#endregion
}