public async Task GetModuleOnBehalfOf()
        {
            // Setup ServiceIdentity results
            string parentEdgeId         = "edge1";
            string childEdgeId          = "edge2";
            string moduleId             = "module1";
            string deviceScope          = "deviceScope1";
            string parentScope          = "parentScope1";
            string generationId         = "generation1";
            var    authentication       = new ServiceAuthentication(new SymmetricKeyAuthentication(this.primaryKey, this.secondaryKey));
            var    resultDeviceIdentity = new ServiceIdentity(childEdgeId, null, deviceScope, new List <string>()
            {
                parentScope
            }, generationId, Enumerable.Empty <string>(), authentication, ServiceIdentityStatus.Enabled);
            var resultModuleIdentity = new ServiceIdentity(childEdgeId, 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>();
            string targetId         = childEdgeId + "/" + moduleId;

            authChainMapping.Add(targetId, $"{targetId};{childEdgeId};{parentEdgeId};edgeroot");
            var controller = MakeController(childEdgeId, resultIdentities, authChainMapping);

            // Act
            controller.Request.Headers.Add(Constants.OriginEdgeHeaderKey, $"{childEdgeId}");
            var request = new IdentityOnBehalfOfRequest(childEdgeId, moduleId, $"{childEdgeId};{parentEdgeId}");
            await controller.GetDeviceAndModuleOnBehalfOfAsync(parentEdgeId, "$edgeHub", request);

            // Verify EdgeHub result types
            var expectedAuth = new AuthenticationMechanism()
            {
                SymmetricKey = new SymmetricKey()
                {
                    PrimaryKey = this.primaryKey, SecondaryKey = this.secondaryKey
                }
            };
            var expectedDeviceIdentities = new List <EdgeHubScopeDevice>()
            {
                new EdgeHubScopeDevice(childEdgeId, generationId, DeviceStatus.Enabled, expectedAuth, new DeviceCapabilities(), deviceScope, new List <string> {
                    parentScope
                })
            };
            var expectedModuleIdentities = new List <EdgeHubScopeModule>()
            {
                new EdgeHubScopeModule(moduleId, childEdgeId, 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);
        }
Exemplo n.º 2
0
        public async Task HandleGetDeviceAndModuleOnBehalfOfAsync(
            string actorDeviceId,
            string actorModuleId,
            string targetDeviceId,
            string targetModuleId,
            string authChain,
            string originatorDeviceId,
            string authChainToTarget,
            HttpStatusCode expectedStatus)
        {
            // Setup
            var    request         = new IdentityOnBehalfOfRequest(targetDeviceId, targetModuleId, authChain);
            var    identitiesCache = new Mock <IDeviceScopeIdentitiesCache>();
            string targetId        = targetDeviceId + (string.IsNullOrWhiteSpace(targetModuleId) ? string.Empty : $"/{targetModuleId}");

            identitiesCache.Setup(i => i.RefreshServiceIdentityOnBehalfOf(targetId, originatorDeviceId)).Returns(Task.CompletedTask);
            var targetServiceIdentity = new ServiceIdentity(targetId, "dummy", Enumerable.Empty <string>(), new ServiceAuthentication(ServiceAuthenticationType.None), ServiceIdentityStatus.Enabled);

            identitiesCache.Setup(i => i.GetServiceIdentity(targetId)).Returns(Task.FromResult(Option.Some(targetServiceIdentity)));
            identitiesCache.Setup(i => i.GetAuthChain(targetId)).Returns(Task.FromResult(Option.Some(authChainToTarget)));

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

            // Verity
            Assert.Equal(expectedStatus, edgeHubScopeResult.Status);
        }
Exemplo n.º 3
0
        async Task <ScopeResult> GetIdentityOnBehalfOfInternalAsync(Uri uri, string deviceId, Option <string> moduleId, string onBehalfOfDevice)
        {
            HttpClient client = this.proxy
                                .Map(p => new HttpClient(new HttpClientHandler {
                Proxy = p
            }, disposeHandler: true))
                                .GetOrElse(() => new HttpClient());

            using (var msg = new HttpRequestMessage(HttpMethod.Post, uri))
            {
                // Get the auth-chain for the EdgeHub we're acting OnBehalfOf
                string          onBehalfOfEdgeHub = $"{onBehalfOfDevice}/{Constants.EdgeHubModuleId}";
                Option <string> maybeAuthChain    = await this.serviceIdentityHierarchy.GetEdgeAuthChain(onBehalfOfEdgeHub);

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

                // We must pass the origin Edge ID along upstream, so the root
                // can know which Edge to act OnBehalfOf when calling IoT Hub
                msg.Headers.Add(Constants.OriginEdgeHeaderKey, onBehalfOfDevice);

                var    payload = new IdentityOnBehalfOfRequest(deviceId, moduleId.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);
                }
            }
        }
Exemplo n.º 4
0
        public async Task GetDeviceAndModuleOnBehalfOfAsync([FromRoute] string actorDeviceId, [FromRoute] string actorModuleId, [FromBody] IdentityOnBehalfOfRequest 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)
            {
                EdgeHubScopeResult reqResult = await this.HandleGetDeviceAndModuleOnBehalfOfAsync(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));
            }
        }
