Beispiel #1
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()));
            }
        }
        public async Task CreateOrUpdateModule_Success()
        {
            // Setup
            var authChainMapping = new Dictionary <string, string>()
            {
                { ChildEdgeId, AuthChainOnParent }
            };

            (RegistryController controller, Mock <IRegistryOnBehalfOfApiClient> registryApiClient, Mock <IHttpRequestAuthenticator> authenticator, Mock <IDeviceScopeIdentitiesCache> _) =
                this.TestSetup(ParentEdgeId, authChainMapping);
            CreateOrUpdateModuleOnBehalfOfData actualRequestData = null;
            var module = new Module(ChildEdgeId, ModuleId);

            registryApiClient.Setup(c => c.PutModuleAsync(ParentEdgeId, It.IsAny <CreateOrUpdateModuleOnBehalfOfData>(), It.IsAny <string>()))
            .Callback <string, CreateOrUpdateModuleOnBehalfOfData, string>((_, data, __) => actualRequestData = data)
            .Returns(Task.FromResult(new RegistryApiHttpResult(HttpStatusCode.OK, JsonConvert.SerializeObject(module))));
            authenticator.Setup(a => a.AuthenticateAsync(ChildEdgeId, Option.None <string>(), Option.None <string>(), It.IsAny <HttpContext>()))
            .ReturnsAsync(new HttpAuthResult(true, string.Empty));

            // Act
            await controller.CreateOrUpdateModuleAsync(ChildEdgeId, ModuleId, "*", module);

            // Verify
            registryApiClient.Verify(c => c.PutModuleAsync(ParentEdgeId, It.IsAny <CreateOrUpdateModuleOnBehalfOfData>(), It.IsAny <string>()), Times.Once());
            Assert.Equal(AuthChainOnParent, actualRequestData.AuthChain);
            Assert.Equal(ChildEdgeId, actualRequestData.Module.DeviceId);
            Assert.Equal(ModuleId, actualRequestData.Module.Id);
            Assert.Equal((int)HttpStatusCode.OK, controller.HttpContext.Response.StatusCode);

            byte[] actualResponseBytes = this.GetResponseBodyBytes(controller);
            string actualResponseJson  = Encoding.UTF8.GetString(actualResponseBytes);
            Module actualModule        = JsonConvert.DeserializeObject <Module>(actualResponseJson);

            Assert.Equal(ChildEdgeId, actualModule.DeviceId);
            Assert.Equal(ModuleId, actualModule.Id);
        }
Beispiel #3
0
 public static string GetAdditionalInfo(CreateOrUpdateModuleOnBehalfOfData data)
 {
     return($"authChain={data.AuthChain}, targetId={data.Module.Id}/{data.Module.DeviceId}");
 }
Beispiel #4
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()));
            }
        }
Beispiel #5
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);
                if (!AuthChainHelpers.TryGetTargetDeviceId(requestData.AuthChain, out string targetDeviceId))
                {
                    Events.InvalidRequestAuthChain(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), requestData.AuthChain);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage($"Invalid request auth chain {requestData.AuthChain}."));

                    return;
                }

                if (!string.Equals(targetDeviceId, requestData.Module.DeviceId, StringComparison.Ordinal))
                {
                    string errorMessage = $"Target device Id does not match between auth chain ({targetDeviceId}) and request body ({requestData.Module.DeviceId}).";
                    Events.BadRequest(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), errorMessage);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(errorMessage));

                    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(requestData.Module.DeviceId);
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

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

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

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