Exemplo n.º 1
0
        /// <summary>
        /// Get list of DeviceTwinNames from IOT-hub and whitelist it.
        /// </summary>
        /// <remarks>
        /// List of Twin Names to be whitelisted is hardcoded in appsettings.ini
        /// </remarks>
        private async Task <DeviceTwinName> GetValidNamesAsync()
        {
            ParseWhitelist(this.whitelist, out var fullNameWhitelist, out var prefixWhitelist);

            var validNames = new DeviceTwinName
            {
                Tags = fullNameWhitelist.Tags,
                ReportedProperties = fullNameWhitelist.ReportedProperties
            };

            if (prefixWhitelist.Tags.Any() || prefixWhitelist.ReportedProperties.Any())
            {
                DeviceTwinName allNames = new DeviceTwinName();
                try
                {
                    /// Get list of DeviceTwinNames from IOT-hub
                    allNames = await this.devices.GetDeviceTwinNamesAsync();
                }
                catch (Exception e)
                {
                    throw new ExternalDependencyException("Unable to fetch IoT devices", e);
                }
                validNames.Tags.UnionWith(allNames.Tags.
                                          Where(s => prefixWhitelist.Tags.Any(s.StartsWith)));

                validNames.ReportedProperties.UnionWith(
                    allNames.ReportedProperties.Where(
                        s => prefixWhitelist.ReportedProperties.Any(s.StartsWith)));
            }

            return(validNames);
        }
Exemplo n.º 2
0
        private static bool CheckNames(string data, DeviceTwinName expiredNames)
        {
            var cacheValue = JsonConvert.DeserializeObject <DevicePropertyServiceModel>(data);

            return(cacheValue.Tags.SetEquals(expiredNames.Tags) &&
                   cacheValue.Reported.SetEquals(expiredNames.ReportedProperties));
        }
Exemplo n.º 3
0
        private static void ParseWhitelist(string whitelist, out DeviceTwinName fullNameWhitelist, out DeviceTwinName prefixWhitelist)
        {
            var whitelistItems = whitelist.Split(',').Select(s => s.Trim());

            var tags = whitelistItems
                       .Where(s => s.StartsWith(WHITELIST_TAG_PREFIX, StringComparison.OrdinalIgnoreCase))
                       .Select(s => s.Substring(WHITELIST_TAG_PREFIX.Length));

            var reported = whitelistItems
                           .Where(s => s.StartsWith(WHITELIST_REPORTED_PREFIX, StringComparison.OrdinalIgnoreCase))
                           .Select(s => s.Substring(WHITELIST_REPORTED_PREFIX.Length));

            var fixedTags     = tags.Where(s => !s.EndsWith("*"));
            var fixedReported = reported.Where(s => !s.EndsWith("*"));

            var regexTags     = tags.Where(s => s.EndsWith("*")).Select(s => s.Substring(0, s.Length - 1));
            var regexReported = reported.Where(s => s.EndsWith("*")).Select(s => s.Substring(0, s.Length - 1));

            fullNameWhitelist = new DeviceTwinName
            {
                Tags = new HashSet <string>(fixedTags),
                ReportedProperties = new HashSet <string>(fixedReported)
            };

            prefixWhitelist = new DeviceTwinName
            {
                Tags = new HashSet <string>(regexTags),
                ReportedProperties = new HashSet <string>(regexReported)
            };
        }
Exemplo n.º 4
0
        private async Task <DeviceTwinName> GetValidNamesAsync()
        {
            ParseWhitelist(this.cacheWhitelist, out var fullNameWhitelist, out var prefixWhitelist);

            var validNames = new DeviceTwinName
            {
                Tags = fullNameWhitelist.Tags,
                ReportedProperties = fullNameWhitelist.ReportedProperties
            };

            if (prefixWhitelist.Tags.Any() || prefixWhitelist.ReportedProperties.Any())
            {
                var allNames = await this.iotHubClient.GetDeviceTwinNamesAsync();

                validNames.Tags.UnionWith(
                    allNames.Tags
                    .Where(s => prefixWhitelist.Tags.Any(s.StartsWith)));

                validNames.ReportedProperties.UnionWith(
                    allNames.ReportedProperties
                    .Where(s => prefixWhitelist.ReportedProperties.Any(s.StartsWith)));
            }

            return(validNames);
        }
