Skip to content

Commit

Permalink
Add healthcheck controller with loopback-only authorization filter. A…
Browse files Browse the repository at this point in the history
…dd curl install to Dockerfile.
  • Loading branch information
bitbound committed May 3, 2023
1 parent cfc4ddb commit 7b69141
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 2 deletions.
33 changes: 33 additions & 0 deletions Server/API/HealthCheckController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Remotely.Server.Auth;
using Remotely.Server.Services;
using System.Threading.Tasks;

namespace Remotely.Server.API
{
/// <summary>
/// Can only be accessed from the local machine. The sole purpose
/// is to provide a healthcheck endpoint for Docker that exercises
/// the database connection.
/// </summary>
[Route("api/[controller]")]
[ApiController]
[ServiceFilter(typeof(LocalOnlyFilter))]
public class HealthCheckController : ControllerBase
{
private readonly IDataService _dataService;

public HealthCheckController(IDataService dataService)
{
_dataService = dataService;
}

[HttpGet]
public async Task<IActionResult> Get()
{
var orgCount = await _dataService.GetOrganizationCountAsync();
return Ok($"Organization Count: {orgCount}");
}
}
}
19 changes: 19 additions & 0 deletions Server/Auth/LocalOnlyFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Net;

namespace Remotely.Server.Auth
{
public class LocalOnlyFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
if (!IPAddress.IsLoopback(remoteIp))
{
context.Result = new UnauthorizedResult();
return;
}
}
}
}
4 changes: 3 additions & 1 deletion Server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ COPY /_immense.Remotely/Server/linux-x64/Server /app
WORKDIR /app

RUN \
apt-get -y update && \
apt-get -y install curl && \
mkdir -p /remotely-data && \
sed -i 's/DataSource=Remotely.db/DataSource=\/remotely-data\/Remotely.db/' /app/appsettings.json

Expand All @@ -23,4 +25,4 @@ RUN chmod +x "/src/DockerMain.sh"
ENTRYPOINT ["/src/DockerMain.sh"]

HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost:5000/ || exit 1
CMD curl -f http://localhost:5000/api/healthcheck || exit 1
7 changes: 6 additions & 1 deletion Server/Dockerfile.local
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ COPY ./DockerMain.sh .
WORKDIR /app

RUN \
apt-get -y update && \
apt-get -y install curl && \
mkdir -p /remotely-data && \
sed -i 's/DataSource=Remotely.db/DataSource=\/remotely-data\/Remotely.db/' ./appsettings.json

VOLUME "/remotely-data"

RUN chmod +x "/src/DockerMain.sh"

ENTRYPOINT ["/src/DockerMain.sh"]
ENTRYPOINT ["/src/DockerMain.sh"]

HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost:5000/api/healthcheck || exit 1
1 change: 1 addition & 0 deletions Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
services.AddTransient<IDataService, DataService>();
services.AddSingleton<IApplicationConfig, ApplicationConfig>();
services.AddScoped<ApiAuthorizationFilter>();
services.AddScoped<LocalOnlyFilter>();
services.AddScoped<ExpiringTokenFilter>();
services.AddHostedService<DbCleanupService>();
services.AddHostedService<ScriptScheduler>();
Expand Down
8 changes: 8 additions & 0 deletions Server/Services/DataService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ public interface IDataService
Task<Organization> GetOrganizationByUserName(string userName);

int GetOrganizationCount();
Task<int> GetOrganizationCountAsync();

string GetOrganizationNameById(string organizationID);

Expand Down Expand Up @@ -1399,6 +1400,13 @@ public int GetOrganizationCount()
return dbContext.Organizations.Count();
}

public async Task<int> GetOrganizationCountAsync()
{
using var dbContext = _appDbFactory.GetContext();

return await dbContext.Organizations.CountAsync();
}

public string GetOrganizationNameById(string organizationID)
{
using var dbContext = _appDbFactory.GetContext();
Expand Down

0 comments on commit 7b69141

Please sign in to comment.