// Copyright Epic Games, Inc. All Rights Reserved. using EpicGames.Horde; using EpicGames.Horde.Secrets; using Microsoft.Extensions.DependencyInjection; using System.Collections.Concurrent; using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; #nullable enable namespace AutomationTool { /// /// Helper methods for Horde functionality /// public partial class CommandUtils { static readonly ConcurrentDictionary> _cachedSecrets = new ConcurrentDictionary>(); /// /// Reads a secret from Horde /// /// Identifier of the secret to retrieve /// Cancellation token for the operation /// Values configured for the given secret public static async Task> GetHordeSecretAsync(SecretId secretId, CancellationToken cancellationToken = default) { IReadOnlyDictionary? secret; if (!_cachedSecrets.TryGetValue(secretId, out secret)) { IHordeClient hordeClient = ServiceProvider.GetRequiredService(); using HordeHttpClient hordeHttpClient = hordeClient.CreateHttpClient(); GetSecretResponse response; try { response = await hordeHttpClient.GetSecretAsync(secretId); } catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) { throw new AutomationException(ex, $"Secret '{secretId}' was not found on {hordeClient.ServerUrl}"); } catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Forbidden) { throw new AutomationException(ex, $"User does not have permissions to read '{secretId}' on {hordeClient.ServerUrl}"); } secret = response.Data; _cachedSecrets.TryAdd(secretId, secret); } return secret; } /// /// Reads a secret from Horde /// /// Identifier of the secret to retrieve /// Name of the property within the secret /// Cancellation token for the operation /// Values configured for the given secret public static async Task GetHordeSecretAsync(SecretId secretId, string propertyName, CancellationToken cancellationToken = default) { IReadOnlyDictionary secrets = await GetHordeSecretAsync(secretId, cancellationToken); if (!secrets.TryGetValue(propertyName, out string? propertyValue)) { throw new AutomationException("Secret '{secretId}' does not contain a value for '{propertyName}'"); } return propertyValue; } } }