示例#1
0
        public static async Task Run(TimerInfo myTimer, CloudTable configTbl, CloudTable statsTbl, CloudTable invalidTypesTbl, ICollector <string> outQueue, TraceWriter log)
        {
            _log      = log;
            _outQueue = outQueue;
            log.Info("Starding subscription audit.");
            var invalidTagResourcesQuery = await invalidTypesTbl.ExecuteQuerySegmentedAsync(new TableQuery <InvalidTagResource>(), null);

            var auditConfigQuery = await configTbl.ExecuteQuerySegmentedAsync(new TableQuery <AuditConfig>(), null);

            // Init config table if new deployment
            if (auditConfigQuery.Results.Count == 0)
            {
                AuditConfig initConfig = new AuditConfig {
                    SubscriptionId = "enter_valid_subscription_id", RowKey = Guid.NewGuid().ToString(), RequiredTags = "comma,separated,tag,list,here", PartitionKey = "init"
                };
                TableOperation insertOperation = TableOperation.InsertOrReplace(initConfig);
                await configTbl.ExecuteAsync(insertOperation);

                log.Info("First run for new deployment. Please populate the AuditConfig table.");
                return;
            }

            foreach (var auditConfig in auditConfigQuery.Results)
            {
                try
                {
                    AuditStats stats = new AuditStats {
                        JobStart = DateTime.Now, PartitionKey = auditConfig.SubscriptionId, RowKey = Guid.NewGuid().ToString()
                    };
                    IEnumerable <string> requiredTagsList = auditConfig.RequiredTags.Split(',');

                    try
                    {
                        string token = await AuthenticationService.GetAccessTokenAsync();

                        _resourceManager = new ResourceManagerService(token);
                    }
                    catch (Exception ex)
                    {
                        log.Error("Unable to connect to the ARM API, Message: " + ex.Message);
                    }

                    await ProcessResourceGroups(requiredTagsList, invalidTagResourcesQuery.Results, auditConfig.SubscriptionId, stats);

                    log.Info("Completed audit of subscription: " + auditConfig.SubscriptionId);
                    stats.JobEnd = DateTime.Now;

                    TableOperation insertOperation = TableOperation.InsertOrReplace(stats);
                    await statsTbl.ExecuteAsync(insertOperation);
                }
                catch (Exception ex)
                {
                    log.Error("Failure processing resource groups for auditConfig: " + auditConfig.RowKey);
                    log.Error(ex.Message);
                }
            }
        }
示例#2
0
        static async Task <List <ResourceItem> > ProcessResourceGroups(IEnumerable <string> requiredTagsList, string subscriptionId, AuditStats stats)
        {
            List <ResourceItem> updateList           = new List <ResourceItem>();
            List <string>       invalidResourceTypes = _resourceTypes.Where(t => !String.IsNullOrEmpty(t.ErrorMessage)).Select(t => t.Type).ToList();
            var resourceGroups = await _resourceManager.GetResourceGroups(subscriptionId);

            stats.ResourceGroupsTotal = resourceGroups.Count;

            foreach (var rg in resourceGroups)
            {
                _log.Info("Resource group: " + rg.Name);

                if (rg.Tags == null)
                {
                    _log.Warning("Resource group: " + rg.Name + " does not have tags.");
                    continue;
                }

                var tagsToSync = TagService.GetRequiredTags((Dictionary <string, string>)rg.Tags, requiredTagsList);

                if (tagsToSync.Count < 1)
                {
                    _log.Warning("Resource group: " + rg.Name + " does not have required tags.");
                    stats.ResourceGroupsSkipped += 1;
                }
                else
                {
                    List <ResourceItem> resources = await _resourceManager.GetResources(rg.Name, subscriptionId, invalidResourceTypes);

                    stats.ResourceItemsTotal = resources.Count();

                    foreach (var resource in resources)
                    {
                        var result = TagService.GetTagUpdates(resource.Tags.ToDictionary(x => x.Key, x => x.Value), tagsToSync);

                        if (result.Count > 0)
                        {
                            try
                            {
                                stats.ResourceItemsWithUpdates += 1;
                                resource.Tags       = result;
                                resource.ApiVersion = await GetApiVersion(resource);

                                updateList.Add(resource);
                            }
                            catch (Exception ex)
                            {
                                _log.Error("Failure processing resource: " + resource.Id);
                                _log.Error(ex.Message);
                            }
                        }
                        else
                        {
                            stats.ResourceItemsSkipped += 1;
                        }
                    }
                }
            }

            return(updateList);
        }
