public void GetDevicesAndModulesInTargetDeviceScope_UnauthorizedActorTest()
        {
            string targetEdgeId     = "edge2";
            var    resultIdentities = new List <ServiceIdentity>();
            var    authChainMapping = new Dictionary <string, string>();

            authChainMapping.Add(targetEdgeId, targetEdgeId + ";edge1;edgeroot");
            var controller = MakeController(targetEdgeId, resultIdentities, authChainMapping);

            var request = new NestedScopeRequest(0, string.Empty, "edge2;edge1");

            controller.GetDevicesAndModulesInTargetDeviceScopeAsync("edge1", "notEdgeHub", request).Wait();

            Assert.Equal((int)HttpStatusCode.Unauthorized, controller.HttpContext.Response.StatusCode);
        }
        public async Task HandleDevicesAndModulesInTargetDeviceScopeAsyncTest(
            string actorDeviceId,
            string actorModuleId,
            string authChain,
            string targetDeviceId,
            string authChainToTarget,
            HttpStatusCode expectedStatus)
        {
            // Setup
            var request         = new NestedScopeRequest(1, string.Empty, authChain);
            var identitiesCache = new Mock <IDeviceScopeIdentitiesCache>();

            identitiesCache.Setup(i => i.GetAuthChain(targetDeviceId)).Returns(Task.FromResult(Option.Some(authChainToTarget)));
            identitiesCache.Setup(i => i.GetServiceIdentity(targetDeviceId)).Returns(Task.FromResult(Option.None <ServiceIdentity>()));
            identitiesCache.Setup(i => i.GetDevicesAndModulesInTargetScopeAsync(targetDeviceId)).Returns(Task.FromResult(new List <ServiceIdentity>() as IList <ServiceIdentity>));

            // Act
            EdgeHubScopeResult result = await DeviceScopeController.HandleDevicesAndModulesInTargetDeviceScopeAsync(actorDeviceId, actorModuleId, request, identitiesCache.Object);

            // Verify
            Assert.Equal(expectedStatus, result.Status);
        }
        async Task <ScopeResult> GetIdentitiesInTargetScopeInternalAsync(Uri uri, Option <string> continuationToken)
        {
            HttpClient client = this.proxy
                                .Map(p => new HttpClient(new HttpClientHandler {
                Proxy = p
            }, disposeHandler: true))
                                .GetOrElse(() => new HttpClient());

            client.Timeout = HttpOperationTimeout;
            using (var msg = new HttpRequestMessage(HttpMethod.Post, uri))
            {
                // Get the auth-chain for the target device
                Option <string> maybeAuthChain = await this.serviceIdentityHierarchy.GetAuthChain(this.TargetEdgeDeviceId);

                string authChain = maybeAuthChain.Expect(() => new InvalidOperationException($"No valid authentication chain for {this.TargetEdgeDeviceId}"));

                var    payload = new NestedScopeRequest(this.batchSize, continuationToken.OrDefault(), authChain);
                string token   = await this.edgeHubTokenProvider.GetTokenAsync(Option.None <TimeSpan>());

                msg.Headers.Add(HttpRequestHeader.Authorization.ToString(), token);
                msg.Content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");

                HttpResponseMessage response = await client.SendAsync(msg);

                string content = await response.Content.ReadAsStringAsync();

                if (response.IsSuccessStatusCode)
                {
                    var scopeResult = JsonConvert.DeserializeObject <ScopeResult>(content);
                    Events.GotValidResult();
                    return(scopeResult);
                }
                else
                {
                    throw new DeviceScopeApiException("Error getting device scope result from upstream", response.StatusCode, content);
                }
            }
        }
        public async Task GetDevicesAndModulesInTargetDeviceScope_RoundTripTest()
        {
            // Setup ServiceIdentity results
            string parentEdgeId         = "edge1";
            string childEdgeId          = "edge2";
            string deviceId             = "device1";
            string moduleId             = "module1";
            string deviceScope          = "deviceScope1";
            string parentScope          = "parentScope1";
            string generationId         = "generation1";
            string primaryKey           = "t3LtII3CppvtVqycKp9bo043vCEgWbGBJAzXZNmoBXo=";
            string secondaryKey         = "kT4ac4PpH5UY0vA1JpLQWOu2yG6qKoqwvzee3j1Z3bA=";
            var    authentication       = new ServiceAuthentication(new SymmetricKeyAuthentication(primaryKey, secondaryKey));
            var    resultDeviceIdentity = new ServiceIdentity(deviceId, null, deviceScope, new List <string>()
            {
                parentScope
            }, generationId, Enumerable.Empty <string>(), authentication, ServiceIdentityStatus.Enabled);
            var resultModuleIdentity = new ServiceIdentity(deviceId, moduleId, null, new List <string>()
            {
                deviceScope
            }, generationId, Enumerable.Empty <string>(), authentication, ServiceIdentityStatus.Enabled);
            var resultIdentities = new List <ServiceIdentity>()
            {
                resultDeviceIdentity, resultModuleIdentity
            };
            var authChainMapping = new Dictionary <string, string>();

            authChainMapping.Add(childEdgeId, "edge2;edge1;edgeroot");
            var controller = MakeController(childEdgeId, resultIdentities, authChainMapping);

            // Act
            var request = new NestedScopeRequest(0, string.Empty, "edge2;edge1");
            await controller.GetDevicesAndModulesInTargetDeviceScopeAsync(parentEdgeId, "$edgeHub", request);

            // Verify EdgeHub result types
            var expectedAuth = new AuthenticationMechanism()
            {
                SymmetricKey = new SymmetricKey()
                {
                    PrimaryKey = primaryKey, SecondaryKey = secondaryKey
                }
            };
            var expectedDeviceIdentities = new List <EdgeHubScopeDevice>()
            {
                new EdgeHubScopeDevice(deviceId, generationId, DeviceStatus.Enabled, expectedAuth, new DeviceCapabilities(), deviceScope, new List <string> {
                    parentScope
                })
            };
            var expectedModuleIdentities = new List <EdgeHubScopeModule>()
            {
                new EdgeHubScopeModule(moduleId, deviceId, generationId, expectedAuth)
            };
            var responseExpected     = new EdgeHubScopeResultSuccess(expectedDeviceIdentities, expectedModuleIdentities);
            var responseExpectedJson = JsonConvert.SerializeObject(responseExpected);

            var responseActualBytes = GetResponseBodyBytes(controller);
            var responseActualJson  = Encoding.UTF8.GetString(responseActualBytes);

            Assert.Equal((int)HttpStatusCode.OK, controller.HttpContext.Response.StatusCode);
            Assert.Equal(responseExpectedJson, responseActualJson);

            // Deserialize JSON back to SDK result types
            var scopeResult = JsonConvert.DeserializeObject <ScopeResult>(responseActualJson);

            // Convert to original ServiceIdentity type
            Assert.Equal(1, (int)scopeResult.Devices.Count());
            Assert.Equal(1, (int)scopeResult.Modules.Count());
            ServiceIdentity device = scopeResult.Devices.First().ToServiceIdentity();
            ServiceIdentity module = scopeResult.Modules.First().ToServiceIdentity();

            Assert.Equal(resultDeviceIdentity, device);
            Assert.Equal(resultModuleIdentity, module);
        }
