| 1 | using System.Net.Http.Headers; |
| 2 | using System.Net.Http.Json; |
| 3 | |
| 4 | namespace AgentForge.Tests; |
| 5 | |
| 6 | [CollectionDefinition("ForgeEnvironment", DisableParallelization = true)] |
| 7 | public sealed class ForgeEnvironmentCollection; |
| 8 | |
| 9 | [Collection("ForgeEnvironment")] |
| 10 | public sealed class ForgePublicSecurityTests |
| 11 | { |
| 12 | [Fact] |
| 13 | public async Task Git_push_rejects_anonymous_when_require_auth() |
| 14 | { |
| 15 | Environment.SetEnvironmentVariable("FORGE_REQUIRE_AUTH", "true"); |
| 16 | Environment.SetEnvironmentVariable("FORGE_GIT_HOOK_SECRET", "hook-secret"); |
| 17 | try |
| 18 | { |
| 19 | using var factory = new ForgeWebApplicationFactory(); |
| 20 | using var client = factory.CreateClient(); |
| 21 | |
| 22 | var response = await client.PostAsJsonAsync("/api/v1/git/push", new |
| 23 | { |
| 24 | repo = "secured-push", |
| 25 | branch = "main", |
| 26 | commit = "abc", |
| 27 | }); |
| 28 | |
| 29 | Assert.Equal(System.Net.HttpStatusCode.Unauthorized, response.StatusCode); |
| 30 | } |
| 31 | finally |
| 32 | { |
| 33 | Environment.SetEnvironmentVariable("FORGE_REQUIRE_AUTH", null); |
| 34 | Environment.SetEnvironmentVariable("FORGE_GIT_HOOK_SECRET", null); |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | [Fact] |
| 39 | public async Task Git_push_returns_503_when_require_auth_and_hook_secret_missing() |
| 40 | { |
| 41 | Environment.SetEnvironmentVariable("FORGE_REQUIRE_AUTH", "true"); |
| 42 | Environment.SetEnvironmentVariable("FORGE_GIT_HOOK_SECRET", null); |
| 43 | try |
| 44 | { |
| 45 | using var factory = new ForgeWebApplicationFactory(); |
| 46 | using var client = factory.CreateClient(); |
| 47 | |
| 48 | var response = await client.PostAsJsonAsync("/api/v1/git/push", new |
| 49 | { |
| 50 | repo = "any", |
| 51 | branch = "main", |
| 52 | commit = "abc", |
| 53 | }); |
| 54 | |
| 55 | Assert.Equal(System.Net.HttpStatusCode.ServiceUnavailable, response.StatusCode); |
| 56 | } |
| 57 | finally |
| 58 | { |
| 59 | Environment.SetEnvironmentVariable("FORGE_REQUIRE_AUTH", null); |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | [Fact] |
| 64 | public async Task Plugin_status_requires_bootstrap_when_require_auth() |
| 65 | { |
| 66 | Environment.SetEnvironmentVariable("FORGE_REQUIRE_AUTH", "true"); |
| 67 | Environment.SetEnvironmentVariable("FORGE_BOOTSTRAP_TOKEN", "bootstrap-security"); |
| 68 | try |
| 69 | { |
| 70 | using var factory = new ForgeWebApplicationFactory(); |
| 71 | using var client = factory.CreateClient(); |
| 72 | |
| 73 | var anonymous = await client.GetAsync("/api/v1/admin/plugins/status"); |
| 74 | Assert.Equal(System.Net.HttpStatusCode.Unauthorized, anonymous.StatusCode); |
| 75 | |
| 76 | using var authorized = new HttpRequestMessage(HttpMethod.Get, "/api/v1/admin/plugins/status"); |
| 77 | authorized.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "bootstrap-security"); |
| 78 | var ok = await client.SendAsync(authorized); |
| 79 | ok.EnsureSuccessStatusCode(); |
| 80 | } |
| 81 | finally |
| 82 | { |
| 83 | Environment.SetEnvironmentVariable("FORGE_REQUIRE_AUTH", null); |
| 84 | Environment.SetEnvironmentVariable("FORGE_BOOTSTRAP_TOKEN", null); |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | |