migrate proxy (#2206)

* migrate proxy function

* - added private ip address query
- updated Azure.ResourceManager.Storage to non beta release

* remove comment

* extracting nework interface query

* format

* Update src/ApiService/ApiService/Functions/Proxy.cs

Co-authored-by: Teo Voinea <58236992+tevoinea@users.noreply.github.com>

* fix function name

* Fix merge conflict

Co-authored-by: Teo Voinea <58236992+tevoinea@users.noreply.github.com>
This commit is contained in:
Cheick Keita
2022-08-04 13:09:09 -07:00
committed by GitHub
parent 3a0e8bb2e3
commit 6d07095eea
19 changed files with 416 additions and 66 deletions

View File

@ -23,10 +23,10 @@
<PackageReference Include="Azure.Core" Version="1.25.0" /> <PackageReference Include="Azure.Core" Version="1.25.0" />
<PackageReference Include="Azure.Identity" Version="1.6.0" /> <PackageReference Include="Azure.Identity" Version="1.6.0" />
<PackageReference Include="Azure.Messaging.EventGrid" Version="4.10.0" /> <PackageReference Include="Azure.Messaging.EventGrid" Version="4.10.0" />
<PackageReference Include="Azure.ResourceManager" Version="1.0.0" /> <PackageReference Include="Azure.ResourceManager" Version="1.2.1" />
<PackageReference Include="Azure.ResourceManager.Network" Version="1.0.0-beta.7" /> <PackageReference Include="Azure.ResourceManager.Network" Version="1.0.0" />
<PackageReference Include="Azure.ResourceManager.Resources" Version="1.0.0" /> <PackageReference Include="Azure.ResourceManager.Resources" Version="1.0.0" />
<PackageReference Include="Azure.ResourceManager.Storage" Version="1.0.0-beta.8" /> <PackageReference Include="Azure.ResourceManager.Storage" Version="1.0.0-beta.11" />
<PackageReference Include="Azure.Storage.Queues" Version="12.11.0" /> <PackageReference Include="Azure.Storage.Queues" Version="12.11.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.13.0" /> <PackageReference Include="Azure.Storage.Blobs" Version="12.13.0" />
<PackageReference Include="Microsoft.Graph" Version="4.24.0" /> <PackageReference Include="Microsoft.Graph" Version="4.24.0" />

View File

@ -0,0 +1,172 @@
using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using VmProxy = Microsoft.OneFuzz.Service.Proxy;
namespace Microsoft.OneFuzz.Service.Functions;
public class Proxy {
private readonly ILogTracer _log;
private readonly IEndpointAuthorization _auth;
private readonly IOnefuzzContext _context;
public Proxy(ILogTracer log, IEndpointAuthorization auth, IOnefuzzContext context) {
_log = log;
_auth = auth;
_context = context;
}
[Function("proxy")]
public Async.Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "GET", "PATCH", "POST", "DELETE")] HttpRequestData req) {
return _auth.CallIfUser(req, r => r.Method switch {
"GET" => Get(r),
"PATCH" => Patch(r),
"POST" => Post(r),
"DELETE" => Delete(r),
_ => throw new InvalidOperationException("Unsupported HTTP method"),
});
}
private ProxyGetResult GetResult(ProxyForward proxyForward, VmProxy? proxy) {
var forward = _context.ProxyForwardOperations.ToForward(proxyForward);
if (proxy == null
|| (proxy.State != VmState.Running && proxy.State != VmState.ExtensionsLaunch)
|| proxy.Heartbeat == null
|| !proxy.Heartbeat.Forwards.Contains(forward)
) {
return new ProxyGetResult(null, Forward: forward);
}
return new ProxyGetResult(proxy.Ip, forward);
}
private async Async.Task<HttpResponseData> Get(HttpRequestData req) {
var request = await RequestHandling.ParseRequest<ProxyGet>(req);
if (!request.IsOk) {
return await _context.RequestHandling.NotOk(
req,
request.ErrorV,
"ProxyGet");
}
var proxyGet = request.OkV;
switch ((proxyGet.ScalesetId, proxyGet.MachineId, proxyGet.DstPort)) {
case (Guid scalesetId, Guid machineId, int dstPort):
var scaleset = await _context.ScalesetOperations.GetById(scalesetId);
if (!scaleset.IsOk) {
return await _context.RequestHandling.NotOk(req, scaleset.ErrorV, "ProxyGet");
}
var proxy = await _context.ProxyOperations.GetOrCreate(scaleset.OkV.Region);
var forwards = await _context.ProxyForwardOperations.SearchForward(scalesetId: scalesetId,
machineId: machineId, dstPort: dstPort).ToListAsync();
if (!forwards.Any()) {
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "no forwards for scaleset and node" }), "debug_proxy get");
}
var response = req.CreateResponse();
await response.WriteAsJsonAsync(GetResult(forwards[0], proxy));
return response;
case (null, null, null):
var proxies = await _context.ProxyOperations.SearchAll()
.Select(p => new ProxyInfo(p.Region, p.ProxyId, p.State)).ToListAsync();
var r = req.CreateResponse();
await r.WriteAsJsonAsync(new ProxyList(proxies));
return r;
default:
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "ProxyGet must provide all or none of the following: scaleset_id, machine_id, dst_port" }), "debug_proxy get");
}
}
private async Async.Task<HttpResponseData> Post(HttpRequestData req) {
var request = await RequestHandling.ParseRequest<ProxyCreate>(req);
if (!request.IsOk) {
return await _context.RequestHandling.NotOk(
req,
request.ErrorV,
"ProxyCreate");
}
var scaleset = await _context.ScalesetOperations.GetById(request.OkV.MachineId);
if (!scaleset.IsOk) {
return await _context.RequestHandling.NotOk(req, scaleset.ErrorV, "debug_proxy create");
}
var forwardResult = await _context.ProxyForwardOperations.UpdateOrCreate(
region: scaleset.OkV.Region,
scalesetId: scaleset.OkV.ScalesetId,
machineId: request.OkV.MachineId,
dstPort: request.OkV.DstPort,
duration: request.OkV.Duration
);
if (!forwardResult.IsOk) {
return await _context.RequestHandling.NotOk(req, forwardResult.ErrorV, "debug_proxy create");
}
var proxy = await _context.ProxyOperations.GetOrCreate(scaleset.OkV.Region);
if (proxy != null) {
var updated = forwardResult.OkV with { ProxyId = proxy.ProxyId };
await _context.ProxyForwardOperations.Update(updated);
await _context.ProxyOperations.SaveProxyConfig(proxy);
}
var response = req.CreateResponse();
var result = GetResult(forwardResult.OkV, proxy);
await response.WriteAsJsonAsync(result);
return response;
}
private async Async.Task<HttpResponseData> Patch(HttpRequestData req) {
var request = await RequestHandling.ParseRequest<ProxyReset>(req);
if (!request.IsOk) {
return await _context.RequestHandling.NotOk(
req,
request.ErrorV,
"ProxyReset");
}
var proxyList = await _context.ProxyOperations.SearchByPartitionKeys(new[] { $"{request.OkV.Region}" }).ToListAsync();
foreach (var proxy in proxyList) {
await _context.ProxyOperations.SetState(proxy, VmState.Stopping);
}
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(new BoolResult(proxyList.Any()));
return response;
}
private async Async.Task<HttpResponseData> Delete(HttpRequestData req) {
var request = await RequestHandling.ParseRequest<ProxyDelete>(req);
if (!request.IsOk) {
return await _context.RequestHandling.NotOk(
req,
request.ErrorV,
"debug_proxy delet");
}
var regions = await _context.ProxyForwardOperations.RemoveForward(
scalesetId: request.OkV.ScalesetId,
machineId: request.OkV.MachineId,
dstPort: request.OkV.DstPort
);
foreach (var region in regions) {
var proxy = await _context.ProxyOperations.GetOrCreate(region);
if (proxy != null) {
await _context.ProxyOperations.SaveProxyConfig(proxy);
}
}
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(new BoolResult(true));
return response;
}
}

