private async Task <string> GetAccessKeyAsync(CancellationToken token)
        {
            var accessToken = await Curl.GetAsync <AccessToken>(this.options.ArmMsiUri, new Dictionary <string, string>() { { "Metadata", "true" } }, token);

            this.logger.Information("Got access token expires in {0}, expires on {1}, not before {2}, now {3}, resource {4}, token type {5}",
                                    accessToken.expires_in, accessToken.expires_on, accessToken.not_before, (DateTimeOffset.Now - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.FromSeconds(0))).TotalSeconds,
                                    accessToken.resource, accessToken.token_type);
            return(accessToken.access_token);
        }
        private async Task <StorageConfiguration> GetStorageConfigAsync(string accessToken, CancellationToken token)
        {
            // 1. Tags
            //      1.1 Node tags
            //      1.2 Resource group tags
            // 2. Config
            // 3. Node Metadata Inspections

            var compute = await Curl.GetAsync <Compute>(this.options.ArmComputeMetadataUri, new Dictionary <string, string>() { { "Metadata", "true" } }, token);

            this.logger.Information("queried metadata.");
            var config = this.GetConfigFromTags(compute.tags);

            if (config == null)
            {
                this.logger.Information("Getting tags from resource group {0}, subid {1}", compute.resourceGroupName, compute.subscriptionId);
                config = this.GetConfigFromTags((await Curl.GetAsync <ResourceGroupInfo>(
                                                     string.Format(this.options.ArmResourceGroupUri, compute.subscriptionId, compute.resourceGroupName),
                                                     new Dictionary <string, string>()
                {
                    { "Authorization", $"Bearer {accessToken}" }
                },
                                                     token)).tags?.StorageConfiguration, true);
            }

            if (config == null)
            {
                this.logger.Information("Couldn't get config from tags, getting from config file");
                if (this.options.Storage == null)
                {
                    this.logger.Information("Couldn't get config from config file, returning null");
                    return(null);
                }

                config = this.options.Storage.Clone();
            }

            this.logger.Information("Config Info From config file: SubscriptionId {0}, resource group {1}", config.SubscriptionId, config.ResourceGroup);
            config.SubscriptionId = config.SubscriptionId ?? compute.subscriptionId;
            config.ResourceGroup  = config.ResourceGroup ?? compute.resourceGroupName;

            this.logger.Information("Config Info Combined with metadata: SubscriptionId {0}, resource group {1}", config.SubscriptionId, config.ResourceGroup);
            return(config);
        }
        public async Task <StorageConfiguration> GetStorageConfigAsync(CancellationToken token)
        {
            // get token
            this.logger.Information("Getting access token");
            var accessToken = await this.GetAccessKeyAsync(token);

            // resolve config
            this.logger.Information("Getting storage config");
            var config = await this.GetStorageConfigAsync(accessToken, token);

            // get keys
            if (config == null)
            {
                return(null);
            }
            this.logger.Information("Getting storage key");
            var requestUri = this.GetListStorageKeyUri(config);
            var keys       = await Curl.PostAsync <StorageKeys, object>(requestUri, new Dictionary <string, string>() { { "Authorization", $"Bearer {accessToken}" } }, null, token);

            var key = keys.keys.FirstOrDefault(k => config.KeyName == null || string.Equals(k.keyName, config.KeyName, StringComparison.OrdinalIgnoreCase));

            config.KeyValue = key?.value;
            return(config);
        }