{"action":"opened","number":3614,"pull_request":{"url":"https://api.github.com/repos/puppetlabs/puppet/pulls/3614","id":29334453,"html_url":"https://github.com/puppetlabs/puppet/pull/3614","diff_url":"https://github.com/puppetlabs/puppet/pull/3614.diff","patch_url":"https://github.com/puppetlabs/puppet/pull/3614.patch","issue_url":"https://api.github.com/repos/puppetlabs/puppet/issues/3614","number":3614,"state":"open","locked":false,"title":"Add PKINIT support to Puppet CA","user":{"login":"michaelweiser","id":1473703,"avatar_url":"https://avatars.githubusercontent.com/u/1473703?v=3","gravatar_id":"","url":"https://api.github.com/users/michaelweiser","html_url":"https://github.com/michaelweiser","followers_url":"https://api.github.com/users/michaelweiser/followers","following_url":"https://api.github.com/users/michaelweiser/following{/other_user}","gists_url":"https://api.github.com/users/michaelweiser/gists{/gist_id}","starred_url":"https://api.github.com/users/michaelweiser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaelweiser/subscriptions","organizations_url":"https://api.github.com/users/michaelweiser/orgs","repos_url":"https://api.github.com/users/michaelweiser/repos","events_url":"https://api.github.com/users/michaelweiser/events{/privacy}","received_events_url":"https://api.github.com/users/michaelweiser/received_events","type":"User","site_admin":false},"body":"Hi,\r\n\r\nI've written up this patch to enable the Puppet CA to deal with Kerberos-PKINIT-enabled certificate requests and allow the clients to request those extensions.\r\n\r\nThose certificates can be used on the client to obtain Kerberos tickets using just the certificate and private key and no password or keytab:\r\n\r\n```\r\nroot@client:~# fqdn=`hostname -f`\r\nroot@client:~# pupssl=/var/lib/puppet/ssl\r\nroot@client:~# kinit -X \"X509_user_identity=FILE:$pupssl/certs/${fqdn}.pem,$pupssl/private_keys/${fqdn}.pem\" $fqdn\r\nroot@client:~# klist\r\nTicket cache: FILE:/tmp/krb5cc_0\r\nDefault principal: client.example.org@EXAMPLE.ORG\r\n\r\nValid starting       Expires              Service principal\r\n02/15/2015 12:56:21  02/15/2015 22:56:21  krbtgt/EXAMPLE.ORG@EXAMPLE.ORG\r\n        renew until 02/16/2015 12:56:21\r\n```\r\n\r\nThis can easily be made into a cron job so the machine always has a TGT floating around for accessing kerberised services!\r\n\r\nI am also using this in an environment where I run Kerberos-enabled services and want to allow them to auto-enroll with the KDC and create their principals and keytabs. Using PKINIT with the Puppet machine certificates and making the machine principal a very limited Kerberos administrator for it's own principal namespace (*/$fqdn@$realm) allows for this very elegantly, securely and without any additional password storage and passing.\r\n\r\nWith the KDC extension it is also possible to run a PKINIT-enabled KDC with just the Puppet client certificate and key.\r\n\r\nSince the whole PKINIT certificate extension thing is IMO highly inaccessible to people with non-ASN.1-capable brains (i.e. everyone) I think it would be a killer feature for Puppet to support this with just a few command line options out of the box.\r\n\r\nUsage:\r\n```\r\nroot@freshlybootstrappedbox # puppet agent -t --request_pkinit_client\r\n(or option in puppet.conf)\r\n```\r\n\r\n```\r\nroot@puppetmaster:~# puppet cert sign freshlybootstrappedbox.example.org\r\nError: CSR 'freshlybootstrappedbox.example.org' contains subject alternative names (PKINIT-Client:freshlybootstrappedbox.example.org@EXAMPLE.ORG), which are disallowed. Use `puppet cert --allow-dns-alt-names sign freshlybootstrappedbox.example.org` to sign this request.\r\nroot@puppetmaster:~# puppet cert sign freshlybootstrappedbox.example.org --allow-dns-alt-names\r\nError: CSR 'freshlybootstrappedbox.example.org' contains a PKINIT extension for Kerberos clients (PKINIT-Client:freshlybootstrappedbox.example.org@EXAMPLE.ORG), which is disallowed. Use `puppet cert --allow-pkinit-client sign freshlybootstrappedbox.example.org` to sign this request.\r\nroot@puppetmaster:~# puppet cert sign freshlybootstrappedbox.example.org --allow-dns-alt-names --allow-pkinit-kdc --allow-pkinit-client\r\nNotice: Signed certificate request for freshlybootstrappedbox.example.org\r\nNotice: Removing file Puppet::SSL::CertificateRequest freshlybootstrappedbox.example.org at '/var/lib/puppet/ssl/ca/requests/freshlybootstrappedbox.example.org.pem'\r\n```\r\n(This doubled acceptance procedure is intentional and IMO a nice opportunity for the admin to realise what he's doing.)\r\n\r\nI've developed this with Puppet 3.7.2 on Debian jessie and adjusted slightly for current master HEAD.\r\n\r\nExtend agent to allow requesting of Kerberos PKINIT certificate\r\nextensions for a configurable realm. Extend CA to check certificate\r\nrequests for those extensions, vet them and present the user with\r\ninstructions how to sign them.\r\n\r\nThis allows to distribute Kerberos PKINIT-ready certificates to Puppet\r\nclients, enabling easy bootstrapping of PKINIT-enabled KDCs as well as\r\nusing PKINIT from the Kerberos clients. Instructions on how to do so can\r\nbe found here:\r\nhttp://web.mit.edu/kerberos/krb5-devel/doc/admin/pkinit.html. A puppet\r\nmodule that does so fully automatically is available here:\r\nhttps://github.com/michaelweiser/puppet-module-kerberos.","created_at":"2015-02-15T13:01:52Z","updated_at":"2015-02-15T13:01:52Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/3614/commits","review_comments_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/3614/comments","review_comment_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments/{number}","comments_url":"https://api.github.com/repos/puppetlabs/puppet/issues/3614/comments","statuses_url":"https://api.github.com/repos/puppetlabs/puppet/statuses/711341e6b0e1427918b17877ecf563f97bd4fb95","head":{"label":"michaelweiser:master","ref":"master","sha":"711341e6b0e1427918b17877ecf563f97bd4fb95","user":{"login":"michaelweiser","id":1473703,"avatar_url":"https://avatars.githubusercontent.com/u/1473703?v=3","gravatar_id":"","url":"https://api.github.com/users/michaelweiser","html_url":"https://github.com/michaelweiser","followers_url":"https://api.github.com/users/michaelweiser/followers","following_url":"https://api.github.com/users/michaelweiser/following{/other_user}","gists_url":"https://api.github.com/users/michaelweiser/gists{/gist_id}","starred_url":"https://api.github.com/users/michaelweiser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaelweiser/subscriptions","organizations_url":"https://api.github.com/users/michaelweiser/orgs","repos_url":"https://api.github.com/users/michaelweiser/repos","events_url":"https://api.github.com/users/michaelweiser/events{/privacy}","received_events_url":"https://api.github.com/users/michaelweiser/received_events","type":"User","site_admin":false},"repo":{"id":30826057,"name":"puppet","full_name":"michaelweiser/puppet","owner":{"login":"michaelweiser","id":1473703,"avatar_url":"https://avatars.githubusercontent.com/u/1473703?v=3","gravatar_id":"","url":"https://api.github.com/users/michaelweiser","html_url":"https://github.com/michaelweiser","followers_url":"https://api.github.com/users/michaelweiser/followers","following_url":"https://api.github.com/users/michaelweiser/following{/other_user}","gists_url":"https://api.github.com/users/michaelweiser/gists{/gist_id}","starred_url":"https://api.github.com/users/michaelweiser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaelweiser/subscriptions","organizations_url":"https://api.github.com/users/michaelweiser/orgs","repos_url":"https://api.github.com/users/michaelweiser/repos","events_url":"https://api.github.com/users/michaelweiser/events{/privacy}","received_events_url":"https://api.github.com/users/michaelweiser/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/michaelweiser/puppet","description":"Server automation framework and application","fork":true,"url":"https://api.github.com/repos/michaelweiser/puppet","forks_url":"https://api.github.com/repos/michaelweiser/puppet/forks","keys_url":"https://api.github.com/repos/michaelweiser/puppet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/michaelweiser/puppet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/michaelweiser/puppet/teams","hooks_url":"https://api.github.com/repos/michaelweiser/puppet/hooks","issue_events_url":"https://api.github.com/repos/michaelweiser/puppet/issues/events{/number}","events_url":"https://api.github.com/repos/michaelweiser/puppet/events","assignees_url":"https://api.github.com/repos/michaelweiser/puppet/assignees{/user}","branches_url":"https://api.github.com/repos/michaelweiser/puppet/branches{/branch}","tags_url":"https://api.github.com/repos/michaelweiser/puppet/tags","blobs_url":"https://api.github.com/repos/michaelweiser/puppet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/michaelweiser/puppet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/michaelweiser/puppet/git/refs{/sha}","trees_url":"https://api.github.com/repos/michaelweiser/puppet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/michaelweiser/puppet/statuses/{sha}","languages_url":"https://api.github.com/repos/michaelweiser/puppet/languages","stargazers_url":"https://api.github.com/repos/michaelweiser/puppet/stargazers","contributors_url":"https://api.github.com/repos/michaelweiser/puppet/contributors","subscribers_url":"https://api.github.com/repos/michaelweiser/puppet/subscribers","subscription_url":"https://api.github.com/repos/michaelweiser/puppet/subscription","commits_url":"https://api.github.com/repos/michaelweiser/puppet/commits{/sha}","git_commits_url":"https://api.github.com/repos/michaelweiser/puppet/git/commits{/sha}","comments_url":"https://api.github.com/repos/michaelweiser/puppet/comments{/number}","issue_comment_url":"https://api.github.com/repos/michaelweiser/puppet/issues/comments/{number}","contents_url":"https://api.github.com/repos/michaelweiser/puppet/contents/{+path}","compare_url":"https://api.github.com/repos/michaelweiser/puppet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/michaelweiser/puppet/merges","archive_url":"https://api.github.com/repos/michaelweiser/puppet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/michaelweiser/puppet/downloads","issues_url":"https://api.github.com/repos/michaelweiser/puppet/issues{/number}","pulls_url":"https://api.github.com/repos/michaelweiser/puppet/pulls{/number}","milestones_url":"https://api.github.com/repos/michaelweiser/puppet/milestones{/number}","notifications_url":"https://api.github.com/repos/michaelweiser/puppet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/michaelweiser/puppet/labels{/name}","releases_url":"https://api.github.com/repos/michaelweiser/puppet/releases{/id}","created_at":"2015-02-15T11:52:07Z","updated_at":"2015-02-15T12:35:25Z","pushed_at":"2015-02-15T12:35:25Z","git_url":"git://github.com/michaelweiser/puppet.git","ssh_url":"git@github.com:michaelweiser/puppet.git","clone_url":"https://github.com/michaelweiser/puppet.git","svn_url":"https://github.com/michaelweiser/puppet","homepage":"http://www.puppetlabs.com/puppet/introduction/","size":107054,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"puppetlabs:master","ref":"master","sha":"38f9023661667478dc29bb27eaa48e9d11561b59","user":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":910744,"name":"puppet","full_name":"puppetlabs/puppet","owner":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/puppetlabs/puppet","description":"Server automation framework and application","fork":false,"url":"https://api.github.com/repos/puppetlabs/puppet","forks_url":"https://api.github.com/repos/puppetlabs/puppet/forks","keys_url":"https://api.github.com/repos/puppetlabs/puppet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/puppetlabs/puppet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/puppetlabs/puppet/teams","hooks_url":"https://api.github.com/repos/puppetlabs/puppet/hooks","issue_events_url":"https://api.github.com/repos/puppetlabs/puppet/issues/events{/number}","events_url":"https://api.github.com/repos/puppetlabs/puppet/events","assignees_url":"https://api.github.com/repos/puppetlabs/puppet/assignees{/user}","branches_url":"https://api.github.com/repos/puppetlabs/puppet/branches{/branch}","tags_url":"https://api.github.com/repos/puppetlabs/puppet/tags","blobs_url":"https://api.github.com/repos/puppetlabs/puppet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/puppetlabs/puppet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/puppetlabs/puppet/git/refs{/sha}","trees_url":"https://api.github.com/repos/puppetlabs/puppet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/puppetlabs/puppet/statuses/{sha}","languages_url":"https://api.github.com/repos/puppetlabs/puppet/languages","stargazers_url":"https://api.github.com/repos/puppetlabs/puppet/stargazers","contributors_url":"https://api.github.com/repos/puppetlabs/puppet/contributors","subscribers_url":"https://api.github.com/repos/puppetlabs/puppet/subscribers","subscription_url":"https://api.github.com/repos/puppetlabs/puppet/subscription","commits_url":"https://api.github.com/repos/puppetlabs/puppet/commits{/sha}","git_commits_url":"https://api.github.com/repos/puppetlabs/puppet/git/commits{/sha}","comments_url":"https://api.github.com/repos/puppetlabs/puppet/comments{/number}","issue_comment_url":"https://api.github.com/repos/puppetlabs/puppet/issues/comments/{number}","contents_url":"https://api.github.com/repos/puppetlabs/puppet/contents/{+path}","compare_url":"https://api.github.com/repos/puppetlabs/puppet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/puppetlabs/puppet/merges","archive_url":"https://api.github.com/repos/puppetlabs/puppet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/puppetlabs/puppet/downloads","issues_url":"https://api.github.com/repos/puppetlabs/puppet/issues{/number}","pulls_url":"https://api.github.com/repos/puppetlabs/puppet/pulls{/number}","milestones_url":"https://api.github.com/repos/puppetlabs/puppet/milestones{/number}","notifications_url":"https://api.github.com/repos/puppetlabs/puppet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/puppetlabs/puppet/labels{/name}","releases_url":"https://api.github.com/repos/puppetlabs/puppet/releases{/id}","created_at":"2010-09-14T19:26:44Z","updated_at":"2015-02-14T13:08:45Z","pushed_at":"2015-02-13T21:00:44Z","git_url":"git://github.com/puppetlabs/puppet.git","ssh_url":"git@github.com:puppetlabs/puppet.git","clone_url":"https://github.com/puppetlabs/puppet.git","svn_url":"https://github.com/puppetlabs/puppet","homepage":"http://www.puppetlabs.com/puppet/introduction/","size":107054,"stargazers_count":2964,"watchers_count":2964,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1267,"mirror_url":null,"open_issues_count":34,"forks":1267,"open_issues":34,"watchers":2964,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/3614"},"html":{"href":"https://github.com/puppetlabs/puppet/pull/3614"},"issue":{"href":"https://api.github.com/repos/puppetlabs/puppet/issues/3614"},"comments":{"href":"https://api.github.com/repos/puppetlabs/puppet/issues/3614/comments"},"review_comments":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/3614/comments"},"review_comment":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/3614/commits"},"statuses":{"href":"https://api.github.com/repos/puppetlabs/puppet/statuses/711341e6b0e1427918b17877ecf563f97bd4fb95"}},"merged":false,"mergeable":null,"mergeable_state":"unknown","merged_by":null,"comments":0,"review_comments":0,"commits":1,"additions":254,"deletions":27,"changed_files":9}}