示例#1
0
        public async Task DeleteModuleAsync(
            [FromRoute] string deviceId,
            [FromRoute] string moduleId)
        {
            try
            {
                Events.ReceivedRequest(nameof(this.DeleteModuleAsync), deviceId, moduleId);

                try
                {
                    deviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)));
                    moduleId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId)));
                }
                catch (Exception ex)
                {
                    Events.BadRequest(nameof(this.DeleteModuleAsync), ex.Message);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(ex.Message));

                    return;
                }

                IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
                if (!await AuthenticateAsync(deviceId, Option.None <string>(), Option.None <string>(), this.HttpContext, authenticator))
                {
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                IEdgeHub edgeHub = await this.edgeHubGetter;
                IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
                Option <string>             targetAuthChain = await identitiesCache.GetAuthChain(deviceId);

                if (!targetAuthChain.HasValue)
                {
                    Events.AuthorizationFail_NoAuthChain(deviceId);
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                string edgeDeviceId          = edgeHub.GetEdgeDeviceId();
                var    requestData           = new DeleteModuleOnBehalfOfData($"{targetAuthChain.OrDefault()}", moduleId);
                RegistryApiHttpResult result = await this.apiClient.DeleteModuleAsync(edgeDeviceId, requestData);

                await this.SendResponseAsync(result.StatusCode, result.JsonContent);

                Events.CompleteRequest(nameof(this.DeleteModuleAsync), edgeDeviceId, requestData.AuthChain, result);
            }
            catch (Exception ex)
            {
                Events.InternalServerError(nameof(this.DeleteModuleAsync), ex);
                await this.SendResponseAsync(HttpStatusCode.InternalServerError, FormatErrorResponseMessage(ex.ToString()));
            }
        }
示例#2
0
        public async Task CreateOrUpdateModuleOnBehalfOfAsync(
            [FromRoute] string actorDeviceId,
            [FromHeader(Name = "if-match")] string ifMatchHeader,
            [FromBody] CreateOrUpdateModuleOnBehalfOfData requestData)
        {
            try
            {
                Events.ReceivedOnBehalfOfRequest(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), actorDeviceId, Events.GetAdditionalInfo(requestData));

                try
                {
                    Preconditions.CheckNonWhiteSpace(actorDeviceId, nameof(actorDeviceId));
                    Preconditions.CheckNotNull(requestData, nameof(requestData));
                    Preconditions.CheckNonWhiteSpace(requestData.AuthChain, nameof(requestData.AuthChain));
                    Preconditions.CheckNotNull(requestData.Module, nameof(requestData.Module));
                }
                catch (Exception ex)
                {
                    Events.BadRequest(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), ex.Message);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(ex.ToString()));

                    return;
                }

                actorDeviceId = WebUtility.UrlDecode(actorDeviceId);
                IEdgeHub edgeHub = await this.edgeHubGetter;
                IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
                Try <string> targetAuthChainTry         = await AuthorizeOnBehalfOf(actorDeviceId, requestData.AuthChain, nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), this.HttpContext, edgeHub, authenticator);

                if (targetAuthChainTry.Success)
                {
                    string targetAuthChain       = targetAuthChainTry.Value;
                    string edgeDeviceId          = edgeHub.GetEdgeDeviceId();
                    RegistryApiHttpResult result = await this.apiClient.PutModuleAsync(
                        edgeDeviceId,
                        new CreateOrUpdateModuleOnBehalfOfData($"{targetAuthChain}", requestData.Module),
                        ifMatchHeader);

                    await this.SendResponseAsync(result.StatusCode, result.JsonContent);

                    Events.CompleteRequest(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), edgeDeviceId, targetAuthChain, result);
                }
                else
                {
                    await this.SendErrorResponse(targetAuthChainTry.Exception);
                }
            }
            catch (Exception ex)
            {
                Events.InternalServerError(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), ex);
                await this.SendResponseAsync(HttpStatusCode.InternalServerError, FormatErrorResponseMessage(ex.ToString()));
            }
        }
