diff --git a/src/ApiService/ApiService/OneFuzzTypes/Model.cs b/src/ApiService/ApiService/OneFuzzTypes/Model.cs index 9781dd73bfb..fe715f78983 100644 --- a/src/ApiService/ApiService/OneFuzzTypes/Model.cs +++ b/src/ApiService/ApiService/OneFuzzTypes/Model.cs @@ -103,8 +103,8 @@ public record Node public record Forward ( - int SrcPort, - int DstPort, + long SrcPort, + long DstPort, string DstIp ); @@ -112,13 +112,13 @@ string DstIp public record ProxyForward ( [PartitionKey] Region Region, - int Port, + [RowKey] string Port, Guid ScalesetId, Guid MachineId, Guid? ProxyId, - [RowKey] int DstPort, + long DstPort, string DstIp, - DateTimeOffset EndTime + [property: JsonPropertyName("endtime")] DateTimeOffset EndTime ) : EntityBase(); public record ProxyConfig diff --git a/src/ApiService/ApiService/TestHooks/InstanceConfigTestHooks.cs b/src/ApiService/ApiService/TestHooks/InstanceConfigTestHooks.cs index 840bee26ff6..95b9dc3b69f 100644 --- a/src/ApiService/ApiService/TestHooks/InstanceConfigTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/InstanceConfigTestHooks.cs @@ -54,10 +54,10 @@ public async Task Patch([HttpTrigger(AuthorizationLevel.Anonym } else { var query = UriExtension.GetQueryComponents(req.Url); - bool isNew = UriExtension.GetBoolValue("isNew", query, false); + bool isNew = UriExtension.GetBool("isNew", query, false); //requireEtag wont' work since our current schema does not return etag to the client when getting data form the table, so // there is no way to know which etag to use - bool requireEtag = UriExtension.GetBoolValue("requireEtag", query, false); + bool requireEtag = UriExtension.GetBool("requireEtag", query, false); await _configOps.Save(newInstanceConfig, isNew, requireEtag); diff --git a/src/ApiService/ApiService/TestHooks/IpOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/IpOperationsTestHooks.cs index 469eca2dd7c..9934c49fc28 100644 --- a/src/ApiService/ApiService/TestHooks/IpOperationsTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/IpOperationsTestHooks.cs @@ -59,7 +59,7 @@ public async Task DeletePublicNic([HttpTrigger(AuthorizationLe var rg = query["rg"]; var name = query["name"]; - var yes = UriExtension.GetBoolValue("force", query, false); + var yes = UriExtension.GetBool("force", query, false); if (yes) { await _ipOps.DeleteNic(rg, name); @@ -79,7 +79,7 @@ public async Task DeleteIp([HttpTrigger(AuthorizationLevel.Ano var rg = query["rg"]; var name = query["name"]; - var yes = UriExtension.GetBoolValue("force", query, false); + var yes = UriExtension.GetBool("force", query, false); if (yes) { await _ipOps.DeleteIp(rg, name); diff --git a/src/ApiService/ApiService/TestHooks/JobOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/JobOperationsTestHooks.cs index 263c0a89887..f69ebf913d4 100644 --- a/src/ApiService/ApiService/TestHooks/JobOperationsTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/JobOperationsTestHooks.cs @@ -53,10 +53,10 @@ public async Task SearchState([HttpTrigger(AuthorizationLevel. _log.Info("Search jobs by state"); var query = UriExtension.GetQueryComponents(req.Url); - var init = UriExtension.GetBoolValue("init", query, false); - var enabled = UriExtension.GetBoolValue("enabled", query, false); - var stopping = UriExtension.GetBoolValue("stopping", query, false); - var stopped = UriExtension.GetBoolValue("stopped", query, false); + var init = UriExtension.GetBool("init", query, false); + var enabled = UriExtension.GetBool("enabled", query, false); + var stopping = UriExtension.GetBool("stopping", query, false); + var stopped = UriExtension.GetBool("stopped", query, false); var states = new List(); if (init) { diff --git a/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs index 7bccdafba09..d5c3a31626b 100644 --- a/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs @@ -128,7 +128,7 @@ public async Task ToReimage([HttpTrigger(AuthorizationLevel.An _log.Info("to reimage"); var query = UriExtension.GetQueryComponents(req.Url); - var done = UriExtension.GetBoolValue("done", query, false); + var done = UriExtension.GetBool("done", query, false); var s = await req.ReadAsStringAsync(); var node = JsonSerializer.Deserialize(s!, EntityConverter.GetJsonSerializerOptions()); @@ -158,35 +158,18 @@ public async Task SearchStates([HttpTrigger(AuthorizationLevel _log.Info("search states"); var query = UriExtension.GetQueryComponents(req.Url); - - Guid? poolId = default; - if (query.ContainsKey("poolId")) { - poolId = Guid.Parse(query["poolId"]); - } - - Guid? scaleSetId = default; - if (query.ContainsKey("scaleSetId")) { - scaleSetId = Guid.Parse(query["scaleSetId"]); - } + Guid? poolId = UriExtension.GetGuid("poolId", query); + Guid? scaleSetId = UriExtension.GetGuid("scaleSetId", query); List? states = default; if (query.ContainsKey("states")) { states = query["states"].Split('-').Select(s => Enum.Parse(s)).ToList(); } + string? poolName = UriExtension.GetString("poolName", query); - string? poolName = default; - if (query.ContainsKey("poolName")) { - poolName = query["poolName"]; - } - - var excludeUpdateScheduled = UriExtension.GetBoolValue("excludeUpdateScheduled", query, false); - int? numResults = default; - if (query.ContainsKey("numResults")) { - numResults = int.Parse(query["numResults"]); - } + var excludeUpdateScheduled = UriExtension.GetBool("excludeUpdateScheduled", query, false); + int? numResults = UriExtension.GetInt("numResults", query); var r = _nodeOps.SearchStates(poolId, scaleSetId, states, poolName, excludeUpdateScheduled, numResults); - - var json = JsonSerializer.Serialize(await r.ToListAsync(), EntityConverter.GetJsonSerializerOptions()); var resp = req.CreateResponse(HttpStatusCode.OK); await resp.WriteStringAsync(json); @@ -236,7 +219,7 @@ public async Task CreateNode([HttpTrigger(AuthorizationLevel.A string version = query["version"]; - bool isNew = UriExtension.GetBoolValue("isNew", query, false); + bool isNew = UriExtension.GetBool("isNew", query, false); var node = await _nodeOps.Create(poolId, poolName, machineId, scaleSetId, version, isNew); diff --git a/src/ApiService/ApiService/TestHooks/NotificationOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/NotificationOperationsTestHooks.cs index 91d2c908e61..37bc9251a73 100644 --- a/src/ApiService/ApiService/TestHooks/NotificationOperationsTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/NotificationOperationsTestHooks.cs @@ -28,7 +28,7 @@ public async Task NewFiles([HttpTrigger(AuthorizationLevel.Ano var container = query["container"]; var fileName = query["fileName"]; - var failTaskOnTransientError = UriExtension.GetBoolValue("failTaskOnTransientError", query, true); + var failTaskOnTransientError = UriExtension.GetBool("failTaskOnTransientError", query, true); await _notificationOps.NewFiles(new Container(container), fileName, failTaskOnTransientError); var resp = req.CreateResponse(HttpStatusCode.OK); diff --git a/src/ApiService/ApiService/TestHooks/NsgOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/NsgOperationsTestHooks.cs index b4767c5861d..1d5a01d064d 100644 --- a/src/ApiService/ApiService/TestHooks/NsgOperationsTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/NsgOperationsTestHooks.cs @@ -15,7 +15,7 @@ public class NsgOperationsTestHooks { private readonly INsgOperations _nsgOperations; public NsgOperationsTestHooks(ILogTracer log, IConfigOperations configOps, INsgOperations nsgOperations) { - _log = log.WithTag("TestHooks", nameof(NotificationOperationsTestHooks)); + _log = log.WithTag("TestHooks", nameof(NsgOperationsTestHooks)); _configOps = configOps; ; _nsgOperations = nsgOperations; } diff --git a/src/ApiService/ApiService/TestHooks/PoolOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/PoolOperationsTestHooks.cs index b23c630f448..75a40c8c8a4 100644 --- a/src/ApiService/ApiService/TestHooks/PoolOperationsTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/PoolOperationsTestHooks.cs @@ -21,7 +21,7 @@ public PoolOperationsTestHooks(ILogTracer log, IConfigOperations configOps, IPoo [Function("GetPoolTestHook")] - public async Task GetNsg([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/poolOperations/pool")] HttpRequestData req) { + public async Task GetPool([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/poolOperations/pool")] HttpRequestData req) { _log.Info("get pool"); var query = UriExtension.GetQueryComponents(req.Url); diff --git a/src/ApiService/ApiService/TestHooks/ProxyForwardTestHooks.cs b/src/ApiService/ApiService/TestHooks/ProxyForwardTestHooks.cs new file mode 100644 index 00000000000..8a6752eec78 --- /dev/null +++ b/src/ApiService/ApiService/TestHooks/ProxyForwardTestHooks.cs @@ -0,0 +1,43 @@ +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.OneFuzz.Service; +using Microsoft.OneFuzz.Service.OneFuzzLib.Orm; + + +#if DEBUG +namespace ApiService.TestHooks { + public class ProxyForwardTestHooks { + private readonly ILogTracer _log; + private readonly IConfigOperations _configOps; + private readonly IProxyForwardOperations _proxyForward; + + public ProxyForwardTestHooks(ILogTracer log, IConfigOperations configOps, IProxyForwardOperations proxyForward) { + _log = log.WithTag("TestHooks", nameof(ProxyForwardTestHooks)); + _configOps = configOps; ; + _proxyForward = proxyForward; ; + } + + [Function("SearchForwardTestHook")] + public async Task SearchForward([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/proxyForwardOperations/search")] HttpRequestData req) { + _log.Info("search proxy forward"); + + var query = UriExtension.GetQueryComponents(req.Url); + + var poolRes = _proxyForward.SearchForward( + UriExtension.GetGuid("scaleSetId", query), + UriExtension.GetString("region", query), + UriExtension.GetGuid("machineId", query), + UriExtension.GetGuid("proxyId", query), + UriExtension.GetInt("dstPort", query)); + + var json = JsonSerializer.Serialize(await poolRes.ToListAsync(), EntityConverter.GetJsonSerializerOptions()); + var resp = req.CreateResponse(HttpStatusCode.OK); + await resp.WriteStringAsync(json); + return resp; + } + } +} +#endif diff --git a/src/ApiService/ApiService/TestHooks/UriExtension.cs b/src/ApiService/ApiService/TestHooks/UriExtension.cs index 068afc2a19b..4b14a922b39 100644 --- a/src/ApiService/ApiService/TestHooks/UriExtension.cs +++ b/src/ApiService/ApiService/TestHooks/UriExtension.cs @@ -13,18 +13,43 @@ from cs in queryComponents return new Dictionary(q); } - public static bool GetBoolValue(string key, IDictionary query, bool defaultValue = false) { + public static bool GetBool(string key, IDictionary query, bool defaultValue = false) { bool v; if (query.ContainsKey(key)) { - if (!bool.TryParse(query[key], out v)) { - v = defaultValue; - } + v = bool.Parse(query[key]); } else { v = defaultValue; } return v; } + public static int? GetInt(string key, IDictionary query, int? defaultValue = null) { + int? v; + if (query.ContainsKey(key)) { + v = int.Parse(query[key]); + } else { + v = defaultValue; + } + return v; + } + + + public static string? GetString(string key, IDictionary query, string? defaultValue = null) { + if (query.ContainsKey(key)) { + return query[key]; + } else { + return defaultValue; + } + } + + public static Guid? GetGuid(string key, IDictionary query, Guid? defaultValue = null) { + if (query.ContainsKey(key)) { + return Guid.Parse(query[key]); + } else { + return defaultValue; + } + } + } } diff --git a/src/ApiService/ApiService/onefuzzlib/ProxyForwardOperations.cs b/src/ApiService/ApiService/onefuzzlib/ProxyForwardOperations.cs index 7ad9e0920f8..921cb7de8f4 100644 --- a/src/ApiService/ApiService/onefuzzlib/ProxyForwardOperations.cs +++ b/src/ApiService/ApiService/onefuzzlib/ProxyForwardOperations.cs @@ -19,13 +19,13 @@ public IAsyncEnumerable SearchForward(Guid? scalesetId = null, str var conditions = new[] { scalesetId != null ? $"scaleset_id eq '{scalesetId}'" : null, - region != null ? $"region eq '{region}'" : null , + region != null ? $"PartitionKey eq '{region}'" : null , machineId != null ? $"machine_id eq '{machineId}'" : null , proxyId != null ? $"proxy_id eq '{proxyId}'" : null , - dstPort != null ? $"dsp_port eq {dstPort }" : null , + dstPort != null ? $"dst_port eq {dstPort }" : null , }.Where(x => x != null); - var filter = string.Join(" and ", conditions); + var filter = Query.And(conditions!); return QueryAsync(filter); } diff --git a/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs b/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs index 7cffc0b0948..dcc8c7308aa 100644 --- a/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs +++ b/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs @@ -108,7 +108,6 @@ public async Async.Task SaveProxyConfig(Proxy proxy) { } - public async Async.Task SetState(Proxy proxy, VmState state) { if (proxy.State == state) { return; @@ -127,7 +126,7 @@ public async Async.Task> GetForwards(Proxy proxy) { if (entry.EndTime < DateTimeOffset.UtcNow) { await _context.ProxyForwardOperations.Delete(entry); } else { - forwards.Add(new Forward(entry.Port, entry.DstPort, entry.DstIp)); + forwards.Add(new Forward(long.Parse(entry.Port), entry.DstPort, entry.DstIp)); } } return forwards; diff --git a/src/ApiService/Tests/OrmModelsTest.cs b/src/ApiService/Tests/OrmModelsTest.cs index 7f95eb15756..fd40b71d1f2 100644 --- a/src/ApiService/Tests/OrmModelsTest.cs +++ b/src/ApiService/Tests/OrmModelsTest.cs @@ -91,11 +91,11 @@ public static Gen Node() { } public static Gen ProxyForward() { - return Arb.Generate, Tuple>>().Select( + return Arb.Generate, Tuple>>().Select( arg => new ProxyForward( Region: arg.Item1.Item1, - Port: arg.Item1.Item2, + Port: arg.Item1.Item2.ToString(), ScalesetId: arg.Item1.Item3, MachineId: arg.Item1.Item4, ProxyId: arg.Item1.Item5,