Skip to content

Commit b46045a

Browse files
Copilothajekj
andcommitted
Add SyncTriggerKey authentication to /api/sync endpoint
Co-authored-by: hajekj <8337913+hajekj@users.noreply.github.com> Agent-Logs-Url: https://github.com/NETWORG/github-organization-management/sessions/9cf4b695-d1a9-42f4-8a12-0d0008dbdfbf
1 parent 18d1b17 commit b46045a

3 files changed

Lines changed: 28 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ The application secrets can be also passed in as [environment variables](https:/
6969
},
7070
"ExemptUsers": [
7171
"<Case_Sensitive_List_Of_Users>"
72-
]
72+
],
73+
"SyncTriggerKey": "<secret_key_to_trigger_sync>"
7374
}
7475
```
7576

Web/Controllers/SyncController.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Web.Services;
44
using Microsoft.AspNetCore.Mvc;
55
using Octokit;
6+
using System.Security.Cryptography;
67
using System.Text;
78

89
namespace Web.Controllers
@@ -14,18 +15,38 @@ public class SyncController : Controller
1415
private readonly string _privateKeyPem;
1516
private readonly string _clientId;
1617
private readonly string _appId;
18+
private readonly string? _syncTriggerKey;
1719
private readonly MicrosoftGraphService _microsoftGraph;
1820
private readonly ILogger _logger;
1921
public SyncController(IConfiguration configuration, MicrosoftGraphService microsoftGraph, ILoggerFactory loggerFactory)
2022
{
2123
_privateKeyPem = Encoding.UTF8.GetString(Convert.FromBase64String(configuration["GitHubProvisioning:PrivateKey"]));
2224
_clientId = configuration["GitHubProvisioning:ClientId"];
2325
_appId = configuration["GitHubProvisioning:AppId"];
26+
_syncTriggerKey = configuration["SyncTriggerKey"];
2427
_microsoftGraph = microsoftGraph;
2528
_logger = loggerFactory.CreateLogger<SyncController>();
2629
}
2730
public async Task<IActionResult> Index()
2831
{
32+
if (string.IsNullOrWhiteSpace(_syncTriggerKey))
33+
{
34+
_logger.LogError("SyncTriggerKey is not configured. The /api/sync endpoint cannot be used.");
35+
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
36+
}
37+
38+
if (!Request.Headers.TryGetValue("X-Sync-Trigger-Key", out var providedKey))
39+
{
40+
return new UnauthorizedResult();
41+
}
42+
43+
if (!CryptographicOperations.FixedTimeEquals(
44+
Encoding.UTF8.GetBytes(providedKey.FirstOrDefault() ?? string.Empty),
45+
Encoding.UTF8.GetBytes(_syncTriggerKey)))
46+
{
47+
return new UnauthorizedResult();
48+
}
49+
2950
var appClient = new GitHubClient(new ProductHeaderValue(Constants.UserAgent), new GitHubAppCredentialStore(long.Parse(_appId), _privateKeyPem));;
3051
var installations = await appClient.GitHubApps.GetAllInstallationsForCurrent();
3152

Web/Program.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
Web.Helpers.Constants.ExtensionAttributeName = builder.Configuration["AzureAd:ExtensionAttributeName"];
1919
Web.Helpers.Constants.ExemptUsers = builder.Configuration.GetSection("ExemptUsers").Get<string[]>();
2020

21+
if (string.IsNullOrWhiteSpace(builder.Configuration["SyncTriggerKey"]))
22+
{
23+
Console.WriteLine("WARNING: SyncTriggerKey is not configured. The /api/sync endpoint will be unavailable.");
24+
}
25+
2126
// Add services to the container.
2227
builder.Services.AddRazorPages();
2328
builder.Services.AddControllers();

0 commit comments

Comments
 (0)