示例#3
0
        async Task <MethodResult> InvokeMethodAsync(DirectMethodRequest directMethodRequest)
        {
            Events.ReceivedMethodCall(directMethodRequest);
            IEdgeHub edgeHub = await this.edgeHubGetter;

            MethodResult methodResult;
            string       currentEdgeDeviceId = edgeHub.GetEdgeDeviceId();

            if (this.TryGetActorId(out string actorDeviceId, out string actorModuleId))
            {
                string actorId = $"{actorDeviceId}/{actorModuleId}";

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

                    if (authResult.Authenticated)
                    {
                        using (Metrics.TimeDirectMethod(actorDeviceId, directMethodRequest.Id))
                        {
                            DirectMethodResponse directMethodResponse = await edgeHub.InvokeMethodAsync(actorId, directMethodRequest);

                            Events.ReceivedMethodCallResponse(directMethodRequest, actorId);

                            methodResult = GetMethodResult(directMethodResponse);
                        }
                    }
                    else
                    {
                        methodResult = new MethodErrorResult(HttpStatusCode.Unauthorized, authResult.ErrorMessage);
                    }
                }
                else
                {
                    methodResult = new MethodErrorResult(HttpStatusCode.Unauthorized, "Only modules on the same device can invoke DirectMethods");
                }
            }
            else
            {
                methodResult = new MethodErrorResult(HttpStatusCode.BadRequest, $"Invalid header value for {Constants.ServiceApiIdHeaderKey}");
            }

            return(methodResult);
        }
示例#4
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));
        }
示例#5
0
        public async Task CreateOrUpdateModuleAsync(
            [FromRoute] string deviceId,
            [FromRoute] string moduleId,
            [FromHeader(Name = "if-match")] string ifMatchHeader,
            [FromBody] Module module)
        {
            try
            {
                Events.ReceivedRequest(nameof(this.CreateOrUpdateModuleAsync), deviceId, moduleId);

                try
                {
                    deviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)));
                    moduleId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId)));
                    Preconditions.CheckNotNull(module, nameof(module));

                    if (!string.Equals(deviceId, module.DeviceId) || !string.Equals(moduleId, module.Id))
                    {
                        throw new ApplicationException("Device Id or module Id doesn't match between request URI and body.");
                    }
                }
                catch (Exception ex)
                {
                    Events.BadRequest(nameof(this.CreateOrUpdateModuleAsync), ex.Message);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(ex.Message));

                    return;
                }

                IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
                if (!await AuthenticateAsync(deviceId, Option.None <string>(), Option.None <string>(), this.HttpContext, authenticator))
                {
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                IEdgeHub edgeHub = await this.edgeHubGetter;
                IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
                Option <string>             targetAuthChain = await identitiesCache.GetAuthChain(deviceId);

                if (!targetAuthChain.HasValue)
                {
                    Events.AuthorizationFail_NoAuthChain(deviceId);
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                string edgeDeviceId          = edgeHub.GetEdgeDeviceId();
                var    requestData           = new CreateOrUpdateModuleOnBehalfOfData($"{targetAuthChain.OrDefault()}", module);
                RegistryApiHttpResult result = await this.apiClient.PutModuleAsync(edgeDeviceId, requestData, ifMatchHeader);

                await this.SendResponseAsync(result.StatusCode, result.JsonContent);

                Events.CompleteRequest(nameof(this.CreateOrUpdateModuleAsync), edgeDeviceId, requestData.AuthChain, result);
            }
            catch (Exception ex)
            {
                Events.InternalServerError(nameof(this.CreateOrUpdateModuleAsync), ex);
                await this.SendResponseAsync(HttpStatusCode.InternalServerError, FormatErrorResponseMessage(ex.ToString()));
            }
        }
