{"action":"created","comment":{"url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/comments/77692587","id":77692587,"diff_hunk":"@@ -0,0 +1,157 @@\n+﻿using NuGet.Services.KeyVault;\n+using System;\n+using System.Collections;\n+using System.Collections.Generic;\n+using System.ComponentModel;\n+using System.Linq;\n+using System.Text;\n+using System.Threading.Tasks;\n+\n+namespace NuGet.Jobs\n+{\n+    /// <summary>\n+    /// Maintains a cache of configuration or command line arguments injected with secrets using an ISecretInjector and refreshes itself at a specified interval.\n+    /// </summary>\n+    public class RefreshingArgumentsDictionary : IArgumentsDictionary\n+    {\n+        public const string RefreshArgsIntervalSec = \"CacheRefreshInterval\";\n+        private const int DefaultRefreshIntervalSec = 60 * 60 * 24; // 1 day (24 hrs)\n+\n+        private int _refreshArgsIntervalSec;\n+        private ISecretInjector _secretInjector;\n+\n+        private Dictionary<string, string> _unprocessedArguments;\n+        private Dictionary<string, Tuple<string, DateTime>> _injectedArguments;\n+\n+        public RefreshingArgumentsDictionary(ISecretInjector secretInjector, Dictionary<string, string> unprocessedArguments)\n+        {\n+            _secretInjector = secretInjector;\n+            _unprocessedArguments = unprocessedArguments;\n+            _injectedArguments = new Dictionary<string, Tuple<string, DateTime>>();\n+\n+            var refreshArgsIntervalSec = DefaultRefreshIntervalSec;\n+            if (_unprocessedArguments.ContainsKey(RefreshArgsIntervalSec))\n+            {\n+                int parsedRefreshInterval;\n+                if (int.TryParse(_unprocessedArguments[RefreshArgsIntervalSec], out parsedRefreshInterval)) refreshArgsIntervalSec = parsedRefreshInterval;","path":"src/NuGet.Services.KeyVault/RefreshingArgumentsDictionary.cs","position":36,"original_position":36,"commit_id":"a9415d4b58176aa2f345ab1e7c4e79ed4dcbe17e","original_commit_id":"a9415d4b58176aa2f345ab1e7c4e79ed4dcbe17e","user":{"login":"skofman1","id":16807822,"avatar_url":"https://avatars.githubusercontent.com/u/16807822?v=3","gravatar_id":"","url":"https://api.github.com/users/skofman1","html_url":"https://github.com/skofman1","followers_url":"https://api.github.com/users/skofman1/followers","following_url":"https://api.github.com/users/skofman1/following{/other_user}","gists_url":"https://api.github.com/users/skofman1/gists{/gist_id}","starred_url":"https://api.github.com/users/skofman1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skofman1/subscriptions","organizations_url":"https://api.github.com/users/skofman1/orgs","repos_url":"https://api.github.com/users/skofman1/repos","events_url":"https://api.github.com/users/skofman1/events{/privacy}","received_events_url":"https://api.github.com/users/skofman1/received_events","type":"User","site_admin":false},"body":">if (int.TryParse(_unprocessedArguments[RefreshArgsIntervalSec], out parsedRefreshInterval)) [](start = 16, length = 91)\r\n\r\nuse {}. No one line ifs. It's not readable.","created_at":"2016-09-06T18:32:33Z","updated_at":"2016-09-06T18:32:33Z","html_url":"https://github.com/NuGet/NuGet.Jobs/pull/64#discussion_r77692587","pull_request_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64","_links":{"self":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/comments/77692587"},"html":{"href":"https://github.com/NuGet/NuGet.Jobs/pull/64#discussion_r77692587"},"pull_request":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64"}}},"pull_request":{"url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64","id":82804500,"html_url":"https://github.com/NuGet/NuGet.Jobs/pull/64","diff_url":"https://github.com/NuGet/NuGet.Jobs/pull/64.diff","patch_url":"https://github.com/NuGet/NuGet.Jobs/pull/64.patch","issue_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/64","number":64,"state":"open","locked":false,"title":"Key rotation logic for jobs in NuGet.Jobs","user":{"login":"scottbommarito","id":18014088,"avatar_url":"https://avatars.githubusercontent.com/u/18014088?v=3","gravatar_id":"","url":"https://api.github.com/users/scottbommarito","html_url":"https://github.com/scottbommarito","followers_url":"https://api.github.com/users/scottbommarito/followers","following_url":"https://api.github.com/users/scottbommarito/following{/other_user}","gists_url":"https://api.github.com/users/scottbommarito/gists{/gist_id}","starred_url":"https://api.github.com/users/scottbommarito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scottbommarito/subscriptions","organizations_url":"https://api.github.com/users/scottbommarito/orgs","repos_url":"https://api.github.com/users/scottbommarito/repos","events_url":"https://api.github.com/users/scottbommarito/events{/privacy}","received_events_url":"https://api.github.com/users/scottbommarito/received_events","type":"User","site_admin":false},"body":"Replaced the ordinary `Dictionary<string, string>` that stored config arguments with a `RefreshingArgumentsDictionary` which refreshes at an interval that can be passed in through the command line.\r\n\r\nAdditionally, job initialization is now done with every run of the job loop, so that each job gets the updated config values when they are refreshed.\r\n\r\nI have tested that this works with Search.GenerateAuxilliaryData and looked at the rest of the jobs to make sure there is no caching of the `RefreshingArgumentsDictionary` by jobs (which would lead to key rotation bugs), but given the sheer number of jobs affected by this change I was unsure how to methodically test them.","created_at":"2016-08-25T22:30:06Z","updated_at":"2016-09-06T18:32:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4aabd79c9e445d4fd2e237ed848e6af0361ddc4f","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64/commits","review_comments_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64/comments","review_comment_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/64/comments","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/statuses/a9415d4b58176aa2f345ab1e7c4e79ed4dcbe17e","head":{"label":"NuGet:jobkeyrotation","ref":"jobkeyrotation","sha":"a9415d4b58176aa2f345ab1e7c4e79ed4dcbe17e","user":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"repo":{"id":23330255,"name":"NuGet.Jobs","full_name":"NuGet/NuGet.Jobs","owner":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NuGet/NuGet.Jobs","description":"","fork":false,"url":"https://api.github.com/repos/NuGet/NuGet.Jobs","forks_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/forks","keys_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/teams","hooks_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/hooks","issue_events_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/events{/number}","events_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/events","assignees_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/assignees{/user}","branches_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/branches{/branch}","tags_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/tags","blobs_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/refs{/sha}","trees_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/statuses/{sha}","languages_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/languages","stargazers_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/stargazers","contributors_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/contributors","subscribers_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/subscribers","subscription_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/subscription","commits_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/commits{/sha}","git_commits_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/commits{/sha}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/comments{/number}","issue_comment_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/comments{/number}","contents_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/contents/{+path}","compare_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/merges","archive_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/downloads","issues_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues{/number}","pulls_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls{/number}","milestones_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/milestones{/number}","notifications_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/labels{/name}","releases_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/releases{/id}","deployments_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/deployments","created_at":"2014-08-25T22:01:47Z","updated_at":"2016-07-11T13:35:22Z","pushed_at":"2016-09-06T12:48:09Z","git_url":"git://github.com/NuGet/NuGet.Jobs.git","ssh_url":"git@github.com:NuGet/NuGet.Jobs.git","clone_url":"https://github.com/NuGet/NuGet.Jobs.git","svn_url":"https://github.com/NuGet/NuGet.Jobs","homepage":null,"size":1738,"stargazers_count":7,"watchers_count":7,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":3,"forks":5,"open_issues":3,"watchers":7,"default_branch":"master"}},"base":{"label":"NuGet:dev","ref":"dev","sha":"4836403a7cfef8cbf4e69ed3344b9a76d3b5060a","user":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"repo":{"id":23330255,"name":"NuGet.Jobs","full_name":"NuGet/NuGet.Jobs","owner":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NuGet/NuGet.Jobs","description":"","fork":false,"url":"https://api.github.com/repos/NuGet/NuGet.Jobs","forks_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/forks","keys_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/teams","hooks_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/hooks","issue_events_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/events{/number}","events_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/events","assignees_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/assignees{/user}","branches_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/branches{/branch}","tags_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/tags","blobs_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/refs{/sha}","trees_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/statuses/{sha}","languages_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/languages","stargazers_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/stargazers","contributors_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/contributors","subscribers_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/subscribers","subscription_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/subscription","commits_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/commits{/sha}","git_commits_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/git/commits{/sha}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/comments{/number}","issue_comment_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/comments{/number}","contents_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/contents/{+path}","compare_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/merges","archive_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/downloads","issues_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues{/number}","pulls_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls{/number}","milestones_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/milestones{/number}","notifications_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/labels{/name}","releases_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/releases{/id}","deployments_url":"https://api.github.com/repos/NuGet/NuGet.Jobs/deployments","created_at":"2014-08-25T22:01:47Z","updated_at":"2016-07-11T13:35:22Z","pushed_at":"2016-09-06T12:48:09Z","git_url":"git://github.com/NuGet/NuGet.Jobs.git","ssh_url":"git@github.com:NuGet/NuGet.Jobs.git","clone_url":"https://github.com/NuGet/NuGet.Jobs.git","svn_url":"https://github.com/NuGet/NuGet.Jobs","homepage":null,"size":1738,"stargazers_count":7,"watchers_count":7,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":3,"forks":5,"open_issues":3,"watchers":7,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64"},"html":{"href":"https://github.com/NuGet/NuGet.Jobs/pull/64"},"issue":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/64"},"comments":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/issues/64/comments"},"review_comments":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64/comments"},"review_comment":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/pulls/64/commits"},"statuses":{"href":"https://api.github.com/repos/NuGet/NuGet.Jobs/statuses/a9415d4b58176aa2f345ab1e7c4e79ed4dcbe17e"}}}}
{"actor":{"display_login":"skofman1"}}