Exemplo n.º 5
0
        public async Task TryRecreateListAsyncTest()
        {
            var mockStorageAdapterClient = new Mock <IStorageAdapterClient>();
            var mockDevices = new Mock <IDevices>();

            var cache = new DeviceProperties(
                mockStorageAdapterClient.Object,
                new AppConfig
            {
                Global = new GlobalConfig(),
                IotHubManagerService = new IotHubManagerServiceConfig
                {
                    DevicePropertiesCache = new DevicePropertiesCacheConfig
                    {
                        Whitelist = "tags.*, reported.Type, reported.Config.*",
                        Ttl       = 3600,
                    },
                },
            },
                new Mock <ILogger <DeviceProperties> >().Object,
                mockDevices.Object);

            var etagOld  = this.rand.NextString();
            var etagLock = this.rand.NextString();
            var etagNew  = this.rand.NextString();

            mockStorageAdapterClient
            .Setup(x => x.GetAsync(
                       It.Is <string>(s => s == DeviceProperties.CacheCollectioId),
                       It.Is <string>(s => s == DeviceProperties.CacheKey)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagOld,
                Data = JsonConvert.SerializeObject(new DevicePropertyServiceModel
                {
                    Rebuilding = false,
                }),
                Metadata = new Dictionary <string, string>
                {
                    { "$modified", (DateTimeOffset.UtcNow - TimeSpan.FromDays(1)).ToString(CultureInfo.InvariantCulture) },
                },
            });
            mockDevices.Setup(x => x.GetDeviceTwinNamesAsync())
            .ReturnsAsync(new DeviceTwinName
            {
                Tags = new HashSet <string> {
                    "Building", "Group"
                },
                ReportedProperties = new HashSet <string> {
                    "Config.Interval", "otherProperty"
                },
            });

            mockStorageAdapterClient
            .Setup(x => x.UpdateAsync(
                       It.Is <string>(s => s == DeviceProperties.CacheCollectioId),
                       It.Is <string>(s => s == DeviceProperties.CacheKey),
                       It.Is <string>(s => Rebuilding(s)),
                       It.Is <string>(s => s == etagOld)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagLock,
            });

            mockStorageAdapterClient
            .Setup(x => x.UpdateAsync(
                       It.Is <string>(s => s == DeviceProperties.CacheCollectioId),
                       It.Is <string>(s => s == DeviceProperties.CacheKey),
                       It.Is <string>(s => !Rebuilding(s)),
                       It.Is <string>(s => s == etagLock)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagNew,
            });

            var expiredNames = new DeviceTwinName
            {
                Tags = new HashSet <string>
                {
                    "Building", "Group",
                },
                ReportedProperties = new HashSet <string>
                {
                    "Type", "Config.Interval", "MethodStatus", "UpdateStatus",
                },
            };

            var result = await cache.TryRecreateListAsync();

            Assert.True(result);

            mockStorageAdapterClient
            .Verify(
                x => x.GetAsync(
                    It.Is <string>(s => s == DeviceProperties.CacheCollectioId),
                    It.Is <string>(s => s == DeviceProperties.CacheKey)),
                Times.Once);

            mockDevices
            .Verify(x => x.GetDeviceTwinNamesAsync(), Times.Once);

            mockStorageAdapterClient
            .Verify(
                x => x.UpdateAsync(
                    It.Is <string>(s => s == DeviceProperties.CacheCollectioId),
                    It.Is <string>(s => s == DeviceProperties.CacheKey),
                    It.Is <string>(s => Rebuilding(s)),
                    It.Is <string>(s => s == etagOld)),
                Times.Once);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Parse the comma seperated string "whitelist" and create two separate list
        /// One with regex(*) and one without regex(*)
        /// </summary>
        /// <param name="whitelist">Comma seperated list of deviceTwinName to be
        /// whitlisted which is hardcoded in appsettings.ini.</param>
        /// <param name="fullNameWhitelist">An out paramenter which is a list of
        /// deviceTwinName to be whitlisted without regex.</param>
        /// <param name="prefixWhitelist">An out paramenter which is a list of
        /// deviceTwinName to be whitlisted with regex.</param>
        private static void ParseWhitelist(string whitelist,
                                           out DeviceTwinName fullNameWhitelist,
                                           out DeviceTwinName prefixWhitelist)
        {
            /// <example>
            /// whitelist = "tags.*, reported.Protocol, reported.SupportedMethods,
            ///                 reported.DeviceMethodStatus, reported.FirmwareUpdateStatus"
            /// whitelistItems = [tags.*,
            ///                   reported.Protocol,
            ///                   reported.SupportedMethods,
            ///                   reported.DeviceMethodStatus,
            ///                   reported.FirmwareUpdateStatus]
            /// </example>
            var whitelistItems = whitelist.Split(',').Select(s => s.Trim());

            /// <example>
            /// tags = [tags.*]
            /// </example>
            var tags = whitelistItems
                       .Where(s => s.StartsWith(WHITELIST_TAG_PREFIX, StringComparison.OrdinalIgnoreCase))
                       .Select(s => s.Substring(WHITELIST_TAG_PREFIX.Length));

            /// <example>
            /// reported = [reported.Protocol,
            ///             reported.SupportedMethods,
            ///             reported.DeviceMethodStatus,
            ///             reported.FirmwareUpdateStatus]
            /// </example>
            var reported = whitelistItems
                           .Where(s => s.StartsWith(WHITELIST_REPORTED_PREFIX, StringComparison.OrdinalIgnoreCase))
                           .Select(s => s.Substring(WHITELIST_REPORTED_PREFIX.Length));

            /// <example>
            /// fixedTags = []
            /// </example>
            var fixedTags = tags.Where(s => !s.EndsWith("*"));
            /// <example>
            /// fixedReported = [reported.Protocol,
            ///                  reported.SupportedMethods,
            ///                  reported.DeviceMethodStatus,
            ///                  reported.FirmwareUpdateStatus]
            /// </example>
            var fixedReported = reported.Where(s => !s.EndsWith("*"));

            /// <example>
            /// regexTags = [tags.]
            /// </example>
            var regexTags = tags.Where(s => s.EndsWith("*")).Select(s => s.Substring(0, s.Length - 1));
            /// <example>
            /// regexReported = []
            /// </example>
            var regexReported = reported.
                                Where(s => s.EndsWith("*")).
                                Select(s => s.Substring(0, s.Length - 1));

            /// <example>
            /// fullNameWhitelist = {Tags = [],
            ///                      ReportedProperties = [
            ///                         reported.Protocol,
            ///                         reported.SupportedMethods,
            ///                         reported.DeviceMethodStatus,
            ///                         reported.FirmwareUpdateStatus]
            ///                      }
            /// </example>
            fullNameWhitelist = new DeviceTwinName
            {
                Tags = new HashSet <string>(fixedTags),
                ReportedProperties = new HashSet <string>(fixedReported)
            };

            /// <example>
            /// prefixWhitelist = {Tags = [tags.],
            ///                    ReportedProperties = []}
            /// </example>
            prefixWhitelist = new DeviceTwinName
            {
                Tags = new HashSet <string>(regexTags),
                ReportedProperties = new HashSet <string>(regexReported)
            };
        }
Exemplo n.º 7
0
        public async Task TryRecreateListAsyncTest()
        {
            var mockStorageAdapterClient = new Mock <IStorageAdapterClient>();
            var mockDevices = new Mock <IDevices>();

            var cache = new DeviceProperties(
                mockStorageAdapterClient.Object,
                new ServicesConfig
            {
                DevicePropertiesWhiteList = "tags.*, reported.Type, reported.Config.*",
                DevicePropertiesTTL       = 3600
            },
                new Logger("UnitTest", LogLevel.Debug),
                mockDevices.Object);

            var etagOld  = this.rand.NextString();
            var etagLock = this.rand.NextString();
            var etagNew  = this.rand.NextString();

            mockStorageAdapterClient
            .Setup(x => x.GetAsync(
                       It.Is <string>(s => s == DeviceProperties.CACHE_COLLECTION_ID),
                       It.Is <string>(s => s == DeviceProperties.CACHE_KEY)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagOld,
                Data = JsonConvert.SerializeObject(new DevicePropertyServiceModel
                {
                    Rebuilding = false
                }),
                Metadata = new Dictionary <string, string>
                {
                    { "$modified", (DateTimeOffset.UtcNow - TimeSpan.FromDays(1)).ToString(CultureInfo.InvariantCulture) }
                }
            });
            mockDevices.Setup(x => x.GetDeviceTwinNamesAsync())
            .ReturnsAsync(new DeviceTwinName
            {
                Tags = new HashSet <string> {
                    "Building", "Group"
                },
                ReportedProperties = new HashSet <string> {
                    "Config.Interval", "otherProperty"
                }
            });

            mockStorageAdapterClient
            .Setup(x => x.UpdateAsync(
                       It.Is <string>(s => s == DeviceProperties.CACHE_COLLECTION_ID),
                       It.Is <string>(s => s == DeviceProperties.CACHE_KEY),
                       It.Is <string>(s => Rebuilding(s)),
                       It.Is <string>(s => s == etagOld)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagLock
            });

            mockStorageAdapterClient
            .Setup(x => x.UpdateAsync(
                       It.Is <string>(s => s == DeviceProperties.CACHE_COLLECTION_ID),
                       It.Is <string>(s => s == DeviceProperties.CACHE_KEY),
                       It.Is <string>(s => !Rebuilding(s)),
                       It.Is <string>(s => s == etagLock)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagNew
            });

            var expiredNames = new DeviceTwinName
            {
                Tags = new HashSet <string>
                {
                    "Building", "Group"
                },
                ReportedProperties = new HashSet <string>
                {
                    "Type", "Config.Interval", "MethodStatus", "UpdateStatus"
                }
            };

            var result = await cache.TryRecreateListAsync();

            Assert.True(result);

            mockStorageAdapterClient
            .Verify(x => x.GetAsync(
                        It.Is <string>(s => s == DeviceProperties.CACHE_COLLECTION_ID),
                        It.Is <string>(s => s == DeviceProperties.CACHE_KEY)),
                    Times.Once);

            mockDevices
            .Verify(x => x.GetDeviceTwinNamesAsync(), Times.Once);

            mockStorageAdapterClient
            .Verify(x => x.UpdateAsync(
                        It.Is <string>(s => s == DeviceProperties.CACHE_COLLECTION_ID),
                        It.Is <string>(s => s == DeviceProperties.CACHE_KEY),
                        It.Is <string>(s => Rebuilding(s)),
                        It.Is <string>(s => s == etagOld)),
                    Times.Once);
        }