示例#3
0
        public static async Task Run(
            [TimerTrigger("0 0 */4 * * *", RunOnStartup = false)] TimerInfo timer,
            [Table("AuditConfig")] CloudTable configTbl,
            [Table("AuditStats")] CloudTable statsTbl,
            [Table("ResourceTypes")] CloudTable resourceTypesTbl,
            [Queue("resources-to-tag")] ICollector <string> outQueue,
            TraceWriter log)
        {
            _log = log;
            _resourceTypesTbl = resourceTypesTbl;
            log.Info("Starding subscription audit.");

            var resourceTypesQuery = await resourceTypesTbl.ExecuteQuerySegmentedAsync(new TableQuery <ResourceType>(), null);

            _resourceTypes = resourceTypesQuery.Results;
            var auditConfigQuery = await configTbl.ExecuteQuerySegmentedAsync(new TableQuery <AuditConfig>(), null);

            // Init config table if new deployment
            if (auditConfigQuery.Results.Count == 0)
            {
                AuditConfig initConfig = new AuditConfig {
                    SubscriptionId = "enter_valid_subscription_id", RowKey = Guid.NewGuid().ToString(), RequiredTags = "comma,separated,tag,list,here", PartitionKey = "init"
                };
                TableOperation insertOperation = TableOperation.InsertOrReplace(initConfig);
                await configTbl.ExecuteAsync(insertOperation);

                log.Info("First run for new deployment. Please populate the AuditConfig table.");
                return;
            }

            foreach (var auditConfig in auditConfigQuery.Results)
            {
                try
                {
                    AuditStats stats = new AuditStats {
                        JobStart = DateTime.Now, PartitionKey = auditConfig.SubscriptionId, RowKey = Guid.NewGuid().ToString()
                    };
                    IEnumerable <string> requiredTagsList = auditConfig.RequiredTags.Split(',');

                    try
                    {
                        string token = AuthenticationService.GetAccessTokenAsync();
                        _resourceManager = new ResourceManagerService(token);
                    }
                    catch (Exception ex)
                    {
                        log.Error("Unable to connect to the ARM API, Message: " + ex.Message);
                    }

                    List <ResourceItem> tagUpdates = await ProcessResourceGroups(requiredTagsList, auditConfig.SubscriptionId, stats);

                    foreach (ResourceItem resourceItem in tagUpdates)
                    {
                        string messageText = JsonConvert.SerializeObject(resourceItem);
                        _log.Info("Requesting tags for: " + resourceItem.Id);
                        outQueue.Add(messageText);
                    }

                    log.Info("Completed audit of subscription: " + auditConfig.SubscriptionId);
                    stats.JobEnd = DateTime.Now;

                    TableOperation insertOperation = TableOperation.InsertOrReplace(stats);
                    await statsTbl.ExecuteAsync(insertOperation);
                }
                catch (Exception ex)
                {
                    log.Error("Failure processing resource groups for auditConfig: " + auditConfig.RowKey);
                    log.Error(ex.Message);
                }
            }
        }
        public static async Task Run(
            [TimerTrigger("0 0 */2 * * *")] TimerInfo myTimer,
            [Table("AuditConfig")] CloudTable configTbl,
            [Table("AuditStats")] CloudTable statsTbl,
            [Table("InvalidTagResources")] CloudTable invalidTypesTbl,
            [Queue("resources-to-tag")] ICollector <string> outQueue,
            TraceWriter log)
        {
            _log      = log;
            _outQueue = outQueue;
            log.Info("Starding subscription audit.");
            var invalidTagResourcesQuery = await invalidTypesTbl.ExecuteQuerySegmentedAsync(new TableQuery <InvalidTagResource>(), null);

            var auditConfigQuery = await configTbl.ExecuteQuerySegmentedAsync(new TableQuery <AuditConfig>(), null);

            TokenCredentials tokenCredential;

            if (Environment.GetEnvironmentVariable("MSI_ENDPOINT") == null)
            {
                log.Info("Using service principal");
                string appId     = Environment.GetEnvironmentVariable("appId");
                string appSecret = Environment.GetEnvironmentVariable("appSecret");
                string tenantId  = Environment.GetEnvironmentVariable("tenantId");
                tokenCredential = AuthenticationService.GetAccessToken(appId, appSecret, tenantId);
            }
            else
            {
                log.Info("Using MSI");
                var    azureServiceTokenProvider = new AzureServiceTokenProvider();
                string token = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.core.windows.net/");

                tokenCredential = new TokenCredentials(token);
            }

            try
            {
                _client = new ResourceManagementClient(tokenCredential);
            }
            catch (Exception ex)
            {
                log.Error("Unable to connect to the ARM API, Message: " + ex.Message);
            }

            // Init config table if new deployment
            if (auditConfigQuery.Results.Count == 0)
            {
                AuditConfig initConfig = new AuditConfig {
                    SubscriptionId = "enter_valid_subscription_id", RowKey = Guid.NewGuid().ToString(), RequiredTags = "comma,separated,tag,list,here", PartitionKey = "init"
                };
                TableOperation insertOperation = TableOperation.InsertOrReplace(initConfig);
                await configTbl.ExecuteAsync(insertOperation);

                log.Info("First run for new deployment. Please populate the AuditConfig table.");
                return;
            }

            foreach (var auditConfig in auditConfigQuery.Results)
            {
                try
                {
                    AuditStats stats = new AuditStats {
                        JobStart = DateTime.Now, PartitionKey = auditConfig.SubscriptionId, RowKey = Guid.NewGuid().ToString()
                    };
                    IEnumerable <string> requiredTagsList = auditConfig.RequiredTags.Split(',');
                    _client.SubscriptionId = auditConfig.SubscriptionId;
                    IEnumerable <ResourceGroupInner> resourceGroups = await _client.ResourceGroups.ListAsync();

                    stats.ResourceGroupsTotal = resourceGroups.Count();
                    await ProcessResourceGroups(requiredTagsList, resourceGroups, invalidTagResourcesQuery.Results, auditConfig.SubscriptionId, stats);

                    log.Info("Completed audit of subscription: " + auditConfig.SubscriptionId);
                    stats.JobEnd = DateTime.Now;

                    TableOperation insertOperation = TableOperation.InsertOrReplace(stats);
                    await statsTbl.ExecuteAsync(insertOperation);
                }
                catch (Exception ex)
                {
                    log.Error("Failure processing resource groups for auditConfig: " + auditConfig.RowKey);
                    log.Error(ex.Message);
                }
            }
        }
        static async Task ProcessResourceGroups(IEnumerable <string> requiredTagsList, IEnumerable <ResourceGroupInner> resourceGroups, List <InvalidTagResource> invalidTypes, string subscriptionId, AuditStats stats)
        {
            foreach (ResourceGroupInner rg in resourceGroups)
            {
                _log.Info("*** Resource Group: " + rg.Name);

                Dictionary <string, string> requiredRgTags = new Dictionary <string, string>();
                foreach (string tagKey in requiredTagsList)
                {
                    if (rg.Tags != null && rg.Tags.ContainsKey(tagKey))
                    {
                        requiredRgTags.Add(tagKey, rg.Tags[tagKey]);
                    }
                }

                if (requiredRgTags.Count != requiredTagsList.Count())
                {
                    _log.Warning("Resource group: " + rg.Name + " does not have required tags.");
                    stats.ResourceGroupsSkipped += 1;
                }
                else
                {
                    IEnumerable <GenericResourceInner> resources = await _client.Resources.ListByResourceGroupAsync(rg.Name);

                    stats.ResourceItemsTotal = resources.Count();

                    foreach (var resource in resources)
                    {
                        // InvalidTagResource invalidResourceMatch = invalidTagResourcesQuery.Results.Where(x => x.Type == resource.Type).FirstOrDefault();
                        InvalidTagResource invalidType = invalidTypes.Where(x => x.Type == resource.Type).FirstOrDefault();

                        if (invalidType == null)
                        {
                            string apiVersion;

                            try
                            {
                                apiVersion = await GetApiVersion(_client, resource.Type);
                            }
                            catch (Exception ex)
                            {
                                _log.Error(ex.Message);
                                break;
                            }

                            var result = SetTags(resource.Tags, requiredRgTags);

                            if (result.Count > 0)
                            {
                                stats.ResourceItemsWithUpdates += 1;
                                resource.Tags = result;
                                ResourceItem newItem = new ResourceItem {
                                    Id           = resource.Id,
                                    ApiVersion   = apiVersion,
                                    Location     = resource.Location,
                                    Tags         = resource.Tags,
                                    Type         = resource.Type,
                                    Subscription = subscriptionId
                                };

                                string messageText = JsonConvert.SerializeObject(newItem);
                                _outQueue.Add(messageText);
                                _log.Info("Requesting tags for: " + resource.Id);
                            }
                            else
                            {
                                stats.ResourceItemsSkipped += 1;
                            }
                        }
                        else
                        {
                            _log.Warning("Item type does not support tagging: " + resource.Type);
                            stats.ResourceItemsSkipped += 1;
                        }
                    }
                }
            }
        }
