public async Task WhenInstanceAvailableButRelayPolicyFails_ThenProbeThrowsUnauthorizedException( [WindowsInstance] ResourceTask <InstanceLocator> testInstance, [Credential(Role = PredefinedRole.IapTunnelUser)] ResourceTask <ICredential> credential) { var service = new TunnelService(CreateAuthorizationAdapter( await credential, null)); var destination = new TunnelDestination( await testInstance, 3389); using (var tunnel = await service.CreateTunnelAsync( destination, new DenyAllPolicy())) { // The Probe should still succeed. await tunnel.Probe(TimeSpan.FromSeconds(20)); // Trying to send ot receive anything should cause a connection reset. var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(new IPEndPoint(IPAddress.Loopback, tunnel.LocalPort)); socket.ReceiveTimeout = 100; Assert.AreEqual(0, socket.Receive(new byte[1])); } }
public void TestGetConnectionWithInvalidSession() { var httpContextMock = helper.CreateTunnelHttpContextMock("GET", sessionType: "invalid"); var tunnelHandlerMock = new Mock <ITunnelHandler>(); TunnelService tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); tunnelService.Handle(tunnelHandlerMock.Object, new TunnelHandleOptions() { CheckLogin = true }); /// 验证是否调用 OnTunnelRequest /// 请求登录的情况下,如果会话无效,应该直接输出会话无效 tunnelHandlerMock.Verify( expression: x => x.OnTunnelRequest( It.IsAny <SDK.Tunnel.Tunnel>(), It.IsAny <SDK.Authorization.UserInfo>() ), times: Times.Never(), failMessage: "意外地调用了 OnTunnelRequest" ); /// 验证是否正确输出申请到的连接地址到客户端 httpContextMock.Verify( expression: x => x.Response.Write( It.Is <string>(content => helper.CheckBodyHasMagicId(JObject.Parse(content))) ), times: Times.Once(), failMessage: "请求 WebSocket 连接没有进行合法的输出" ); }
public void TestPostMessagePacket() { var httpContextMock = helper.CreateTunnelHttpContextMock("POST"); helper.SetupRequestBody(httpContextMock, helper.BuildPacket(new { type = "message", tunnelId = "tunnel1", content = new { type = "test-type", content = "test-content" }.ToJson() }.ToJson())); var tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); var tunnelHandlerMock = new Mock <ITunnelHandler>(); tunnelService.Handle(tunnelHandlerMock.Object); Func <TunnelMessage, bool> IsValidMessage = message => { return(message.Type == "test-type" && message.Content == "test-content"); }; tunnelHandlerMock.Verify( expression: x => x.OnTunnelMessage( It.Is((Tunnel tunnel) => tunnel.Id == "tunnel1"), It.Is((TunnelMessage message) => IsValidMessage(message)) ), times: Times.Once(), failMessage: "接收到关闭数据包之后没有正确调用 OnTunnelClose 事件" ); helper.VerifyHandleResponseSuccess(httpContextMock); }
public void TestGetConnectionWithoutSession() { var httpContextMock = helper.CreateTunnelHttpContextMock("GET", sessionType: null); var tunnelHandlerMock = new Mock <ITunnelHandler>(); TunnelService tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); tunnelService.Handle(tunnelHandlerMock.Object, new TunnelHandleOptions() { CheckLogin = false }); /// 验证是否成功调用 OnTunnelRequest /// 正常获取的时候,信道不为空,并且有 Id 可以进行索引 /// 因为 CheckLogin 配置为 false,所以应该获取不到用户信息 tunnelHandlerMock.Verify( expression: x => x.OnTunnelRequest( It.Is <SDK.Tunnel.Tunnel>(tunnel => tunnel.Id != null), It.Is <SDK.Authorization.UserInfo>(user => user == null) ), times: Times.Once(), failMessage: "没有正确调用 OnTunnelRequest" ); /// 验证是否正确输出申请到的连接地址到客户端 httpContextMock.Verify( expression: x => x.Response.Write( It.Is <string>(content => helper.CheckBodyHasUrl(content)) ), times: Times.Once(), failMessage: "请求 WebSocket 连接没有进行合法的输出" ); }
public void TestPostBadRequest() { var httpContextMock = helper.CreateTunnelHttpContextMock("POST"); helper.SetupRequestBody(httpContextMock, "illegal request"); var tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); var tunnelHandlerMock = new Mock <ITunnelHandler>(); tunnelService.Handle(tunnelHandlerMock.Object); helper.CheckNoMethodIsCalled(tunnelHandlerMock); helper.VerifyHandleResponseFail(httpContextMock); }
public async Task WhenInstanceAvailableAndUserInRole_ThenCreateTunnelAndProbeSucceeds( [WindowsInstance] ResourceTask <InstanceLocator> testInstance, [Credential(Role = PredefinedRole.IapTunnelUser)] ResourceTask <ICredential> credential) { var service = new TunnelService(CreateAuthorizationAdapter( await credential)); var destination = new TunnelDestination( await testInstance, 3389); var tunnel = await service.CreateTunnelAsync(destination); Assert.AreEqual(destination, tunnel.Destination); await tunnel.Probe(TimeSpan.FromSeconds(20)); tunnel.Close(); }
public void TestPostSignatureErrorPacket() { var httpContextMock = helper.CreateTunnelHttpContextMock("POST"); helper.SetupRequestBody(httpContextMock, helper.BuildPacket(new { type = "connect", tunnelId = "tunnel1" }.ToJson(), fakeSignature: true)); var tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); var tunnelHandlerMock = new Mock <ITunnelHandler>(); tunnelService.Handle(tunnelHandlerMock.Object); helper.CheckNoMethodIsCalled(tunnelHandlerMock); helper.VerifyHandleResponseFail(httpContextMock); }
public void TestPostUnknowPacket() { var httpContextMock = helper.CreateTunnelHttpContextMock("POST"); helper.SetupRequestBody(httpContextMock, helper.BuildPacket(new { type = "unknown", tunnelId = "tunnel1" }.ToJson())); var tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); var tunnelHandlerMock = new Mock <ITunnelHandler>(); tunnelService.Handle(tunnelHandlerMock.Object); helper.CheckNoMethodIsCalled(tunnelHandlerMock); helper.VerifyHandleResponseSuccess(httpContextMock); }
public async Task WhenInstanceAvailableButRelayPolicyFails_ThenXxxx( [WindowsInstance] ResourceTask <InstanceLocator> testInstance, [Credential(Role = PredefinedRole.ComputeViewer)] ResourceTask <ICredential> credential) { var service = new TunnelService(CreateAuthorizationAdapter( await credential)); var destination = new TunnelDestination( await testInstance, 3389); var tunnel = await service.CreateTunnelAsync( destination, new DenyAllPolicy()); AssertEx.ThrowsAggregateException <UnauthorizedException>( () => tunnel.Probe(TimeSpan.FromSeconds(20)).Wait()); tunnel.Close(); }
/// <summary> /// GET /tunnel <para /> /// 请求建立隧道连接 <para /> /// /// POST /tunnel <para /> /// 用于信道服务器推送消息到业务服务器 /// </summary> public ActionResult Index() { // 创建信道服务处理信道相关请求 tunnelService = new TunnelService(Request, Response); // 信道服务会自动帮你响应请求,请不要使用 Response 进行二次请求 tunnelService.Handle( // 需要自己实现隧道消息处理器,TunnelHandler 是一个实现的范例,详情请看 TunnelHandler 的实现源码 handler: new ChatTunnelHandler(), // 配置是可选的,配置 CheckLogin 为 true 的话,会在隧道建立之前获取用户信息,以便业务将隧道和用户关联起来 options: new TunnelHandleOptions() { CheckLogin = true } ); // 返回 null 确保 MVC 框架不进行输出 return null; }
public async Task WhenDeviceEnrolled_ThenAuditLogIndicatesDevice( [WindowsInstance] ResourceTask <InstanceLocator> testInstance) { var service = new TunnelService(CreateAuthorizationAdapterForSecureConnectUser()); // Probe a random port so that we have something unique to look for // in the audit log. var randomPort = (ushort)new Random().Next(10000, 50000); var destination = new TunnelDestination( await testInstance, randomPort); using (var tunnel = await service.CreateTunnelAsync( destination, new SameProcessRelayPolicy())) { Assert.AreEqual(destination, tunnel.Destination); Assert.IsTrue(tunnel.IsMutualTlsEnabled); // The probe will fail, but it will leave a record in the audit log. try { await tunnel.Probe(TimeSpan.FromSeconds(5)); } catch (UnauthorizedException) { } } var logs = await GetIapAccessLogsForPortAsync(randomPort); Assert.IsTrue(logs.Any(), "data access log emitted"); var metadata = (JToken)logs.First().ProtoPayload["metadata"]; Assert.AreNotEqual( "Unknown", metadata.Value <string>("device_state")); CollectionAssert.Contains( new[] { "Normal", "Cross Organization" }, metadata.Value <string>("device_state")); }
public async Task WhenInstanceAvailableAndUserInRole_ThenCreateTunnelAndProbeSucceeds( [WindowsInstance] ResourceTask <InstanceLocator> testInstance, [Credential(Role = PredefinedRole.IapTunnelUser)] ResourceTask <ICredential> credential) { var service = new TunnelService(CreateAuthorizationAdapter( await credential, null)); var destination = new TunnelDestination( await testInstance, 3389); using (var tunnel = await service.CreateTunnelAsync( destination, new SameProcessRelayPolicy())) { Assert.AreEqual(destination, tunnel.Destination); Assert.IsFalse(tunnel.IsMutualTlsEnabled); await tunnel.Probe(TimeSpan.FromSeconds(20)); } }
public async Task WhenInstanceAvailableButUserNotInRole_ThenProbeFails( [WindowsInstance] ResourceTask <InstanceLocator> testInstance, [Credential(Role = PredefinedRole.ComputeViewer)] ResourceTask <ICredential> credential) { var service = new TunnelService(CreateAuthorizationAdapter( await credential, null)); var destination = new TunnelDestination( await testInstance, 3389); using (var tunnel = await service.CreateTunnelAsync( destination, new SameProcessRelayPolicy())) { Assert.AreEqual(destination, tunnel.Destination); AssertEx.ThrowsAggregateException <UnauthorizedException>( () => tunnel.Probe(TimeSpan.FromSeconds(20)).Wait()); } }
public async Task WhenInstanceNotAvailable_ThenProbeFails( [Credential(Role = PredefinedRole.ComputeViewer)] ResourceTask <ICredential> credential) { var service = new TunnelService(CreateAuthorizationAdapter( await credential)); var destination = new TunnelDestination( new InstanceLocator( TestProject.ProjectId, "us-central1-a", "nonexistinginstance"), 3389); var tunnel = await service.CreateTunnelAsync(destination); Assert.AreEqual(destination, tunnel.Destination); AssertEx.ThrowsAggregateException <UnauthorizedException>( () => tunnel.Probe(TimeSpan.FromSeconds(20)).Wait()); tunnel.Close(); }
public void TestPostClosePacket() { var httpContextMock = helper.CreateTunnelHttpContextMock("POST"); helper.SetupRequestBody(httpContextMock, helper.BuildPacket(new { type = "close", tunnelId = "tunnel1" }.ToJson())); var tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); var tunnelHandlerMock = new Mock <ITunnelHandler>(); tunnelService.Handle(tunnelHandlerMock.Object); tunnelHandlerMock.Verify( expression: x => x.OnTunnelClose(It.Is((SDK.Tunnel.Tunnel tunnel) => tunnel.Id == "tunnel1")), times: Times.Once(), failMessage: "接收到关闭数据包之后没有正确调用 OnTunnelClose 事件" ); helper.VerifyHandleResponseSuccess(httpContextMock); }
public void TestPostBadNetwork() { var httpContextMock = helper.CreateTunnelHttpContextMock("POST"); httpContextMock.Setup(x => x.Request.InputStream).Throws(new HttpException("Bad Network")); var tunnelService = new TunnelService(httpContextMock.Object.Request, httpContextMock.Object.Response); var tunnelHandlerMock = new Mock <ITunnelHandler>(); Exception errorShouldThrow = null; try { tunnelService.Handle(tunnelHandlerMock.Object); } catch (Exception error) { errorShouldThrow = error; } helper.CheckNoMethodIsCalled(tunnelHandlerMock); Assert.IsNotNull(errorShouldThrow); }