示例#5
0
        public async Task GetDevicesAndModulesInTargetDeviceScopeAsync([FromRoute] string actorDeviceId, [FromRoute] string actorModuleId, [FromBody] NestedScopeRequest request)
        {
            actorDeviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorDeviceId, nameof(actorDeviceId)));
            actorModuleId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorModuleId, nameof(actorModuleId)));
            Preconditions.CheckNonWhiteSpace(request.AuthChain, nameof(request.AuthChain));

            if (actorModuleId != Constants.EdgeHubModuleId)
            {
                // Only child EdgeHubs are allowed to act OnBehalfOf of devices/modules.
                var result = new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, Events.UnauthorizedActor(actorDeviceId, actorModuleId));
                await this.SendResponse(result.Status, JsonConvert.SerializeObject(result));
            }

            string authChain = request.AuthChain;

            string[] ids = AuthChainHelpers.GetAuthChainIds(authChain);
            if (ids.Length == 1)
            {
                // A child EdgeHub can use its module credentials to calls upstream
                // OnBehalfOf its device identity, so the auth-chain would just have
                // one element denoting the target device scope but no actor.
                // However, the auth stack requires an actor to be specified for OnBehalfOf
                // connections, so we manually add the actor to the auth-chain for this
                // special case.
                authChain = $"{ids[0]}/{Constants.EdgeHubModuleId};{ids[0]}";
            }

            IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
            HttpAuthResult            authResult    = await authenticator.AuthenticateAsync(actorDeviceId, Option.Some(actorModuleId), Option.Some(authChain), this.HttpContext);

            if (authResult.Authenticated)
            {
                EdgeHubScopeResult reqResult = await this.HandleDevicesAndModulesInTargetDeviceScopeAsync(actorDeviceId, actorModuleId, request);

                await this.SendResponse(reqResult.Status, JsonConvert.SerializeObject(reqResult));
            }
            else
            {
                var result = new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, authResult.ErrorMessage);
                await this.SendResponse(result.Status, JsonConvert.SerializeObject(result));
            }
        }