示例#6
0
        public async Task ListModulesAsync(
            [FromRoute] string deviceId)
        {
            try
            {
                Events.ReceivedRequest(nameof(this.ListModulesAsync), deviceId);

                if (!this.HttpContext.Request.Query.ContainsKey("api-version"))
                {
                    Dictionary <string, string> headers = new Dictionary <string, string>();
                    headers.Add("iothub-errorcode", "InvalidProtocolVersion");
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, headers, string.Empty);

                    return;
                }

                try
                {
                    deviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)));
                }
                catch (Exception ex)
                {
                    Events.BadRequest(nameof(this.ListModulesAsync), ex.Message);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(ex.Message));

                    return;
                }

                IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
                if (!await AuthenticateAsync(deviceId, Option.None <string>(), Option.None <string>(), this.HttpContext, authenticator))
                {
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                IEdgeHub edgeHub = await this.edgeHubGetter;
                IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
                Option <string>             targetAuthChain = await identitiesCache.GetAuthChain(deviceId);

                if (!targetAuthChain.HasValue)
                {
                    Events.AuthorizationFail_NoAuthChain(deviceId);
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                string edgeDeviceId          = edgeHub.GetEdgeDeviceId();
                var    requestData           = new ListModulesOnBehalfOfData($"{targetAuthChain.OrDefault()}");
                RegistryApiHttpResult result = await this.apiClient.ListModulesAsync(edgeDeviceId, requestData);

                await this.SendResponseAsync(result.StatusCode, result.JsonContent);

                Events.CompleteRequest(nameof(this.ListModulesAsync), edgeDeviceId, requestData.AuthChain, result);
            }
            catch (Exception ex)
            {
                Events.InternalServerError(nameof(this.ListModulesAsync), ex);
                await this.SendResponseAsync(HttpStatusCode.InternalServerError, FormatErrorResponseMessage(ex.ToString()));
            }
        }
示例#7
0
        public async Task DeleteModuleOnBehalfOfAsync(
            [FromRoute] string actorDeviceId,
            [FromBody] DeleteModuleOnBehalfOfData requestData)
        {
            try
            {
                Events.ReceivedOnBehalfOfRequest(nameof(this.DeleteModuleOnBehalfOfAsync), actorDeviceId, Events.GetAdditionalInfo(requestData));

                try
                {
                    Preconditions.CheckNonWhiteSpace(actorDeviceId, nameof(actorDeviceId));
                    Preconditions.CheckNotNull(requestData, nameof(requestData));
                    Preconditions.CheckNonWhiteSpace(requestData.AuthChain, nameof(requestData.AuthChain));
                    Preconditions.CheckNonWhiteSpace(requestData.ModuleId, nameof(requestData.ModuleId));
                }
                catch (Exception ex)
                {
                    Events.BadRequest(nameof(this.DeleteModuleOnBehalfOfAsync), ex.Message);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(ex.ToString()));

                    return;
                }

                actorDeviceId = WebUtility.UrlDecode(actorDeviceId);

                if (!AuthChainHelpers.TryGetTargetDeviceId(requestData.AuthChain, out string targetDeviceId))
                {
                    Events.InvalidRequestAuthChain(nameof(this.DeleteModuleOnBehalfOfAsync), requestData.AuthChain);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage($"Invalid request auth chain {requestData.AuthChain}."));

                    return;
                }

                if (!await this.AuthenticateAsync(actorDeviceId, Option.Some(Constants.EdgeHubModuleId), Option.Some(requestData.AuthChain)))
                {
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                IEdgeHub edgeHub = await this.edgeHubGetter;
                IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
                Option <string>             targetAuthChain = await identitiesCache.GetAuthChain(targetDeviceId);

                if (!targetAuthChain.HasValue)
                {
                    Events.AuthorizationFail_NoAuthChain(targetDeviceId);
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                string edgeDeviceId          = edgeHub.GetEdgeDeviceId();
                RegistryApiHttpResult result = await this.apiClient.DeleteModuleAsync(
                    edgeDeviceId,
                    new DeleteModuleOnBehalfOfData($"{targetAuthChain.OrDefault()}", requestData.ModuleId));

                await this.SendResponseAsync(result.StatusCode, result.JsonContent);

                Events.CompleteRequest(nameof(this.DeleteModuleOnBehalfOfAsync), edgeDeviceId, targetAuthChain.OrDefault(), result);
            }
            catch (Exception ex)
            {
                Events.InternalServerError(nameof(this.DeleteModuleOnBehalfOfAsync), ex);
                await this.SendResponseAsync(HttpStatusCode.InternalServerError, FormatErrorResponseMessage(ex.ToString()));
            }
        }