Exemplo n.º 5
0
 public static void ReceivedIdentityOnBehalfOfRequest(string actorDeviceId, string actorModuleId, IdentityOnBehalfOfRequest request)
 {
     Log.LogInformation((int)EventIds.ReceivedIdentityOnBehalfOfRequest, $"Received get scope request: actorId: {actorDeviceId}/{actorModuleId}, authChain: {request.AuthChain}, targetDevice: {request.TargetDeviceId}, targetModule: {request.TargetModuleId}");
 }
Exemplo n.º 6
0
        async Task <EdgeHubScopeResult> HandleGetDeviceAndModuleOnBehalfOfAsync(string actorDeviceId, string actorModuleId, IdentityOnBehalfOfRequest request)
        {
            Events.ReceivedIdentityOnBehalfOfRequest(actorDeviceId, actorModuleId, request);
            Preconditions.CheckNonWhiteSpace(request.TargetDeviceId, nameof(request.TargetDeviceId));

            bool   isModule = false;
            string targetId = request.TargetDeviceId;

            if (!request.TargetModuleId.IsNullOrWhiteSpace())
            {
                isModule  = true;
                targetId += "/" + request.TargetModuleId;
            }

            IEdgeHub edgeHub = await this.edgeHubGetter;

            // Check if the actor has provided the originating EdgeHub ID,
            // if not, then we must be by definition by the origin.
            string originatingEdge = edgeHub.GetEdgeDeviceId();

            if (this.Request.Headers.TryGetValue(Constants.OriginEdgeHeaderKey, out StringValues originHeader) && originHeader.Count > 0)
            {
                originatingEdge = originHeader.First();
            }

            // We must always forward the call further upstream first,
            // as this is invoked for refreshing an identity on-demand,
            // and we don't know whether our cache is out-of-date.
            IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
            await identitiesCache.RefreshServiceIdentityOnBehalfOf(targetId, originatingEdge);

            Option <ServiceIdentity> targetIdentity = await identitiesCache.GetServiceIdentity(targetId);

            if (!targetIdentity.HasValue)
            {
                // Identity still doesn't exist, this can happen if the identity
                // is newly added and we couldn't refresh the individual identity
                // because we don't know where it resides in the nested hierarchy.
                // In this case our only recourse is to refresh the whole cache
                // and hope the identity shows up.
                identitiesCache.InitiateCacheRefresh();
                await identitiesCache.WaitForCacheRefresh(TimeSpan.FromSeconds(100));

                targetIdentity = await identitiesCache.GetServiceIdentity(targetId);
            }

            // Add the identity to the result
            var identityList = new List <ServiceIdentity>();

            targetIdentity.ForEach(i => identityList.Add(i));

            // If the target is a module, we also need to
            // include the parent device as well to match
            // IoT Hub API behavior
            if (isModule)
            {
                Option <ServiceIdentity> device = await identitiesCache.GetServiceIdentity(request.TargetDeviceId);

                device.ForEach(i => identityList.Add(i));
            }

            Events.SendingScopeResult(targetId, identityList);
            return(MakeResultFromIdentities(identityList));
        }