示例#6
0
 public static void ReceivedScopeRequest(string actorDeviceId, string actorModuleId, NestedScopeRequest request)
 {
     Log.LogInformation((int)EventIds.ReceivedScopeRequest, $"Received get scope request: actorId: {actorDeviceId}/{actorModuleId}, authChain: {request.AuthChain}, continuationLink: {request.ContinuationLink}, pageSize: {request.PageSize}");
 }
示例#7
0
        async Task <EdgeHubScopeResult> HandleDevicesAndModulesInTargetDeviceScopeAsync(string actorDeviceId, string actorModuleId, NestedScopeRequest request)
        {
            Events.ReceivedScopeRequest(actorDeviceId, actorModuleId, request);

            if (!AuthChainHelpers.TryGetTargetDeviceId(request.AuthChain, out string targetDeviceId))
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.BadRequest, Events.InvalidRequestAuthchain(request.AuthChain)));
            }

            // Get the children of the target device and the target device itself;
            IEdgeHub edgeHub = await this.edgeHubGetter;
            IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
            IList <ServiceIdentity>     identities      = await identitiesCache.GetDevicesAndModulesInTargetScopeAsync(targetDeviceId);

            Option <ServiceIdentity> targetDevice = await identitiesCache.GetServiceIdentity(targetDeviceId);

            targetDevice.ForEach(d => identities.Add(d));

            // Construct the result from the identities
            Events.SendingScopeResult(targetDeviceId, identities);
            return(MakeResultFromIdentities(identities));
        }
示例#8
0
        async Task <EdgeHubScopeResult> HandleDevicesAndModulesInTargetDeviceScopeAsync(string actorDeviceId, string actorModuleId, NestedScopeRequest request)
        {
            Events.ReceivedScopeRequest(actorDeviceId, actorModuleId, request);
            Preconditions.CheckNonWhiteSpace(request.AuthChain, nameof(request.AuthChain));

            if (!this.TryGetTargetDeviceId(request.AuthChain, out string targetDeviceId))
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.BadRequest, Events.InvalidRequestAuthchain(request.AuthChain)));
            }

            // Check that the actor device is authorized to act OnBehalfOf the target
            IEdgeHub edgeHub = await this.edgeHubGetter;
            IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();

            if (!await this.AuthorizeActorAsync(identitiesCache, actorDeviceId, actorModuleId, targetDeviceId))
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, Events.UnauthorizedActor(actorDeviceId, actorModuleId, targetDeviceId)));
            }

            // Get the children of the target device and the target device itself;
            IList <ServiceIdentity> identities = await identitiesCache.GetDevicesAndModulesInTargetScopeAsync(targetDeviceId);

            Option <ServiceIdentity> targetDevice = await identitiesCache.GetServiceIdentity(targetDeviceId);

            targetDevice.ForEach(d => identities.Add(d));

            // Construct the result from the identities
            Events.SendingScopeResult(targetDeviceId, identities);
            return(MakeResultFromIdentities(identities));
        }
