Exemple #1
0
        async Task <bool> AuthorizeActorAsync(IDeviceScopeIdentitiesCache identitiesCache, string actorDeviceId, string actorModuleId, string targetId)
        {
            if (actorModuleId != Constants.EdgeHubModuleId)
            {
                // Only child EdgeHubs are allowed to act OnBehalfOf of devices/modules.
                Events.AuthFail_BadActor(actorDeviceId, actorModuleId, targetId);
                return(false);
            }

            // Actor device is claiming to be our child, and that the target device is its child.
            // So we should have an authchain already cached for the target device.
            Option <string> targetAuthChainOption = await identitiesCache.GetAuthChain(targetId);

            if (!targetAuthChainOption.HasValue)
            {
                Events.AuthFail_NoAuthChain(targetId);
                return(false);
            }

            // Validate the target auth-chain
            string targetAuthChain = targetAuthChainOption.Expect(() => new InvalidOperationException());

            if (!AuthChainHelpers.ValidateAuthChain(actorDeviceId, targetId, targetAuthChain))
            {
                Events.AuthFail_InvalidAuthChain(actorDeviceId, targetId, targetAuthChain);
                return(false);
            }

            return(true);
        }
Exemple #2
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));
        }
Exemple #3
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()));
            }
        }
Exemple #4
0
        static async Task <IList <BrokerServiceIdentity> > ConvertIdsToBrokerServiceIdentities(IList <string> ids, IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache)
        {
            IList <BrokerServiceIdentity> brokerServiceIdentities = new List <BrokerServiceIdentity>();

            foreach (string id in ids)
            {
                brokerServiceIdentities.Add(
                    new BrokerServiceIdentity(id, await deviceScopeIdentitiesCache.GetAuthChain(id)));
            }

            return(brokerServiceIdentities);
        }
Exemple #5
0
        internal static async Task <Try <string> > AuthorizeOnBehalfOf(
            string actorDeviceId,
            string authChain,
            string source,
            HttpContext httpContext,
            IEdgeHub edgeHub,
            IHttpRequestAuthenticator authenticator)
        {
            if (!AuthChainHelpers.TryGetTargetDeviceId(authChain, out string targetDeviceId))
            {
                Events.InvalidRequestAuthChain(source, authChain);
                return(Try <string> .Failure(new ValidationException(HttpStatusCode.BadRequest, FormatErrorResponseMessage($"Invalid request auth chain {authChain}."))));
            }

            if (!await AuthenticateAsync(actorDeviceId, Option.Some(Constants.EdgeHubModuleId), Option.Some(authChain), httpContext, authenticator))
            {
                return(Try <string> .Failure(new ValidationException(HttpStatusCode.Unauthorized)));
            }

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

            return(targetAuthChain.Match(
                       ac =>
            {
                if (!AuthChainHelpers.ValidateAuthChain(actorDeviceId, targetDeviceId, ac))
                {
                    Events.AuthorizationFail_InvalidAuthChain(actorDeviceId, targetDeviceId, ac);
                    return Try <string> .Failure(new ValidationException(HttpStatusCode.Unauthorized));
                }

                return ac;
            },
                       () =>
            {
                Events.AuthorizationFail_NoAuthChain(targetDeviceId);
                return Try <string> .Failure(new ValidationException(HttpStatusCode.Unauthorized));
            }));
        }
Exemple #6
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()));
            }
        }
Exemple #7
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()));
            }
        }
Exemple #8
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()));
            }
        }