示例#6
0
        static async Task ProcessResourceGroups(IEnumerable <string> requiredTagsList, List <InvalidTagResource> invalidTypes, string subscriptionId, AuditStats stats)
        {
            var resourceGroups = await _resourceManager.GetResourceGroups(subscriptionId);

            stats.ResourceGroupsTotal = resourceGroups.Count;

            foreach (var rg in resourceGroups)
            {
                _log.Info("*** Resource Group: " + rg.Name);
                var tagsToSync = TagService.GetRequiredTags((Dictionary <string, string>)rg.Tags, requiredTagsList);

                if (tagsToSync.Count < 1)
                {
                    _log.Warning("Resource group: " + rg.Name + " does not have required tags.");
                    stats.ResourceGroupsSkipped += 1;
                }
                else
                {
                    List <ResourceItem> resources = await _resourceManager.GetResources(rg.Name, subscriptionId, invalidTypes.Select(t => t.Type).ToList());

                    stats.ResourceItemsTotal = resources.Count();

                    foreach (var resource in resources)
                    {
                        var result = TagService.GetTagUpdates(resource.Tags.ToDictionary(x => x.Key, x => x.Value), tagsToSync);

                        if (result.Count > 0)
                        {
                            stats.ResourceItemsWithUpdates += 1;
                            resource.Tags = result;
                            string messageText = JsonConvert.SerializeObject(resource);
                            _log.Info("Requesting tags for: " + resource.Id);
                            _outQueue.Add(messageText);
                        }
                        else
                        {
                            stats.ResourceItemsSkipped += 1;
                        }
                    }
                }
            }
        }