示例#9
0
        public async Task GetDevicesAndModulesInTargetDeviceScopeAsync([FromRoute] string actorDeviceId, [FromRoute] string actorModuleId, [FromBody] NestedScopeRequest request)
        {
            actorDeviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorDeviceId, nameof(actorDeviceId)));
            actorModuleId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorModuleId, nameof(actorModuleId)));

            IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
            HttpAuthResult            authResult    = await authenticator.AuthenticateAsync(actorDeviceId, Option.Some(actorModuleId), this.HttpContext);

            if (authResult.Authenticated)
            {
                EdgeHubScopeResult reqResult = await this.HandleDevicesAndModulesInTargetDeviceScopeAsync(actorDeviceId, actorModuleId, request);

                await this.SendResponse(reqResult.Status, JsonConvert.SerializeObject(reqResult));
            }
            else
            {
                var result = new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, authResult.ErrorMessage);
                await this.SendResponse(result.Status, JsonConvert.SerializeObject(result));
            }
        }
示例#10
0
        internal static async Task <EdgeHubScopeResult> HandleDevicesAndModulesInTargetDeviceScopeAsync(string actorDeviceId, string actorModuleId, NestedScopeRequest request, IDeviceScopeIdentitiesCache identitiesCache)
        {
            Events.ReceivedScopeRequest(actorDeviceId, actorModuleId, request);

            if (!AuthChainHelpers.TryGetTargetDeviceId(request.AuthChain, out string targetDeviceId))
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.BadRequest, Events.InvalidRequestAuthchain(request.AuthChain)));
            }

            // Get the children of the target device and the target device itself;
            Option <string> authChainToTarget = await identitiesCache.GetAuthChain(targetDeviceId);

            (bool validationResult, string errorMsg) = ValidateAuthChainForRequestor(actorDeviceId, targetDeviceId, authChainToTarget);
            if (!validationResult)
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, errorMsg));
            }

            IList <ServiceIdentity> identities = await identitiesCache.GetDevicesAndModulesInTargetScopeAsync(targetDeviceId);

            Option <ServiceIdentity> targetDevice = await identitiesCache.GetServiceIdentity(targetDeviceId);

            targetDevice.ForEach(d => identities.Add(d));

            // Construct the result from the identities
            Events.SendingScopeResult(targetDeviceId, identities);
            return(MakeResultFromIdentities(identities));
        }
示例#11
0
        public async Task GetDevicesAndModulesInTargetDeviceScopeAsync([FromRoute] string actorDeviceId, [FromRoute] string actorModuleId, [FromBody] NestedScopeRequest request)
        {
            actorDeviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorDeviceId, nameof(actorDeviceId)));
            actorModuleId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorModuleId, nameof(actorModuleId)));
            Preconditions.CheckNonWhiteSpace(request.AuthChain, nameof(request.AuthChain));

            if (actorModuleId != Constants.EdgeHubModuleId)
            {
                // Only child EdgeHubs are allowed to act OnBehalfOf of devices/modules.
                var result = new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, Events.UnauthorizedActor(actorDeviceId, actorModuleId));
                await this.SendResponse(result.Status, JsonConvert.SerializeObject(result));
            }

            IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
            HttpAuthResult            authResult    = await authenticator.AuthenticateAsync(actorDeviceId, Option.Some(actorModuleId), Option.Some(request.AuthChain), this.HttpContext);

            if (authResult.Authenticated)
            {
                IEdgeHub edgeHub = await this.edgeHubGetter;
                IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
                EdgeHubScopeResult          reqResult       = await HandleDevicesAndModulesInTargetDeviceScopeAsync(actorDeviceId, actorModuleId, request, identitiesCache);

                await this.SendResponse(reqResult.Status, JsonConvert.SerializeObject(reqResult));
            }
            else
            {
                var result = new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, authResult.ErrorMessage);
                await this.SendResponse(result.Status, JsonConvert.SerializeObject(result));
            }
        }