Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ The application secrets can be also passed in as [environment variables](https:/
},
"ExemptUsers": [
"<Case_Sensitive_List_Of_Users>"
]
],
"SyncTriggerKey": "<secret_key_to_trigger_sync>"
}
```

Expand Down
21 changes: 21 additions & 0 deletions Web/Controllers/SyncController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Web.Services;
using Microsoft.AspNetCore.Mvc;
using Octokit;
using System.Security.Cryptography;
using System.Text;

namespace Web.Controllers
Expand All @@ -14,18 +15,38 @@ public class SyncController : Controller
private readonly string _privateKeyPem;
private readonly string _clientId;
private readonly string _appId;
private readonly string? _syncTriggerKey;
private readonly MicrosoftGraphService _microsoftGraph;
private readonly ILogger _logger;
public SyncController(IConfiguration configuration, MicrosoftGraphService microsoftGraph, ILoggerFactory loggerFactory)
{
_privateKeyPem = Encoding.UTF8.GetString(Convert.FromBase64String(configuration["GitHubProvisioning:PrivateKey"]));
_clientId = configuration["GitHubProvisioning:ClientId"];
_appId = configuration["GitHubProvisioning:AppId"];
_syncTriggerKey = configuration["SyncTriggerKey"];
_microsoftGraph = microsoftGraph;
_logger = loggerFactory.CreateLogger<SyncController>();
}
public async Task<IActionResult> Index()
{
if (string.IsNullOrWhiteSpace(_syncTriggerKey))
{
_logger.LogError("SyncTriggerKey is not configured. The /api/sync endpoint cannot be used.");
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
}

if (!Request.Headers.TryGetValue("X-Sync-Trigger-Key", out var providedKey))
{
return new UnauthorizedResult();
}

if (!CryptographicOperations.FixedTimeEquals(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use equals instead of this comparison

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in b065b8c — replaced the CryptographicOperations.FixedTimeEquals byte-array comparison with string.Equals(providedKey.FirstOrDefault(), _syncTriggerKey, StringComparison.Ordinal) and removed the now-unused System.Security.Cryptography import.

Encoding.UTF8.GetBytes(providedKey.FirstOrDefault() ?? string.Empty),
Encoding.UTF8.GetBytes(_syncTriggerKey)))
{
return new UnauthorizedResult();
}

var appClient = new GitHubClient(new ProductHeaderValue(Constants.UserAgent), new GitHubAppCredentialStore(long.Parse(_appId), _privateKeyPem));;
var installations = await appClient.GitHubApps.GetAllInstallationsForCurrent();

Expand Down
5 changes: 5 additions & 0 deletions Web/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
Web.Helpers.Constants.ExtensionAttributeName = builder.Configuration["AzureAd:ExtensionAttributeName"];
Web.Helpers.Constants.ExemptUsers = builder.Configuration.GetSection("ExemptUsers").Get<string[]>();

if (string.IsNullOrWhiteSpace(builder.Configuration["SyncTriggerKey"]))
{
Console.WriteLine("WARNING: SyncTriggerKey is not configured. The /api/sync endpoint will be unavailable.");
}

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllers();
Expand Down