Exemple #1
0
        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();
        }
Exemple #10
0
        /// <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"));
        }
Exemple #12
0
        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));
            }
        }
Exemple #13
0
        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);
        }