View File

@ -78,7 +78,7 @@ public class TimerProxy {
// if there are NSGs with name same as the region that they are allocated // if there are NSGs with name same as the region that they are allocated
// and have no NIC associated with it then delete the NSG // and have no NIC associated with it then delete the NSG
await foreach (var nsg in nsgOpertions.ListNsgs()) { await foreach (var nsg in nsgOpertions.ListNsgs()) {
if (nsgOpertions.OkToDelete(regions, nsg.Data.Location, nsg.Data.Name)) { if (nsgOpertions.OkToDelete(regions, nsg.Data.Location!, nsg.Data.Name)) {
if (nsg.Data.NetworkInterfaces.Count == 0 && nsg.Data.Subnets.Count == 0) { if (nsg.Data.NetworkInterfaces.Count == 0 && nsg.Data.Subnets.Count == 0) {
await nsgOpertions.StartDeleteNsg(nsg.Data.Name); await nsgOpertions.StartDeleteNsg(nsg.Data.Name);
} }

View File

@ -83,7 +83,7 @@ public record ProxyHeartbeat
( (
Region Region, Region Region,
Guid ProxyId, Guid ProxyId,
List<ProxyForward> Forwards, List<Forward> Forwards,
DateTimeOffset TimeStamp DateTimeOffset TimeStamp
); );
@ -119,7 +119,7 @@ public record Forward
public record ProxyForward public record ProxyForward
( (
[PartitionKey] Region Region, [PartitionKey] Region Region,
[RowKey] string Port, [RowKey] long Port,
Guid ScalesetId, Guid ScalesetId,
Guid MachineId, Guid MachineId,
Guid? ProxyId, Guid? ProxyId,

View File

@ -139,3 +139,25 @@ public record JobSearch(
); );
public record NodeAddSshKeyPost(Guid MachineId, string PublicKey); public record NodeAddSshKeyPost(Guid MachineId, string PublicKey);
public record ProxyGet(
Guid? ScalesetId,
Guid? MachineId,
int? DstPort);
public record ProxyCreate(
Guid ScalesetId,
Guid MachineId,
int DstPort,
int Duration
);
public record ProxyDelete(
Guid ScalesetId,
Guid MachineId,
int? DstPort
);
public record ProxyReset(
string Region
);

View File

@ -101,3 +101,19 @@ public class BaseResponseConverter : JsonConverter<BaseResponse> {
JsonSerializer.Serialize(writer, value, eventType, options); JsonSerializer.Serialize(writer, value, eventType, options);
} }
} }
public record ProxyGetResult(
string? Ip,
Forward Forward
);
public record ProxyInfo(
string Region,
Guid ProxyId,
VmState State
);
public record ProxyList(
List<ProxyInfo> Proxies
);

View File

@ -103,6 +103,7 @@ public class Creds : ICreds {
var path = GetScalesetIdentityResourcePath(); var path = GetScalesetIdentityResourcePath();
var uid = ArmClient.GetGenericResource(new ResourceIdentifier(path)); var uid = ArmClient.GetGenericResource(new ResourceIdentifier(path));
var resource = await uid.GetAsync(); var resource = await uid.GetAsync();
var principalId = resource.Value.Data.Properties.ToObjectFromJson<ScaleSetIdentity>().principalId; var principalId = resource.Value.Data.Properties.ToObjectFromJson<ScaleSetIdentity>().principalId;
return new Guid(principalId); return new Guid(principalId);

View File

@ -1,7 +1,11 @@
using System.Threading.Tasks; using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Azure; using Azure;
using Azure.Core;
using Azure.ResourceManager.Network; using Azure.ResourceManager.Network;
using Azure.ResourceManager.Network.Models; using Azure.ResourceManager.Network.Models;
using Faithlife.Utility;
namespace Microsoft.OneFuzz.Service; namespace Microsoft.OneFuzz.Service;
@ -18,18 +22,22 @@ public interface IIpOperations {
public Async.Task DeleteIp(string resourceGroup, string name); public Async.Task DeleteIp(string resourceGroup, string name);
public Async.Task<string?> GetScalesetInstanceIp(Guid scalesetId, Guid machineId);
public Async.Task CreateIp(string resourceGroup, string name, string region); public Async.Task CreateIp(string resourceGroup, string name, string region);
} }
public class IpOperations : IIpOperations { public class IpOperations : IIpOperations {
private ILogTracer _logTracer; private ILogTracer _logTracer;
private IOnefuzzContext _context; private IOnefuzzContext _context;
private readonly NetworkInterfaceQuery _networkInterfaceQuery;
public IpOperations(ILogTracer log, IOnefuzzContext context) { public IpOperations(ILogTracer log, IOnefuzzContext context) {
_logTracer = log; _logTracer = log;
_context = context; _context = context;
_networkInterfaceQuery = new NetworkInterfaceQuery(context);
} }
public async Async.Task<NetworkInterfaceResource?> GetPublicNic(string resourceGroup, string name) { public async Async.Task<NetworkInterfaceResource?> GetPublicNic(string resourceGroup, string name) {
@ -43,7 +51,6 @@ public class IpOperations : IIpOperations {
public async Async.Task<PublicIPAddressResource?> GetIp(string resourceGroup, string name) { public async Async.Task<PublicIPAddressResource?> GetIp(string resourceGroup, string name) {
_logTracer.Info($"getting ip {resourceGroup}:{name}"); _logTracer.Info($"getting ip {resourceGroup}:{name}");
try { try {
return await _context.Creds.GetResourceGroupResource().GetPublicIPAddressAsync(name); return await _context.Creds.GetResourceGroupResource().GetPublicIPAddressAsync(name);
} catch (RequestFailedException) { } catch (RequestFailedException) {
@ -61,6 +68,16 @@ public class IpOperations : IIpOperations {
await _context.Creds.GetResourceGroupResource().GetPublicIPAddressAsync(name).Result.Value.DeleteAsync(WaitUntil.Started); await _context.Creds.GetResourceGroupResource().GetPublicIPAddressAsync(name).Result.Value.DeleteAsync(WaitUntil.Started);
} }
public async Task<string?> GetScalesetInstanceIp(Guid scalesetId, Guid machineId) {
var instance = await _context.VmssOperations.GetInstanceId(scalesetId, machineId);
if (!instance.IsOk) {
return null;
}
var ips = await _networkInterfaceQuery.ListInstancePrivateIps(scalesetId, instance.OkV);
return ips.FirstOrDefault();
}
public async Task<string?> GetPublicIp(string resourceId) { public async Task<string?> GetPublicIp(string resourceId) {
// TODO: Parts of this function seem redundant, but I'm mirroring // TODO: Parts of this function seem redundant, but I'm mirroring
// the python code exactly. We should revisit this. // the python code exactly. We should revisit this.
@ -75,7 +92,8 @@ public class IpOperations : IIpOperations {
if (publicIp == null) { if (publicIp == null) {
return null; return null;
} }
resource = _context.Creds.ParseResourceId(publicIp.Id);
resource = _context.Creds.ParseResourceId(publicIp.Id!);
try { try {
resource = await _context.Creds.GetData(resource); resource = await _context.Creds.GetData(resource);
var publicIpResource = await _context.Creds.GetResourceGroupResource().GetPublicIPAddressAsync( var publicIpResource = await _context.Creds.GetResourceGroupResource().GetPublicIPAddressAsync(
@ -93,7 +111,7 @@ public class IpOperations : IIpOperations {
var network = await Network.Create(region, _context); var network = await Network.Create(region, _context);
var subnetId = await network.GetId(); var subnetId = await network.GetId();
if (string.IsNullOrEmpty(subnetId)) { if (subnetId is not null) {
await network.Create(); await network.Create();
return OneFuzzResultVoid.Ok; return OneFuzzResultVoid.Ok;
} }
@ -157,7 +175,7 @@ public class IpOperations : IIpOperations {
public async Async.Task CreateIp(string resourceGroup, string name, string region) { public async Async.Task CreateIp(string resourceGroup, string name, string region) {
var ipParams = new PublicIPAddressData() { var ipParams = new PublicIPAddressData() {
Location = region, Location = region,
PublicIPAllocationMethod = IPAllocationMethod.Dynamic PublicIPAllocationMethod = NetworkIPAllocationMethod.Dynamic
}; };
var onefuzzOwner = _context.ServiceConfiguration.OneFuzzOwner; var onefuzzOwner = _context.ServiceConfiguration.OneFuzzOwner;
@ -172,4 +190,52 @@ public class IpOperations : IIpOperations {
); );
return; return;
} }
/// <summary>
/// Query the Scaleset network interface using the rest api directly because
/// the api does not seems to support this :
/// https://github.com/Azure/azure-sdk-for-net/issues/30253#issuecomment-1202447362
/// </summary>
class NetworkInterfaceQuery {
record IpConfigurationsProperties(string privateIPAddress);
record IpConfigurations(IpConfigurationsProperties properties);
record NetworkInterfaceProperties(List<IpConfigurations> ipConfigurations);
record NetworkInterface(NetworkInterfaceProperties properties);
record ValueList<T>(List<T> value);
private readonly IOnefuzzContext _context;
public NetworkInterfaceQuery(IOnefuzzContext context) {
_context = context;
}
public async Task<List<string>> ListInstancePrivateIps(Guid scalesetId, string instanceId) {
var token = _context.Creds.GetIdentity().GetToken(
new TokenRequestContext(
new[] { $"https://management.azure.com" }));
using HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token.Token);
var baseUrl = new Uri($"https://management.azure.com/");
// https://docs.microsoft.com/en-us/rest/api/virtualnetwork/network-interface-in-vm-ss/get-virtual-machine-scale-set-network-interface?tabs=HTTP
var requestURl = baseUrl + $"subscriptions/{_context.Creds.GetSubscription()}/resourceGroups/{_context.Creds.GetBaseResourceGroup()}/providers/Microsoft.Compute/virtualMachineScaleSets/{scalesetId}/virtualMachines/{instanceId}/networkInterfaces?api-version=2021-08-01";
var response = await client.GetAsync(requestURl);
if (response.IsSuccessStatusCode) {
var responseStream = await response.Content.ReadAsStreamAsync();
var nics = await JsonSerializer.DeserializeAsync<ValueList<NetworkInterface>>(responseStream);
if (nics != null)
return nics.value.SelectMany(x => x.properties.ipConfigurations.Select(i => i.properties.privateIPAddress)).WhereNotNull().ToList();
}
return new List<string>();
}
}
} }

View File

@ -1,4 +1,5 @@
using Azure.ResourceManager.Network; using Azure.Core;
using Azure.ResourceManager.Network;
namespace Microsoft.OneFuzz.Service; namespace Microsoft.OneFuzz.Service;
@ -48,7 +49,7 @@ public class Network {
return _context.Subnet.GetSubnet(_name, _name); return _context.Subnet.GetSubnet(_name, _name);
} }
public async Async.Task<string?> GetId() { public async Async.Task<ResourceIdentifier?> GetId() {
return await _context.Subnet.GetSubnetId(this._name, this._name); return await _context.Subnet.GetSubnetId(this._name, this._name);
} }
@ -61,7 +62,8 @@ public class Network {
} }
public async Async.Task<bool> Exists() { public async Async.Task<bool> Exists() {
return !string.IsNullOrEmpty(await GetId()); var id = await GetId();
return id is not null;
} }
internal Async.Task<VirtualNetworkResource?> GetVnet() { internal Async.Task<VirtualNetworkResource?> GetVnet() {

View File

@ -1,14 +1,20 @@
using ApiService.OneFuzzLib.Orm; using System.Threading.Tasks;
using ApiService.OneFuzzLib.Orm;
namespace Microsoft.OneFuzz.Service; namespace Microsoft.OneFuzz.Service;
public interface IProxyForwardOperations : IOrm<ProxyForward> { public interface IProxyForwardOperations : IOrm<ProxyForward> {
IAsyncEnumerable<ProxyForward> SearchForward(Guid? scalesetId = null, string? region = null, Guid? machineId = null, Guid? proxyId = null, int? dstPort = null); IAsyncEnumerable<ProxyForward> SearchForward(Guid? scalesetId = null, string? region = null, Guid? machineId = null, Guid? proxyId = null, int? dstPort = null);
Forward ToForward(ProxyForward proxyForward);
Task<OneFuzzResult<ProxyForward>> UpdateOrCreate(string region, Guid scalesetId, Guid machineId, int dstPort, int duration);
Task<HashSet<string>> RemoveForward(Guid scalesetId, Guid? machineId = null, int? dstPort = null, Guid? proxyId = null);
} }
public class ProxyForwardOperations : Orm<ProxyForward>, IProxyForwardOperations { public class ProxyForwardOperations : Orm<ProxyForward>, IProxyForwardOperations {
private static readonly List<int> PORT_RANGES = Enumerable.Range(28000, 32000 - 28000).ToList();
public ProxyForwardOperations(ILogTracer log, IOnefuzzContext context) public ProxyForwardOperations(ILogTracer log, IOnefuzzContext context)
: base(log, context) { : base(log, context) {
@ -29,4 +35,68 @@ public class ProxyForwardOperations : Orm<ProxyForward>, IProxyForwardOperations
return QueryAsync(filter); return QueryAsync(filter);
} }
public Forward ToForward(ProxyForward proxyForward) {
return new Forward(proxyForward.Port, proxyForward.DstPort, proxyForward.DstIp);
}
public async Task<OneFuzzResult<ProxyForward>> UpdateOrCreate(string region, Guid scalesetId, Guid machineId, int dstPort, int duration) {
var privateIp = await _context.IpOperations.GetScalesetInstanceIp(scalesetId, machineId);
if (privateIp == null) {
return OneFuzzResult<ProxyForward>.Error(ErrorCode.UNABLE_TO_PORT_FORWARD, new[] { "no private ip for node" });
}
var entries =
await this.SearchForward(scalesetId: scalesetId, region: region, machineId: machineId, dstPort: dstPort).ToListAsync();
var firstEntry = entries.FirstOrDefault();
if (firstEntry != null) {
var updated = firstEntry with { EndTime = DateTimeOffset.UtcNow + TimeSpan.FromHours(duration) };
await this.Update(updated);
return OneFuzzResult.Ok(updated);
}
var exisiting = entries.Select(x => x.Port).ToHashSet();
foreach (var port in PORT_RANGES) {
if (exisiting.Contains(port)) {
continue;
}
var entry = new ProxyForward(
Region: region,
Port: port,
ScalesetId: scalesetId,
MachineId: machineId,
DstIp: privateIp,
DstPort: dstPort,
EndTime: DateTimeOffset.UtcNow + TimeSpan.FromHours(duration),
ProxyId: null
);
var result = await Insert(entry);
if (!result.IsOk) {
_logTracer.Info($"port is already used {entry}");
}
return OneFuzzResult.Ok(entry);
}
return OneFuzzResult<ProxyForward>.Error(ErrorCode.UNABLE_TO_PORT_FORWARD, new[] { "all forward ports used" });
}
public async Task<HashSet<string>> RemoveForward(Guid scalesetId, Guid? machineId, int? dstPort, Guid? proxyId) {
var entries = await SearchForward(scalesetId: scalesetId, machineId: machineId, proxyId: proxyId, dstPort: dstPort).ToListAsync();
var regions = new HashSet<string>();
foreach (var entry in entries) {
regions.Add(entry.Region);
await Delete(entry);
}
return regions;
}
} }

View File

@ -12,6 +12,7 @@ public interface IProxyOperations : IStatefulOrm<Proxy, VmState> {
Async.Task SaveProxyConfig(Proxy proxy); Async.Task SaveProxyConfig(Proxy proxy);
bool IsOutdated(Proxy proxy); bool IsOutdated(Proxy proxy);
Async.Task<Proxy?> GetOrCreate(string region); Async.Task<Proxy?> GetOrCreate(string region);
} }
public class ProxyOperations : StatefulOrm<Proxy, VmState, ProxyOperations>, IProxyOperations { public class ProxyOperations : StatefulOrm<Proxy, VmState, ProxyOperations>, IProxyOperations {
@ -126,7 +127,7 @@ public class ProxyOperations : StatefulOrm<Proxy, VmState, ProxyOperations>, IPr
if (entry.EndTime < DateTimeOffset.UtcNow) { if (entry.EndTime < DateTimeOffset.UtcNow) {
await _context.ProxyForwardOperations.Delete(entry); await _context.ProxyForwardOperations.Delete(entry);
} else { } else {
forwards.Add(new Forward(long.Parse(entry.Port), entry.DstPort, entry.DstIp)); forwards.Add(new Forward(entry.Port, entry.DstPort, entry.DstIp));
} }
} }
return forwards; return forwards;

View File

@ -115,10 +115,6 @@ public sealed class Storage : IStorage, IDisposable {
continue; continue;
} }
if (string.IsNullOrEmpty(account.Data.PrimaryEndpoints.Blob)) {
continue;
}
if (!account.Data.Tags.ContainsKey(storageTypeTagKey) if (!account.Data.Tags.ContainsKey(storageTypeTagKey)
|| account.Data.Tags[storageTypeTagKey] != "corpus") { || account.Data.Tags[storageTypeTagKey] != "corpus") {
continue; continue;

View File

@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Azure; using Azure;
using Azure.Core;
using Azure.ResourceManager.Network; using Azure.ResourceManager.Network;
namespace Microsoft.OneFuzz.Service; namespace Microsoft.OneFuzz.Service;
@ -12,7 +13,7 @@ public interface ISubnet {
Async.Task<OneFuzzResultVoid> CreateVirtualNetwork(string resourceGroup, string name, string region, NetworkConfig networkConfig); Async.Task<OneFuzzResultVoid> CreateVirtualNetwork(string resourceGroup, string name, string region, NetworkConfig networkConfig);
Async.Task<string?> GetSubnetId(string name, string subnetName); Async.Task<ResourceIdentifier?> GetSubnetId(string name, string subnetName);
} }
public class Subnet : ISubnet { public class Subnet : ISubnet {
@ -75,7 +76,7 @@ public class Subnet : ISubnet {
return null; return null;
} }
public async Task<string?> GetSubnetId(string name, string subnetName) { public async Task<ResourceIdentifier?> GetSubnetId(string name, string subnetName) {
var subnet = await this.GetSubnet(name, subnetName); var subnet = await this.GetSubnet(name, subnetName);
if (subnet != null) { if (subnet != null) {
return subnet.Id; return subnet.Id;

View File

@ -115,6 +115,7 @@ public class VmssOperations : IVmssOperations {
public async Async.Task<OneFuzzResult<VirtualMachineScaleSetVmResource>> GetInstanceVm(Guid name, Guid vmId) { public async Async.Task<OneFuzzResult<VirtualMachineScaleSetVmResource>> GetInstanceVm(Guid name, Guid vmId) {
_log.Info($"get instance ID for scaleset node: {name}:{vmId}"); _log.Info($"get instance ID for scaleset node: {name}:{vmId}");
var scaleSet = GetVmssResource(name); var scaleSet = GetVmssResource(name);
try { try {
await foreach (var vm in scaleSet.GetVirtualMachineScaleSetVms().AsAsyncEnumerable()) { await foreach (var vm in scaleSet.GetVirtualMachineScaleSetVms().AsAsyncEnumerable()) {
var response = await vm.GetAsync(); var response = await vm.GetAsync();

View File

@ -232,6 +232,8 @@ public class EntityConverter {
return Guid.Parse(entity.GetString(ef.kind.ToString())); return Guid.Parse(entity.GetString(ef.kind.ToString()));
else if (ef.type == typeof(int)) else if (ef.type == typeof(int))
return int.Parse(entity.GetString(ef.kind.ToString())); return int.Parse(entity.GetString(ef.kind.ToString()));
else if (ef.type == typeof(long))
return long.Parse(entity.GetString(ef.kind.ToString()));
else if (ef.type.IsClass) else if (ef.type.IsClass)
return ef.type.GetConstructor(new[] { typeof(string) })!.Invoke(new[] { entity.GetString(ef.kind.ToString()) }); return ef.type.GetConstructor(new[] { typeof(string) })!.Invoke(new[] { entity.GetString(ef.kind.ToString()) });
else { else {

View File

@ -55,11 +55,11 @@
}, },
"Azure.ResourceManager": { "Azure.ResourceManager": {
"type": "Direct", "type": "Direct",
"requested": "[1.0.0, )", "requested": "[1.2.1, )",
"resolved": "1.0.0", "resolved": "1.2.1",
"contentHash": "UGaoiPcJ8a9Et030+F3zc2KhTssPAgPm7uXm4E9kyNI4jYYenUe6zj2J1bTimaTfcOZnn5scSjSYxKtZCzftcA==", "contentHash": "Ac7sSSLVbeJJGtw5JouMxZMHTKSokHu5NgCqlIpZM84SwpDpBK7j8sugUcDEryMPGO+BPeK42bTPJBEEs0DRQA==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -87,12 +87,12 @@
}, },
"Azure.ResourceManager.Network": { "Azure.ResourceManager.Network": {
"type": "Direct", "type": "Direct",
"requested": "[1.0.0-beta.7, )", "requested": "[1.0.0, )",
"resolved": "1.0.0-beta.7", "resolved": "1.0.0",
"contentHash": "Ih8tb6OwxEEEEXATVzgX6oHJzVr9p4X6GfOfBnNAI3aIt9+G8blyQLltaCcJAGJ+dO1sBT/Nalgj/HinO+cBlw==", "contentHash": "BhN2ULPSgi7vPmllXycYbGUBF/r9fI4zklGbuCBWPCNm2hJrFRQOwUy1NYy2UmLBRHtcAK7zp376n+lylsyjAg==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -109,12 +109,12 @@
}, },
"Azure.ResourceManager.Storage": { "Azure.ResourceManager.Storage": {
"type": "Direct", "type": "Direct",
"requested": "[1.0.0-beta.8, )", "requested": "[1.0.0-beta.11, )",
"resolved": "1.0.0-beta.8", "resolved": "1.0.0-beta.11",
"contentHash": "tlVqStqG53lyGxr0dRq2KSkFdeC/+NQImWgsRXD9o5R4qBia4cx7zAGYBlnDeUxh1WldSZF5ZsBi2n5SAwxbxQ==", "contentHash": "w7hOgG4yUFTRrJ65FzHeIQH8wFPczSJG12SnFiA9HrcvoceD/8CflIk5aPHzqc6moB3A1od0lwGciluovsHMbg==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },

View File

@ -94,10 +94,10 @@
}, },
"Azure.ResourceManager": { "Azure.ResourceManager": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.0.0", "resolved": "1.2.1",
"contentHash": "UGaoiPcJ8a9Et030+F3zc2KhTssPAgPm7uXm4E9kyNI4jYYenUe6zj2J1bTimaTfcOZnn5scSjSYxKtZCzftcA==", "contentHash": "Ac7sSSLVbeJJGtw5JouMxZMHTKSokHu5NgCqlIpZM84SwpDpBK7j8sugUcDEryMPGO+BPeK42bTPJBEEs0DRQA==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -123,11 +123,11 @@
}, },
"Azure.ResourceManager.Network": { "Azure.ResourceManager.Network": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.0.0-beta.7", "resolved": "1.0.0",
"contentHash": "Ih8tb6OwxEEEEXATVzgX6oHJzVr9p4X6GfOfBnNAI3aIt9+G8blyQLltaCcJAGJ+dO1sBT/Nalgj/HinO+cBlw==", "contentHash": "BhN2ULPSgi7vPmllXycYbGUBF/r9fI4zklGbuCBWPCNm2hJrFRQOwUy1NYy2UmLBRHtcAK7zp376n+lylsyjAg==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -143,11 +143,11 @@
}, },
"Azure.ResourceManager.Storage": { "Azure.ResourceManager.Storage": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.0.0-beta.8", "resolved": "1.0.0-beta.11",
"contentHash": "tlVqStqG53lyGxr0dRq2KSkFdeC/+NQImWgsRXD9o5R4qBia4cx7zAGYBlnDeUxh1WldSZF5ZsBi2n5SAwxbxQ==", "contentHash": "w7hOgG4yUFTRrJ65FzHeIQH8wFPczSJG12SnFiA9HrcvoceD/8CflIk5aPHzqc6moB3A1od0lwGciluovsHMbg==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -2127,12 +2127,12 @@
"Azure.Data.Tables": "12.5.0", "Azure.Data.Tables": "12.5.0",
"Azure.Identity": "1.6.0", "Azure.Identity": "1.6.0",
"Azure.Messaging.EventGrid": "4.10.0", "Azure.Messaging.EventGrid": "4.10.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.1",
"Azure.ResourceManager.Compute": "1.0.0-beta.8", "Azure.ResourceManager.Compute": "1.0.0-beta.8",
"Azure.ResourceManager.Monitor": "1.0.0-beta.2", "Azure.ResourceManager.Monitor": "1.0.0-beta.2",
"Azure.ResourceManager.Network": "1.0.0-beta.7", "Azure.ResourceManager.Network": "1.0.0",
"Azure.ResourceManager.Resources": "1.0.0", "Azure.ResourceManager.Resources": "1.0.0",
"Azure.ResourceManager.Storage": "1.0.0-beta.8", "Azure.ResourceManager.Storage": "1.0.0-beta.11",
"Azure.Security.KeyVault.Secrets": "4.3.0", "Azure.Security.KeyVault.Secrets": "4.3.0",
"Azure.Storage.Blobs": "12.13.0", "Azure.Storage.Blobs": "12.13.0",
"Azure.Storage.Queues": "12.11.0", "Azure.Storage.Queues": "12.11.0",

View File

@ -112,7 +112,7 @@ namespace Tests {
arg => arg =>
new ProxyForward( new ProxyForward(
Region: arg.Item1.Item1, Region: arg.Item1.Item1,
Port: arg.Item1.Item2.ToString(), Port: arg.Item1.Item2,
ScalesetId: arg.Item1.Item3, ScalesetId: arg.Item1.Item3,
MachineId: arg.Item1.Item4, MachineId: arg.Item1.Item4,
ProxyId: arg.Item1.Item5, ProxyId: arg.Item1.Item5,

View File

@ -113,10 +113,10 @@
}, },
"Azure.ResourceManager": { "Azure.ResourceManager": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.0.0", "resolved": "1.2.1",
"contentHash": "UGaoiPcJ8a9Et030+F3zc2KhTssPAgPm7uXm4E9kyNI4jYYenUe6zj2J1bTimaTfcOZnn5scSjSYxKtZCzftcA==", "contentHash": "Ac7sSSLVbeJJGtw5JouMxZMHTKSokHu5NgCqlIpZM84SwpDpBK7j8sugUcDEryMPGO+BPeK42bTPJBEEs0DRQA==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -142,11 +142,11 @@
}, },
"Azure.ResourceManager.Network": { "Azure.ResourceManager.Network": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.0.0-beta.7", "resolved": "1.0.0",
"contentHash": "Ih8tb6OwxEEEEXATVzgX6oHJzVr9p4X6GfOfBnNAI3aIt9+G8blyQLltaCcJAGJ+dO1sBT/Nalgj/HinO+cBlw==", "contentHash": "BhN2ULPSgi7vPmllXycYbGUBF/r9fI4zklGbuCBWPCNm2hJrFRQOwUy1NYy2UmLBRHtcAK7zp376n+lylsyjAg==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -162,11 +162,11 @@
}, },
"Azure.ResourceManager.Storage": { "Azure.ResourceManager.Storage": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.0.0-beta.8", "resolved": "1.0.0-beta.11",
"contentHash": "tlVqStqG53lyGxr0dRq2KSkFdeC/+NQImWgsRXD9o5R4qBia4cx7zAGYBlnDeUxh1WldSZF5ZsBi2n5SAwxbxQ==", "contentHash": "w7hOgG4yUFTRrJ65FzHeIQH8wFPczSJG12SnFiA9HrcvoceD/8CflIk5aPHzqc6moB3A1od0lwGciluovsHMbg==",
"dependencies": { "dependencies": {
"Azure.Core": "1.24.0", "Azure.Core": "1.25.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.0",
"System.Text.Json": "4.7.2" "System.Text.Json": "4.7.2"
} }
}, },
@ -2254,12 +2254,12 @@
"Azure.Data.Tables": "12.5.0", "Azure.Data.Tables": "12.5.0",
"Azure.Identity": "1.6.0", "Azure.Identity": "1.6.0",
"Azure.Messaging.EventGrid": "4.10.0", "Azure.Messaging.EventGrid": "4.10.0",
"Azure.ResourceManager": "1.0.0", "Azure.ResourceManager": "1.2.1",
"Azure.ResourceManager.Compute": "1.0.0-beta.8", "Azure.ResourceManager.Compute": "1.0.0-beta.8",
"Azure.ResourceManager.Monitor": "1.0.0-beta.2", "Azure.ResourceManager.Monitor": "1.0.0-beta.2",
"Azure.ResourceManager.Network": "1.0.0-beta.7", "Azure.ResourceManager.Network": "1.0.0",
"Azure.ResourceManager.Resources": "1.0.0", "Azure.ResourceManager.Resources": "1.0.0",
"Azure.ResourceManager.Storage": "1.0.0-beta.8", "Azure.ResourceManager.Storage": "1.0.0-beta.11",
"Azure.Security.KeyVault.Secrets": "4.3.0", "Azure.Security.KeyVault.Secrets": "4.3.0",
"Azure.Storage.Blobs": "12.13.0", "Azure.Storage.Blobs": "12.13.0",
"Azure.Storage.Queues": "12.11.0", "Azure.Storage.Queues": "12.11.0",