Esempio n. 1
0
        /// <summary>
        /// Deactivate
        /// </summary>
        /// <param name="registration"></param>
        /// <param name="context"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task DeactivateAsync(EndpointRegistration registration,
                                           RegistryOperationContextModel context, CancellationToken ct = default)
        {
            var endpoint = registration.ToServiceModel();

            // Deactivate twin in twin settings - do no matter what
            await ClearSupervisorTwinSecretAsync(registration.DeviceId,
                                                 registration.SupervisorId, ct);

            // Call down to supervisor to ensure deactivation is complete - do no matter what
            await Try.Async(() => _activator.DeactivateEndpointAsync(endpoint.Registration));

            try {
                // Mark as deactivated
                if (registration.Activated ?? false)
                {
                    var patch = endpoint.ToEndpointRegistration(
                        _serializer, registration.IsDisabled);

                    // Mark as deactivated
                    patch.Activated = false;

                    await _iothub.PatchAsync(registration.Patch(patch, _serializer), true);
                }
                await _broker.NotifyAllAsync(l => l.OnEndpointDeactivatedAsync(context, endpoint));
            }
            catch (Exception ex) {
                _logger.Error(ex, "Failed to deactivate twin");
                throw;
            }
        }
Esempio n. 2
0
        public void EntityValidator_should_raise_validation_exception_if_endpoint_entity_token_is_short()
        {
            var endpoint = new EndpointRegistration
            {
                Address = "address", Group = "group", MonitorType = "http", Name = "name", Password = "******"
            };

            Assert.Throws <ValidationException>(() => endpoint.ValidateModel());
        }
Esempio n. 3
0
        /// <summary>
        /// Try to activate endpoint on any supervisor in site
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="additional"></param>
        /// <param name="context"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task <bool> ActivateAsync(EndpointRegistration endpoint,
                                                IEnumerable <string> additional, RegistryOperationContextModel context,
                                                CancellationToken ct)
        {
            // Get site of this endpoint
            var site = endpoint.SiteId;

            if (string.IsNullOrEmpty(site))
            {
                // Use discovery id gateway part if no site found
                site = DiscovererModelEx.ParseDeviceId(endpoint.DiscovererId, out _);
                if (string.IsNullOrEmpty(site))
                {
                    // Try supervisor id gateway part
                    site = DiscovererModelEx.ParseDeviceId(endpoint.SupervisorId, out _);
                }
            }

            // Get all supervisors in site
            endpoint.SiteId = site;
            var supervisorsInSite = await _supervisors.QueryAllSupervisorsAsync(
                new SupervisorQueryModel { SiteId = site });

            var candidateSupervisors = supervisorsInSite.Select(s => s.Id)
                                       .ToList().Shuffle();

            // Add all supervisors that managed this endpoint before.
            // TODO: Consider removing as it is a source of bugs
            if (additional != null)
            {
                candidateSupervisors.AddRange(additional);
            }

            // Remove previously failing one
            candidateSupervisors.Remove(endpoint.SupervisorId);
            // Loop through all randomly and try to take one that works.
            foreach (var supervisorId in candidateSupervisors)
            {
                endpoint.SupervisorId = supervisorId;
                endpoint.Activated    = false;
                try {
                    await ActivateAsync(endpoint, context, ct);

                    _logger.Information("Activate twin on supervisor {supervisorId}!",
                                        supervisorId);
                    // Done - endpoint was also patched thus has new supervisor id
                    return(true);
                }
                catch (Exception ex) {
                    _logger.Debug(ex, "Failed to activate twin on supervisor {supervisorId} " +
                                  "- trying next...", supervisorId);
                }
            }
            // Failed
            return(false);
        }
Esempio n. 4
0
        public static void AuthorizeRegistration(this HttpRequestContext context, EndpointRegistration model, Endpoint modifiable, params SecurityRole[] roles)
        {
            if (modifiable?.Password == null ||
                modifiable.Password == model?.Password?.ToSha256Hash())
            {
                return;
            }

            Authorize(context, modifiable.Identity.Id, roles);
        }
