feat: add security sink detection patterns for JavaScript/TypeScript
- Introduced `sink-detect.js` with various security sink detection patterns categorized by type (e.g., command injection, SQL injection, file operations). - Implemented functions to build a lookup map for fast sink detection and to match sink calls against known patterns. - Added `package-lock.json` for dependency management.
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// PostgresOnlyStartupTests.cs
|
||||
// Sprint: SPRINT_5100_0001_0001_mongodb_cli_cleanup_consolidation
|
||||
// Task: T1.13 - PostgreSQL-only Platform Startup Test
|
||||
// Description: Validates platform can start with PostgreSQL-only infrastructure.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using StellaOps.Infrastructure.Postgres.Testing;
|
||||
using Testcontainers.PostgreSql;
|
||||
|
||||
namespace StellaOps.Integration.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests validating PostgreSQL-only platform startup.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// T1.13-AC1: Platform starts successfully with PostgreSQL only
|
||||
/// T1.13-AC2: All services connect to PostgreSQL correctly
|
||||
/// T1.13-AC3: Schema migrations run successfully
|
||||
/// T1.13-AC4: No MongoDB connection attempts in logs
|
||||
/// </remarks>
|
||||
[Trait("Category", "Integration")]
|
||||
[Trait("Category", "Platform")]
|
||||
[Trait("Category", "PostgresOnly")]
|
||||
public class PostgresOnlyStartupTests : IAsyncLifetime
|
||||
{
|
||||
private PostgreSqlContainer? _container;
|
||||
private string? _connectionString;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
_container = new PostgreSqlBuilder()
|
||||
.WithImage("postgres:16-alpine")
|
||||
.Build();
|
||||
|
||||
await _container.StartAsync();
|
||||
_connectionString = _container.GetConnectionString();
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
if (_container != null)
|
||||
{
|
||||
await _container.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
#region T1.13-AC1: Platform starts successfully with PostgreSQL only
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC1.1: PostgreSQL container starts and accepts connections")]
|
||||
public async Task PostgresContainer_StartsAndAcceptsConnections()
|
||||
{
|
||||
// Arrange & Act - already done in InitializeAsync
|
||||
|
||||
// Assert
|
||||
_connectionString.Should().NotBeNullOrEmpty();
|
||||
_container!.State.Should().Be(DotNet.Testcontainers.Containers.TestcontainersStates.Running);
|
||||
|
||||
// Verify connection works
|
||||
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
|
||||
await connection.OpenAsync();
|
||||
connection.State.Should().Be(System.Data.ConnectionState.Open);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC1.2: PostgreSQL connection string contains no MongoDB references")]
|
||||
public void ConnectionString_ContainsNoMongoDbReferences()
|
||||
{
|
||||
// Assert
|
||||
_connectionString.Should().NotContainAny("mongo", "mongodb", "27017");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region T1.13-AC2: Services connect to PostgreSQL correctly
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC2.1: Can create and verify database schema")]
|
||||
public async Task Database_CanCreateAndVerifySchema()
|
||||
{
|
||||
// Arrange
|
||||
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
|
||||
await connection.OpenAsync();
|
||||
|
||||
// Act - Create a test schema
|
||||
using var createCmd = connection.CreateCommand();
|
||||
createCmd.CommandText = "CREATE SCHEMA IF NOT EXISTS test_platform";
|
||||
await createCmd.ExecuteNonQueryAsync();
|
||||
|
||||
// Assert - Verify schema exists
|
||||
using var verifyCmd = connection.CreateCommand();
|
||||
verifyCmd.CommandText = @"
|
||||
SELECT schema_name
|
||||
FROM information_schema.schemata
|
||||
WHERE schema_name = 'test_platform'";
|
||||
var result = await verifyCmd.ExecuteScalarAsync();
|
||||
result.Should().Be("test_platform");
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC2.2: Can perform basic CRUD operations")]
|
||||
public async Task Database_CanPerformCrudOperations()
|
||||
{
|
||||
// Arrange
|
||||
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
|
||||
await connection.OpenAsync();
|
||||
|
||||
// Create test table
|
||||
using var createCmd = connection.CreateCommand();
|
||||
createCmd.CommandText = @"
|
||||
CREATE TABLE IF NOT EXISTS test_crud (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
)";
|
||||
await createCmd.ExecuteNonQueryAsync();
|
||||
|
||||
// Act - Insert
|
||||
using var insertCmd = connection.CreateCommand();
|
||||
insertCmd.CommandText = "INSERT INTO test_crud (name) VALUES ('test-record') RETURNING id";
|
||||
var insertedId = await insertCmd.ExecuteScalarAsync();
|
||||
insertedId.Should().NotBeNull();
|
||||
|
||||
// Act - Select
|
||||
using var selectCmd = connection.CreateCommand();
|
||||
selectCmd.CommandText = "SELECT name FROM test_crud WHERE id = @id";
|
||||
selectCmd.Parameters.AddWithValue("id", insertedId!);
|
||||
var name = await selectCmd.ExecuteScalarAsync();
|
||||
name.Should().Be("test-record");
|
||||
|
||||
// Act - Update
|
||||
using var updateCmd = connection.CreateCommand();
|
||||
updateCmd.CommandText = "UPDATE test_crud SET name = 'updated-record' WHERE id = @id";
|
||||
updateCmd.Parameters.AddWithValue("id", insertedId!);
|
||||
var rowsAffected = await updateCmd.ExecuteNonQueryAsync();
|
||||
rowsAffected.Should().Be(1);
|
||||
|
||||
// Act - Delete
|
||||
using var deleteCmd = connection.CreateCommand();
|
||||
deleteCmd.CommandText = "DELETE FROM test_crud WHERE id = @id";
|
||||
deleteCmd.Parameters.AddWithValue("id", insertedId!);
|
||||
rowsAffected = await deleteCmd.ExecuteNonQueryAsync();
|
||||
rowsAffected.Should().Be(1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region T1.13-AC3: Schema migrations run successfully
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC3.1: Can run DDL migrations")]
|
||||
public async Task Database_CanRunDdlMigrations()
|
||||
{
|
||||
// Arrange
|
||||
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
|
||||
await connection.OpenAsync();
|
||||
|
||||
// Act - Run a migration-like DDL script
|
||||
var migrationScript = @"
|
||||
-- V1: Create migrations tracking table
|
||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
version VARCHAR(50) PRIMARY KEY,
|
||||
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
checksum VARCHAR(64) NOT NULL
|
||||
);
|
||||
|
||||
-- V2: Create sample domain table
|
||||
CREATE TABLE IF NOT EXISTS scan_results (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
image_ref TEXT NOT NULL,
|
||||
findings_count INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Record migration
|
||||
INSERT INTO schema_migrations (version, checksum)
|
||||
VALUES ('V2_create_scan_results', 'abc123')
|
||||
ON CONFLICT (version) DO NOTHING;
|
||||
";
|
||||
|
||||
using var migrateCmd = connection.CreateCommand();
|
||||
migrateCmd.CommandText = migrationScript;
|
||||
await migrateCmd.ExecuteNonQueryAsync();
|
||||
|
||||
// Assert - Verify migration recorded
|
||||
using var verifyCmd = connection.CreateCommand();
|
||||
verifyCmd.CommandText = "SELECT COUNT(*) FROM schema_migrations WHERE version = 'V2_create_scan_results'";
|
||||
var count = await verifyCmd.ExecuteScalarAsync();
|
||||
Convert.ToInt32(count).Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC3.2: PostgreSQL extensions can be created")]
|
||||
public async Task Database_CanCreateExtensions()
|
||||
{
|
||||
// Arrange
|
||||
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
|
||||
await connection.OpenAsync();
|
||||
|
||||
// Act - Create common extensions used by StellaOps
|
||||
using var extCmd = connection.CreateCommand();
|
||||
extCmd.CommandText = "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"";
|
||||
await extCmd.ExecuteNonQueryAsync();
|
||||
|
||||
// Assert - Verify extension exists
|
||||
using var verifyCmd = connection.CreateCommand();
|
||||
verifyCmd.CommandText = "SELECT COUNT(*) FROM pg_extension WHERE extname = 'uuid-ossp'";
|
||||
var count = await verifyCmd.ExecuteScalarAsync();
|
||||
Convert.ToInt32(count).Should().Be(1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region T1.13-AC4: No MongoDB connection attempts
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC4.1: Environment variables contain no MongoDB references")]
|
||||
public void EnvironmentVariables_ContainNoMongoDbReferences()
|
||||
{
|
||||
// Arrange - Get all environment variables
|
||||
var envVars = Environment.GetEnvironmentVariables();
|
||||
|
||||
// Act & Assert
|
||||
foreach (string key in envVars.Keys)
|
||||
{
|
||||
var value = envVars[key]?.ToString() ?? "";
|
||||
|
||||
// Skip if this is our test connection string
|
||||
if (key.Contains("POSTGRES", StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
key.Should().NotContainEquivalentOf("mongo",
|
||||
$"Environment variable key '{key}' should not reference MongoDB");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T1.13-AC4.2: PostgreSQL-only configuration is valid")]
|
||||
public void Configuration_IsPostgresOnly()
|
||||
{
|
||||
// This test documents the expected configuration pattern
|
||||
var expectedConfig = new Dictionary<string, string>
|
||||
{
|
||||
["STELLAOPS_STORAGE_DRIVER"] = "postgres",
|
||||
["STELLAOPS_CACHE_DRIVER"] = "valkey", // or "redis" for compatibility
|
||||
};
|
||||
|
||||
// Assert - Document the expected pattern
|
||||
expectedConfig["STELLAOPS_STORAGE_DRIVER"].Should().NotBe("mongodb");
|
||||
expectedConfig["STELLAOPS_STORAGE_DRIVER"].Should().Be("postgres");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
StellaOps.Integration.Platform.csproj
|
||||
Sprint: SPRINT_5100_0001_0001_mongodb_cli_cleanup_consolidation
|
||||
Task: T1.13 - PostgreSQL-only Platform Startup Test
|
||||
Description: Integration tests for platform startup with PostgreSQL-only stack
|
||||
-->
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Testcontainers" Version="3.6.0" />
|
||||
<PackageReference Include="Testcontainers.PostgreSql" Version="3.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Infrastructure testing library -->
|
||||
<ProjectReference Include="../../../src/__Libraries/StellaOps.Infrastructure.Postgres.Testing/StellaOps.Infrastructure.Postgres.Testing.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<Using Include="FluentAssertions" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user