From 36d36cdfaa16fbb7fdaa66da7f37c5d56dc9613a Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Thu, 28 Jul 2022 12:12:47 -0700 Subject: [PATCH] saving secrets in keyvault (#2200) --- .../ApiService/OneFuzzTypes/Model.cs | 2 +- .../onefuzzlib/NotificationOperations.cs | 24 +++++++++++++++++-- .../ApiService/onefuzzlib/Request.cs | 2 +- .../ApiService/onefuzzlib/Secrets.cs | 10 ++++---- src/ApiService/Tests/OrmModelsTest.cs | 4 ++-- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/ApiService/ApiService/OneFuzzTypes/Model.cs b/src/ApiService/ApiService/OneFuzzTypes/Model.cs index 918b37f05..da0e8476f 100644 --- a/src/ApiService/ApiService/OneFuzzTypes/Model.cs +++ b/src/ApiService/ApiService/OneFuzzTypes/Model.cs @@ -677,7 +677,7 @@ public class ISecretConverter : JsonConverter> { if (value is SecretAddress secretAddress) { JsonSerializer.Serialize(writer, secretAddress, options); } else if (value is SecretValue secretValue) { - JsonSerializer.Serialize(writer, secretValue.Value, options); + throw new JsonException("SecretValue should not be serialized"); } } } diff --git a/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs b/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs index b5a66cb1d..473dc33d6 100644 --- a/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs +++ b/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs @@ -99,16 +99,36 @@ public class NotificationOperations : Orm, INotificationOperations await this.Delete(existingEntry); } } - - var entry = new Notification(Guid.NewGuid(), container, config); + var configWithHiddenSecret = await HideSecrets(config); + var entry = new Notification(Guid.NewGuid(), container, configWithHiddenSecret); await this.Insert(entry); _logTracer.Info($"created notification. notification_id:{entry.NotificationId} container:{entry.Container}"); return OneFuzzResult.Ok(entry); } + + private async Async.Task HideSecrets(NotificationTemplate notificationTemplate) { + + switch (notificationTemplate) { + case AdoTemplate adoTemplate: + var hiddenAuthToken = await _context.SecretsOperations.SaveToKeyvault(adoTemplate.AuthToken); + return adoTemplate with { AuthToken = hiddenAuthToken }; + case GithubIssuesTemplate githubIssuesTemplate: + var hiddenAuth = await _context.SecretsOperations.SaveToKeyvault(githubIssuesTemplate.Auth); + return githubIssuesTemplate with { Auth = hiddenAuth }; + case TeamsTemplate teamsTemplate: + var hiddenUrl = await _context.SecretsOperations.SaveToKeyvault(teamsTemplate.Url); + return teamsTemplate with { Url = hiddenUrl }; + default: + throw new ArgumentOutOfRangeException(nameof(notificationTemplate)); + } + + } + public async Async.Task GetRegressionReportTask(RegressionReport report) { if (report.CrashTestResult.CrashReport != null) { + return await _context.TaskOperations.GetByJobIdAndTaskId(report.CrashTestResult.CrashReport.JobId, report.CrashTestResult.CrashReport.TaskId); } if (report.CrashTestResult.NoReproReport != null) { diff --git a/src/ApiService/ApiService/onefuzzlib/Request.cs b/src/ApiService/ApiService/onefuzzlib/Request.cs index f3b38b029..4391037c7 100644 --- a/src/ApiService/ApiService/onefuzzlib/Request.cs +++ b/src/ApiService/ApiService/onefuzzlib/Request.cs @@ -33,7 +33,7 @@ public class RequestHandling : IRequestHandling { public static async Async.Task> ParseRequest(HttpRequestData req) { Exception? exception = null; try { - var t = await JsonSerializer.DeserializeAsync(req.Body, EntityConverter.GetJsonSerializerOptions()); + var t = await req.ReadFromJsonAsync(); if (t != null) { return OneFuzzResult.Ok(t); } diff --git a/src/ApiService/ApiService/onefuzzlib/Secrets.cs b/src/ApiService/ApiService/onefuzzlib/Secrets.cs index 1264a9224..d86438d64 100644 --- a/src/ApiService/ApiService/onefuzzlib/Secrets.cs +++ b/src/ApiService/ApiService/onefuzzlib/Secrets.cs @@ -7,7 +7,7 @@ namespace Microsoft.OneFuzz.Service; public interface ISecretsOperations { public (Uri, string) ParseSecretUrl(Uri secretsUrl); - public Task> SaveToKeyvault(SecretData secretData); + public Task> SaveToKeyvault(SecretData secretData); public Task GetSecretStringValue(SecretData data); @@ -31,14 +31,14 @@ public class SecretsOperations : ISecretsOperations { public (Uri, string) ParseSecretUrl(Uri secretsUrl) { // format: https://{vault-name}.vault.azure.net/secrets/{secret-name}/{version} var vaultUrl = $"{secretsUrl.Scheme}://{secretsUrl.Host}"; - var secretName = secretsUrl.Segments[secretsUrl.Segments.Length - 2].Trim('/'); + var secretName = secretsUrl.Segments[^2].Trim('/'); return (new Uri(vaultUrl), secretName); } - public async Task> SaveToKeyvault(SecretData secretData) { + public async Task> SaveToKeyvault(SecretData secretData) { if (secretData.Secret is SecretAddress secretAddress) { - return secretAddress; + return secretData; } else if (secretData.Secret is SecretValue sValue) { var secretName = Guid.NewGuid(); string secretValue; @@ -49,7 +49,7 @@ public class SecretsOperations : ISecretsOperations { } var kv = await StoreInKeyvault(GetKeyvaultAddress(), secretName.ToString(), secretValue); - return new SecretAddress(kv.Id); + return new SecretData(new SecretAddress(kv.Id)); } throw new Exception("Invalid secret value"); diff --git a/src/ApiService/Tests/OrmModelsTest.cs b/src/ApiService/Tests/OrmModelsTest.cs index cd00280cc..65aa80a3b 100644 --- a/src/ApiService/Tests/OrmModelsTest.cs +++ b/src/ApiService/Tests/OrmModelsTest.cs @@ -43,11 +43,11 @@ namespace Tests { public static Gen> ISecret() { if (typeof(T) == typeof(string)) { - return Arb.Generate().Select(s => (ISecret)new SecretValue(s)); + return Arb.Generate().Select(s => (ISecret)new SecretAddress(new Uri("http://test"))); } if (typeof(T) == typeof(GithubAuth)) { - return Arb.Generate().Select(s => (ISecret)new SecretValue(s)); + return Arb.Generate().Select(s => (ISecret)new SecretAddress(new Uri("http://test"))); } else { throw new Exception($"Unsupported secret type {typeof(T)}"); }