feat(api): Add authenticated Caddy management API
All checks were successful
Caddy Manager CI build / docker (push) Successful in 4m24s
All checks were successful
Caddy Manager CI build / docker (push) Successful in 4m24s
This commit is contained in:
@@ -436,6 +436,37 @@ public class CaddyServiceTests : IDisposable
|
||||
File.Exists(filePath).Should().BeTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the Caddy service refuses to save configurations whose file name escapes the configuration directory.
|
||||
/// Setup: Provides save requests with traversal segments and directory separators in the file name.
|
||||
/// Expectation: The service should reject the request and write nothing outside the configuration directory, so an untrusted caller such as the HTTP API cannot write arbitrary files on the host.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData("../escape")]
|
||||
[InlineData("../../etc/escape")]
|
||||
[InlineData("sub/escape")]
|
||||
[InlineData("sub\\escape")]
|
||||
public void SaveCaddyConfiguration_WithFileNameEscapingConfigDir_ReturnsFailureAndWritesNothing(string fileName)
|
||||
{
|
||||
// Arrange
|
||||
var request = new CaddySaveConfigurationRequest
|
||||
{
|
||||
FileName = fileName,
|
||||
Content = TestHelper.SampleCaddyfiles.SimpleReverseProxy,
|
||||
IsNew = true
|
||||
};
|
||||
var escapedPath = Path.GetFullPath(Path.Combine(_tempConfigDir, $"{fileName}.caddy"));
|
||||
|
||||
// Act
|
||||
var result = _service.SaveCaddyConfiguration(request);
|
||||
|
||||
// Assert
|
||||
result.Success.Should().BeFalse();
|
||||
result.Message.Should().Be("The configuration file name contains invalid characters");
|
||||
File.Exists(escapedPath).Should().BeFalse();
|
||||
Directory.GetFiles(_tempConfigDir).Should().BeEmpty();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SaveCaddyGlobalConfiguration Tests
|
||||
@@ -755,6 +786,37 @@ public class CaddyServiceTests : IDisposable
|
||||
result.DeletedConfigurations.Should().BeEmpty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the Caddy service refuses to delete configurations whose file name escapes the configuration directory.
|
||||
/// Setup: Creates a file outside the configuration directory and asks the service to delete it through a traversal file name.
|
||||
/// Expectation: The service should report the name as failed and leave the outside file untouched, so an untrusted caller such as the HTTP API cannot delete arbitrary files on the host.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void DeleteCaddyConfigurations_WithFileNameEscapingConfigDir_ReportsFailureAndDeletesNothing()
|
||||
{
|
||||
// Arrange
|
||||
var outsideDir = TestHelper.CreateTempDirectory();
|
||||
try
|
||||
{
|
||||
var outsidePath = Path.Combine(outsideDir, "victim.caddy");
|
||||
File.WriteAllText(outsidePath, "content");
|
||||
var traversalName = Path.Combine("..", Path.GetFileName(outsideDir), "victim");
|
||||
|
||||
// Act
|
||||
var result = _service.DeleteCaddyConfigurations([traversalName]);
|
||||
|
||||
// Assert
|
||||
result.Success.Should().BeFalse();
|
||||
result.Message.Should().Contain(traversalName);
|
||||
result.DeletedConfigurations.Should().BeEmpty();
|
||||
File.Exists(outsidePath).Should().BeTrue();
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestHelper.CleanupDirectory(outsideDir);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetCaddyConfigurationInfo Tests
|
||||
|
||||
Reference in New Issue
Block a user