Esempio n. 5
0
        /// <summary>
        /// Apply activation filter
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="registration"></param>
        /// <param name="context"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task <string> ApplyActivationFilterAsync(
            EndpointActivationFilterModel filter, EndpointRegistration registration,
            RegistryOperationContextModel context, CancellationToken ct = default)
        {
            if (filter == null || registration == null)
            {
                return(null);
            }
            // TODO: Get trust list entry and validate endpoint.Certificate
            var mode = registration.SecurityMode ?? SecurityMode.None;

            if (!mode.MatchesFilter(filter.SecurityMode ?? SecurityMode.Best))
            {
                return(null);
            }
            var policy = registration.SecurityPolicy;

            if (filter.SecurityPolicies != null)
            {
                if (!filter.SecurityPolicies.Any(p =>
                                                 p.EqualsIgnoreCase(registration.SecurityPolicy)))
                {
                    return(null);
                }
            }
            try {
                // Ensure device scope for the registration before getting the secret.
                // Changing device's scope regenerates the secret.
                await EnsureDeviceScopeForRegistrationAsync(registration, ct);

                // Get endpoint twin secret
                var secret = await _iothub.GetPrimaryKeyAsync(registration.DeviceId, null, ct);

                var endpoint = registration.ToServiceModel();

                // Try activate endpoint - if possible...
                await _activator.ActivateEndpointAsync(endpoint.Registration, secret, ct);

                // Mark in supervisor
                await SetSupervisorTwinSecretAsync(registration.SupervisorId,
                                                   registration.DeviceId, secret, ct);

                registration.Activated = true;

                await _broker.NotifyAllAsync(
                    l => l.OnEndpointActivatedAsync(context, endpoint));

                return(secret);
            }
            catch (Exception ex) {
                _logger.Information(ex, "Failed activating {eeviceId} based off " +
                                    "filter.  Manual activation required.", registration.DeviceId);
                return(null);
            }
        }
 public IHttpActionResult PostRegisterEndpoint([FromBody] EndpointRegistration endpoint)
 {
     endpoint.ValidateModel();
     try
     {
         var id = _endpointRegistry.RegisterOrUpdate(endpoint.MonitorType, endpoint.Address, endpoint.Group, endpoint.Name, endpoint.Tags);
         return(Created(new Uri(Request.RequestUri, $"/api/endpoints/{id}"), id));
     }
     catch (UnsupportedMonitorException e)
     {
         return(BadRequest(e.Message));
     }
 }
        /// <summary>
        /// Ensure device scope for registration
        /// </summary>
        /// <param name="registration"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task EnsureDeviceScopeForRegistrationAsync(
            EndpointRegistration registration, CancellationToken ct = default)
        {
            // Ensure device scope is set to the owning edge gateway before activation
            var edgeScope = await GetSupervisorDeviceScopeAsync(registration.SupervisorId, ct);

            var deviceTwin = await _iothub.GetAsync(registration.DeviceId, ct : ct);

            if (!string.IsNullOrEmpty(edgeScope) && deviceTwin.DeviceScope != edgeScope)
            {
                deviceTwin.DeviceScope = edgeScope;
                await _iothub.CreateOrUpdateAsync(deviceTwin, true, ct : ct);
            }
        }
        public IHttpActionResult PostRegisterEndpoint([FromBody] EndpointRegistration endpoint)
        {
            endpoint.ValidateModel();

            try
            {
                var existed = _endpointRegistry.GetByNaturalKey(endpoint.MonitorType, endpoint.Address);
                RequestContext.AuthorizeRegistration(endpoint, existed, SecurityRole.Admin);

                var id = _endpointRegistry.RegisterOrUpdate(endpoint.MonitorType, endpoint.Address, endpoint.Group, endpoint.Name, endpoint.Tags, endpoint.Password);
                return(Created(new Uri(Request.RequestUri, $"/api/endpoints/{id}"), id));
            }
            catch (UnsupportedMonitorException e)
            {
                return(BadRequest(e.Message));
            }
        }
        public async Task TestActivateDeactivateEndpoint20Times() {
            using (var harness = new TwinModuleFixture()) {
                await harness.RunTestAsync(async (device, module, services) => {

                // Setup
                var supervisorId = SupervisorModelEx.CreateSupervisorId(device, module);
                var activation = services.Resolve<IActivationServices<EndpointRegistrationModel>>();
                var hub = services.Resolve<IIoTHubTwinServices>();
                var twin = EndpointRegistration.Patch(null, EndpointRegistration.FromServiceModel(new EndpointInfoModel {
                    Registration = new EndpointRegistrationModel {
                        Endpoint = new EndpointModel {
                            Url = "opc.tcp://test"
                        },
                        SupervisorId = supervisorId
                    },
                    ApplicationId = "ua326029342304923"
                }));

                await hub.CreateOrUpdateAsync(twin);
                var registry = services.Resolve<IEndpointRegistry>();
                var endpoints = await registry.ListAllEndpointsAsync();
                var ep1 = endpoints.FirstOrDefault();
                Assert.NotNull(ep1);

                for (var i = 0; i < 20; i++) {
                    // Act
                    await registry.ActivateEndpointAsync(ep1.Registration.Id);
                    await registry.DeactivateEndpointAsync(ep1.Registration.Id);
                }

                var diagnostics = services.Resolve<ISupervisorDiagnostics>();
                endpoints = await registry.ListAllEndpointsAsync();
                var ep3 = endpoints.FirstOrDefault();
                var status = await diagnostics.GetSupervisorStatusAsync(supervisorId);

                // Assert
                Assert.Equal(device, status.DeviceId);
                Assert.Equal(module, status.ModuleId);
                Assert.Null(status.SiteId);
                Assert.Empty(status.Endpoints);
                Assert.Equal(EndpointActivationState.Deactivated, ep3.ActivationState);
                Assert.Null(ep3.EndpointState);
            });
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Activate
        /// </summary>
        /// <param name="registration"></param>
        /// <param name="context"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task ActivateAsync(EndpointRegistration registration,
                                         RegistryOperationContextModel context, CancellationToken ct = default)
        {
            // Ensure device scope for the registration before getting the secret.
            // Changing device's scope regenerates the secret.
            await EnsureDeviceScopeForRegistrationAsync(registration, ct);

            // Update supervisor settings
            var secret = await _iothub.GetPrimaryKeyAsync(registration.DeviceId, null, ct);

            var endpoint = registration.ToServiceModel();

            try {
                // Call down to supervisor to activate - this can fail
                await _activator.ActivateEndpointAsync(endpoint.Registration, secret, ct);

                // Update supervisor desired properties
                await SetSupervisorTwinSecretAsync(registration.SupervisorId,
                                                   registration.DeviceId, secret, ct);

                if (!(registration.Activated ?? false))
                {
                    // Update twin activation status in twin settings
                    var patch = endpoint.ToEndpointRegistration(_serializer,
                                                                registration.IsDisabled);

                    patch.Activated = true; // Mark registration as activated

                    await _iothub.PatchAsync(registration.Patch(patch, _serializer), true, ct);
                }
                await _broker.NotifyAllAsync(l => l.OnEndpointActivatedAsync(context, endpoint));
            }
            catch (Exception ex) {
                // Undo activation
                await Try.Async(() => _activator.DeactivateEndpointAsync(
                                    endpoint.Registration));

                await Try.Async(() => ClearSupervisorTwinSecretAsync(
                                    registration.DeviceId, registration.SupervisorId));

                _logger.Error(ex, "Failed to activate twin");
                throw;
            }
        }
        public async Task TestActivateDeactivate20Endpoints5TimesMultiThreaded() {
            using (var harness = new TwinModuleFixture()) {
                await harness.RunTestAsync(async (device, module, services) => {

                // Setup
                var supervisorId = SupervisorModelEx.CreateSupervisorId(device, module);
                var activation = services.Resolve<IActivationServices<EndpointRegistrationModel>>();
                var hub = services.Resolve<IIoTHubTwinServices>();

                for (var i = 0; i < 20; i++) {
                    var twin = EndpointRegistration.Patch(null, EndpointRegistration.FromServiceModel(new EndpointInfoModel {
                        Registration = new EndpointRegistrationModel {
                            Endpoint = new EndpointModel {
                                Url = "opc.tcp://test"
                            },
                            SupervisorId = supervisorId
                        },
                        ApplicationId = "uas" + i
                    }));
                    await hub.CreateOrUpdateAsync(twin);
                }

                var registry = services.Resolve<IEndpointRegistry>();
                var endpoints = await registry.ListAllEndpointsAsync();

                for (var i = 0; i < 5; i++) {
                    await Task.WhenAll(endpoints.Select(ep => registry.ActivateEndpointAsync(ep.Registration.Id)));
                    await Task.WhenAll(endpoints.Select(ep => registry.DeactivateEndpointAsync(ep.Registration.Id)));
                }

                var diagnostics = services.Resolve<ISupervisorDiagnostics>();
                endpoints = await registry.ListAllEndpointsAsync();
                var status = await diagnostics.GetSupervisorStatusAsync(supervisorId);

                // Assert
                Assert.Equal(device, status.DeviceId);
                Assert.Equal(module, status.ModuleId);
                Assert.Null(status.SiteId);
                Assert.Empty(status.Endpoints);
                Assert.True(endpoints.All(ep => ep.ActivationState == EndpointActivationState.Deactivated));
                Assert.True(endpoints.All(ep => ep.EndpointState == null));
            });
            }
        }
        /// <summary>
        /// Activate
        /// </summary>
        /// <param name="endpoint"></param>
        /// <returns></returns>
        public EndpointRegistrationModel RegisterAndActivateTwinId(EndpointRegistrationModel endpoint)
        {
            var twin = EndpointRegistration.Patch(null, EndpointRegistration.FromServiceModel(
                                                      new EndpointInfoModel {
                Registration  = endpoint,
                ApplicationId = "uas" + Guid.NewGuid().ToString()
            }));
            var result    = _hub.CreateOrUpdateAsync(twin).Result;
            var registry  = HubContainer.Resolve <IEndpointRegistry>();
            var endpoints = registry.ListAllEndpointsAsync().Result;
            var ep1       = endpoints.FirstOrDefault();

            if (ep1.ActivationState == EndpointActivationState.Deactivated)
            {
                // Activate
                registry.ActivateEndpointAsync(ep1.Registration.Id).Wait();
            }
            return(ep1.Registration);
        }
        /// <summary>
        /// Helper to create fixtures
        /// </summary>
        /// <param name="site"></param>
        /// <param name="super"></param>
        /// <param name="existing"></param>
        /// <param name="found"></param>
        /// <param name="registry"></param>
        /// <param name="countDevices"></param>
        /// <param name="fixup"></param>
        /// <param name="disable"></param>
        private static void CreateFixtures(out string site, out string super,
                                           out List <ApplicationRegistrationModel> existing, out List <DiscoveryEventModel> found,
                                           out IoTHubServices registry, int countDevices = -1,
                                           Func <ApplicationRegistrationModel, ApplicationRegistrationModel> fixup = null,
                                           bool disable = false)
        {
            var fix = new Fixture();

            // Create template applications and endpoints
            fix.Customizations.Add(new TypeRelay(typeof(JToken), typeof(JObject)));
            var sitex = site = fix.Create <string>();

            var module = fix.Create <string>();
            var device = fix.Create <string>();
            var superx = super = SupervisorModelEx.CreateSupervisorId(device, module);

            var supervisor = (
                SupervisorRegistration.Patch(null,
                                             SupervisorRegistration.FromServiceModel(new SupervisorModel {
                SiteId = site,
                Id = superx
            })), new DeviceModel {
                Id = device, ModuleId = module
            });

            var template = fix
                           .Build <ApplicationRegistrationModel>()
                           .Without(x => x.Application)
                           .Do(c => c.Application = fix
                                                    .Build <ApplicationInfoModel>()
                                                    .Without(x => x.NotSeenSince)
                                                    .With(x => x.SiteId, sitex)
                                                    .With(x => x.SupervisorId, superx)
                                                    .Create())
                           .Without(x => x.Endpoints)
                           .Do(c => c.Endpoints = fix
                                                  .Build <EndpointRegistrationModel>()
                                                  .With(x => x.SiteId, sitex)
                                                  .With(x => x.SupervisorId, superx)
                                                  .CreateMany(5)
                                                  .ToList())
                           .CreateMany(5)
                           .ToList();

            template.ForEach(a =>
                             a.Application.ApplicationId =
                                 ApplicationInfoModelEx.CreateApplicationId(a.Application)
                             );

            // Create discovery results from template
            var i = 0; var now = DateTime.UtcNow;

            found = template
                    .SelectMany(a => a.Endpoints.Select(
                                    e => new DiscoveryEventModel {
                Application  = a.Application,
                Registration = e,
                Index        = i++,
                TimeStamp    = now
            }))
                    .ToList();

            // Clone and fixup existing applications as per test case
            existing = template
                       .Select(e => e.Clone())
                       .Select(fixup ?? (a => a))
                       .ToList();
            // and fill registry with them...
            var appdevices = existing
                             .Select(a => ApplicationRegistration.FromServiceModel(a.Application, disable))
                             .Select(a => ApplicationRegistration.Patch(null, a))
                             .Select(d => (d, new DeviceModel {
                Id = d.Id
            }));
            var epdevices = existing
                            .SelectMany(a => a.Endpoints
                                        .Select(e => EndpointRegistration.FromServiceModel(
                                                    new EndpointInfoModel {
                ApplicationId = a.Application.ApplicationId,
                Registration  = e
            }, disable)))
                            .Select(e => EndpointRegistration.Patch(null, e))
                            .Select(d => (d, new DeviceModel {
                Id = d.Id
            }));

            appdevices = appdevices.Concat(epdevices);
            if (countDevices != -1)
            {
                appdevices = appdevices.Take(countDevices);
            }
            registry = new IoTHubServices(appdevices.Concat(supervisor.YieldReturn()));
        }