Пример #1
0
        private void EnsureOptions(AzureAppConfigurationOptions azconfigOptions)
        {
            if (azconfigOptions == null)
            {
                throw new ArgumentNullException(nameof(azconfigOptions));
            }

            if (azconfigOptions.ConnectionString == null)
            {
                throw new InvalidOperationException("An Azure App Configuration connection string is required.");
            }

            OfflineFileCacheOptions options = _options ?? new OfflineFileCacheOptions();

            if ((options.Key == null) || (options.SignKey == null) || (options.IV == null))
            {
                byte[] secret = Convert.FromBase64String(ConnectionStringParser.Parse(azconfigOptions.ConnectionString, "Secret"));
                using (SHA256 sha256 = SHA256.Create())
                {
                    byte[] hash = sha256.ComputeHash(secret);

                    options.Key     = options.Key ?? hash;
                    options.SignKey = options.SignKey ?? hash;
                    options.IV      = options.IV ?? hash.Take(16).ToArray();
                }
            }

            if (string.IsNullOrEmpty(_scopeToken))
            {
                //
                // The default scope token is the configuration store endpoint combined with all of the key-value filters

                string endpoint = ConnectionStringParser.Parse(azconfigOptions.ConnectionString, "Endpoint");

                if (string.IsNullOrWhiteSpace(endpoint))
                {
                    throw new InvalidOperationException("Invalid connection string format.");
                }

                var sb = new StringBuilder($"{endpoint}\0");

                foreach (var selector in azconfigOptions.KeyValueSelectors)
                {
                    sb.Append($"{selector.KeyFilter}\0{selector.LabelFilter}\0");
                }

                _scopeToken = sb.ToString();
            }

            _options = options;
        }
Пример #2
0
        /// <summary>
        /// A cache used for storing Azure App Configuration data using the file system.
        /// Supports encryption of the stored data.
        /// </summary>
        /// <param name="options">
        /// Options dictating the behavior of the offline cache.
        /// If the options are null or the encryption keys are omitted, they will be derived from the store's connection string.
        /// <see cref="OfflineFileCacheOptions.Path"/> is required unless the application is running inside of an Azure App Service instance, in which case it can be populated automatically.
        /// </param>
        public OfflineFileCache(OfflineFileCacheOptions options = null)
        {
            OfflineFileCacheOptions opts = options ?? new OfflineFileCacheOptions();

            // If the user does not specify the cache path, we will try to use the default path
            // For the moment, default path is only supported when running inside Azure App Service
            if (opts.Path == null)
            {
                // Generate default cache file name under $home/data/azureAppConfigCache/app{instance}-{hash}.json
                string homePath = Environment.GetEnvironmentVariable("HOME");
                if (Directory.Exists(homePath))
                {
                    string dataPath = Path.Combine(homePath, "data");
                    if (Directory.Exists(dataPath))
                    {
                        string cachePath = Path.Combine(dataPath, "azureAppConfigCache");
                        if (!Directory.Exists(cachePath))
                        {
                            Directory.CreateDirectory(cachePath);
                        }

                        string websiteName = Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME");
                        if (websiteName != null)
                        {
                            byte[] hash = new byte[0];
                            using (var sha = SHA1.Create())
                            {
                                hash = sha.ComputeHash(Encoding.UTF8.GetBytes(websiteName));
                            }

                            // The instance count will help prevent multiple providers from overwriting each other's cache file
                            Interlocked.Increment(ref instance);
                            opts.Path = Path.Combine(cachePath, $"app{instance}-{BitConverter.ToString(hash).Replace("-", String.Empty)}.json");
                        }
                    }
                }

                if (opts.Path == null)
                {
                    throw new ArgumentNullException($"{nameof(OfflineFileCacheOptions)}.{nameof(OfflineFileCacheOptions.Path)}", "Default cache path is only supported when running inside of an Azure App Service.");
                }
            }

            ValidateCachePath(opts.Path);
            _localCachePath = opts.Path;
            _options        = opts;
        }