Merge pull request #666 from HelenCampbell/release
[puppet-modules/puppetlabs-apt.git] / spec / acceptance / apt_key_provider_spec.rb
1 require 'spec_helper_acceptance'
2
3 PUPPETLABS_GPG_KEY_SHORT_ID    = 'EF8D349F'
4 PUPPETLABS_GPG_KEY_LONG_ID     = '7F438280EF8D349F'
5 PUPPETLABS_GPG_KEY_FINGERPRINT = '6F6B15509CF8E59E6E469F327F438280EF8D349F'
6 PUPPETLABS_APT_URL             = 'apt.puppetlabs.com'
7 PUPPETLABS_GPG_KEY_FILE        = 'DEB-GPG-KEY-puppet'
8 CENTOS_GPG_KEY_SHORT_ID        = 'C105B9DE'
9 CENTOS_GPG_KEY_LONG_ID         = '0946FCA2C105B9DE'
10 CENTOS_GPG_KEY_FINGERPRINT     = 'C1DAC52D1664E8A4386DBA430946FCA2C105B9DE'
11 CENTOS_REPO_URL                = 'ftp.cvut.cz/centos'
12 CENTOS_GPG_KEY_FILE            = 'RPM-GPG-KEY-CentOS-6'
13
14 SHOULD_NEVER_EXIST_ID          = 'EF8D349F'
15
16 KEY_CHECK_COMMAND              = "apt-key adv --list-keys --with-colons --fingerprint | grep "
17 PUPPETLABS_KEY_CHECK_COMMAND   = "#{KEY_CHECK_COMMAND} #{PUPPETLABS_GPG_KEY_FINGERPRINT}"
18 CENTOS_KEY_CHECK_COMMAND       = "#{KEY_CHECK_COMMAND} #{CENTOS_GPG_KEY_FINGERPRINT}"
19
20 MAX_TIMEOUT_RETRY              = 3
21 TIMEOUT_RETRY_WAIT             = 5
22 TIMEOUT_ERROR_MATCHER    = /no valid OpenPGP data found/
23
24 describe 'apt_key' do
25   before(:each) do
26     # Delete twice to make sure everything is cleaned
27     # up after the short key collision
28     shell("apt-key del #{PUPPETLABS_GPG_KEY_SHORT_ID}",
29           :acceptable_exit_codes => [0,1,2])
30     shell("apt-key del #{PUPPETLABS_GPG_KEY_SHORT_ID}",
31           :acceptable_exit_codes => [0,1,2])
32   end
33
34   describe 'default options' do
35     key_versions = {
36       '32bit key id'                        => "#{PUPPETLABS_GPG_KEY_SHORT_ID}",
37       '64bit key id'                        => "#{PUPPETLABS_GPG_KEY_LONG_ID}",
38       '160bit key fingerprint'              => "#{PUPPETLABS_GPG_KEY_FINGERPRINT}",
39       '32bit lowercase key id'              => "#{PUPPETLABS_GPG_KEY_SHORT_ID.downcase}",
40       '64bit lowercase key id'              => "#{PUPPETLABS_GPG_KEY_LONG_ID.downcase}",
41       '160bit lowercase key fingerprint'    => "#{PUPPETLABS_GPG_KEY_FINGERPRINT.downcase}",
42       '0x formatted 32bit key id'           => "0x#{PUPPETLABS_GPG_KEY_SHORT_ID}",
43       '0x formatted 64bit key id'           => "0x#{PUPPETLABS_GPG_KEY_LONG_ID}",
44       '0x formatted 160bit key fingerprint' => "0x#{PUPPETLABS_GPG_KEY_FINGERPRINT}",
45       '0x formatted 32bit lowercase key id' => "0x#{PUPPETLABS_GPG_KEY_SHORT_ID.downcase}",
46       '0x formatted 64bit lowercase key id' => "0x#{PUPPETLABS_GPG_KEY_LONG_ID.downcase}",
47       '0x formatted 160bit lowercase key fingerprint' => "0x#{PUPPETLABS_GPG_KEY_FINGERPRINT.downcase}",
48     }
49
50     key_versions.each do |key, value|
51       context "#{key}" do
52         it 'works' do
53           pp = <<-EOS
54           apt_key { 'puppetlabs':
55             id     => '#{value}',
56             ensure => 'present',
57           }
58           EOS
59
60           apply_manifest(pp, :catch_failures => true)
61           apply_manifest(pp, :catch_changes => true)
62           shell(PUPPETLABS_KEY_CHECK_COMMAND)
63         end
64       end
65     end
66
67     context 'invalid length key id' do
68       it 'fails' do
69         pp = <<-EOS
70         apt_key { 'puppetlabs':
71           id => '8280EF8D349F',
72         }
73         EOS
74
75         apply_manifest(pp, :expect_failures => true) do |r|
76           expect(r.stderr).to match(/Valid values match/)
77         end
78       end
79     end
80   end
81
82   describe 'ensure =>' do
83     context 'absent' do
84       it 'is removed' do
85         pp = <<-EOS
86         apt_key { 'centos':
87           id     => '#{CENTOS_GPG_KEY_LONG_ID}',
88           ensure => 'absent',
89         }
90         EOS
91
92         # Install the key first (retry because key pool may timeout)
93         retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do
94           shell("apt-key adv --keyserver hkps.pool.sks-keyservers.net \
95               --recv-keys #{CENTOS_GPG_KEY_FINGERPRINT}")
96         end
97         shell(CENTOS_KEY_CHECK_COMMAND)
98
99         # Time to remove it using Puppet
100         apply_manifest(pp, :catch_failures => true)
101         apply_manifest(pp, :catch_changes => true)
102
103         shell(CENTOS_KEY_CHECK_COMMAND,
104               :acceptable_exit_codes => [1])
105
106         # Re-Install the key (retry because key pool may timeout)
107         retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do
108           shell("apt-key adv --keyserver hkps.pool.sks-keyservers.net \
109                 --recv-keys #{CENTOS_GPG_KEY_FINGERPRINT}")
110         end
111       end
112     end
113
114     context 'absent, added with long key', :unless => (fact('operatingsystem') == 'Debian' and fact('operatingsystemmajrelease') == '6') do
115       it 'is removed' do
116         pp = <<-EOS
117         apt_key { 'puppetlabs':
118           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
119           ensure => 'absent',
120         }
121         EOS
122
123         # Install the key first (retry because key pool may timeout)
124         retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do
125           shell("apt-key adv --keyserver hkps.pool.sks-keyservers.net \
126                 --recv-keys #{PUPPETLABS_GPG_KEY_LONG_ID}")
127         end
128
129         shell(PUPPETLABS_KEY_CHECK_COMMAND)
130
131         # Time to remove it using Puppet
132         apply_manifest(pp, :catch_failures => true)
133         apply_manifest(pp, :catch_changes => true)
134
135         shell(PUPPETLABS_KEY_CHECK_COMMAND,
136               :acceptable_exit_codes => [1])
137       end
138     end
139   end
140
141   describe 'content =>' do
142     context 'puppetlabs gpg key' do
143       it 'works' do
144         pp = <<-EOS
145           apt_key { 'puppetlabs':
146             id      => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}',
147             ensure  => 'present',
148             content => "-----BEGIN PGP PUBLIC KEY BLOCK-----
149
150 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
197 3xJn
198 =mMjt
199 -----END PGP PUBLIC KEY BLOCK-----",
200           }
201         EOS
202
203         #Apply the manifest (Retry if timeout error is received from key pool)
204         retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do
205           apply_manifest(pp, :catch_failures => true)
206         end
207
208         apply_manifest(pp, :catch_changes => true)
209         shell(PUPPETLABS_KEY_CHECK_COMMAND)
210       end
211     end
212
213
214     context 'multiple keys' do
215       it 'runs without errors' do
216         pp = <<-EOS
217           apt_key { 'puppetlabs':
218             id      => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}',
219             ensure  => 'present',
220             content => "-----BEGIN PGP PUBLIC KEY BLOCK-----
221 Version: GnuPG v1
222
223 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
463 FPfZDNCu/TXoqyJk7434jJrcHgPryzrHFBLfEmc=
464 =TREp
465 -----END PGP PUBLIC KEY BLOCK----- ",
466           }
467         EOS
468
469         apply_manifest(pp, :catch_failures => true)
470         apply_manifest(pp, :catch_changes => true)
471         shell(PUPPETLABS_KEY_CHECK_COMMAND)
472       end
473     end
474
475     context 'bogus key' do
476       it 'fails' do
477         pp = <<-EOS
478         apt_key { 'puppetlabs':
479           id      => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
480           ensure  => 'present',
481           content => 'For posterity: such content, much bogus, wow',
482         }
483         EOS
484
485         apply_manifest(pp, :expect_failures => true) do |r|
486           expect(r.stderr).to match(/no valid OpenPGP data found/)
487         end
488       end
489     end
490   end
491
492   describe 'server =>' do
493     context 'hkps.pool.sks-keyservers.net' do
494       it 'works' do
495         pp = <<-EOS
496         apt_key { 'puppetlabs':
497           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
498           ensure => 'present',
499           server => 'hkps.pool.sks-keyservers.net',
500         }
501         EOS
502
503         #Apply the manifest (Retry if timeout error is received from key pool)
504         retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do
505           apply_manifest(pp, :catch_failures => true)
506         end
507
508         apply_manifest(pp, :catch_changes => true)
509         shell(PUPPETLABS_KEY_CHECK_COMMAND)
510       end
511     end
512
513     context 'hkp://hkps.pool.sks-keyservers.net:80' do
514       it 'works' do
515         pp = <<-EOS
516         apt_key { 'puppetlabs':
517           id     => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}',
518           ensure => 'present',
519           server => 'hkp://hkps.pool.sks-keyservers.net:80',
520         }
521         EOS
522
523         retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do
524           apply_manifest(pp, :catch_failures => true)
525         end
526
527         apply_manifest(pp, :catch_changes => true)
528         shell(PUPPETLABS_KEY_CHECK_COMMAND)
529       end
530     end
531
532     context 'nonexistant.key.server' do
533       it 'fails' do
534         pp = <<-EOS
535         apt_key { 'puppetlabs':
536           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
537           ensure => 'present',
538           server => 'nonexistant.key.server',
539         }
540         EOS
541
542         apply_manifest(pp, :expect_failures => true) do |r|
543           expect(r.stderr).to match(/(Host not found|Couldn't resolve host)/)
544         end
545       end
546     end
547
548     context 'key server start with dot' do
549       it 'fails' do
550         pp = <<-EOS
551         apt_key { 'puppetlabs':
552           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
553           ensure => 'present',
554           server => '.pgp.key.server',
555         }
556         EOS
557
558         apply_manifest(pp, :expect_failures => true) do |r|
559           expect(r.stderr).to match(/Invalid value \".pgp.key.server\"/)
560         end
561       end
562     end
563   end
564
565   describe 'source =>' do
566     context 'http://' do
567       it 'works' do
568         pp = <<-EOS
569         apt_key { 'puppetlabs':
570           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
571           ensure => 'present',
572           source => 'http://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
573         }
574         EOS
575
576         apply_manifest(pp, :catch_failures => true)
577         apply_manifest(pp, :catch_changes => true)
578         shell(PUPPETLABS_KEY_CHECK_COMMAND)
579       end
580
581       it 'works with userinfo' do
582         pp = <<-EOS
583         apt_key { 'puppetlabs':
584           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
585           ensure => 'present',
586           source => 'http://dummyuser:dummypassword@#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
587         }
588         EOS
589
590         apply_manifest(pp, :catch_failures => true)
591         apply_manifest(pp, :catch_changes => true)
592         shell(PUPPETLABS_KEY_CHECK_COMMAND)
593       end
594
595       it 'fails with a 404' do
596         pp = <<-EOS
597         apt_key { 'puppetlabs':
598           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
599           ensure => 'present',
600           source => 'http://#{PUPPETLABS_APT_URL}/herpderp.gpg',
601         }
602         EOS
603
604         apply_manifest(pp, :expect_failures => true) do |r|
605           expect(r.stderr).to match(/404 Not Found/)
606         end
607       end
608
609       it 'fails with a socket error' do
610         pp = <<-EOS
611         apt_key { 'puppetlabs':
612           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
613           ensure => 'present',
614           source => 'http://apt.puppetlabss.com/herpderp.gpg',
615         }
616         EOS
617
618         apply_manifest(pp, :expect_failures => true) do |r|
619           expect(r.stderr).to match(/could not resolve/)
620         end
621       end
622     end
623
624     context 'ftp://' do
625       before(:each) do
626         shell("apt-key del #{CENTOS_GPG_KEY_LONG_ID}",
627               :acceptable_exit_codes => [0,1,2])
628       end
629
630       it 'works' do
631         pp = <<-EOS
632         apt_key { 'CentOS 6':
633           id     => '#{CENTOS_GPG_KEY_LONG_ID}',
634           ensure => 'present',
635           source => 'ftp://#{CENTOS_REPO_URL}/#{CENTOS_GPG_KEY_FILE}',
636         }
637         EOS
638
639         apply_manifest(pp, :catch_failures => true)
640         apply_manifest(pp, :catch_changes => true)
641         shell(CENTOS_KEY_CHECK_COMMAND)
642       end
643
644       it 'fails with a 550' do
645         pp = <<-EOS
646         apt_key { 'CentOS 6':
647           id     => '#{SHOULD_NEVER_EXIST_ID}',
648           ensure => 'present',
649           source => 'ftp://#{CENTOS_REPO_URL}/herpderp.gpg',
650         }
651         EOS
652
653         apply_manifest(pp, :expect_failures => true) do |r|
654           expect(r.stderr).to match(/550 Failed to open/)
655         end
656       end
657
658       it 'fails with a socket error' do
659         pp = <<-EOS
660         apt_key { 'puppetlabs':
661           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
662           ensure => 'present',
663           source => 'ftp://apt.puppetlabss.com/herpderp.gpg',
664         }
665         EOS
666
667         apply_manifest(pp, :expect_failures => true) do |r|
668           expect(r.stderr).to match(/could not resolve/)
669         end
670       end
671     end
672
673     context 'https://' do
674       it 'works' do
675         pp = <<-EOS
676         apt_key { 'puppetlabs':
677           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
678           ensure => 'present',
679           source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
680         }
681         EOS
682
683         apply_manifest(pp, :catch_failures => true)
684         apply_manifest(pp, :catch_changes => true)
685         shell(PUPPETLABS_KEY_CHECK_COMMAND)
686       end
687
688       it 'works with userinfo' do
689         pp = <<-EOS
690         apt_key { 'puppetlabs':
691           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
692           ensure => 'present',
693           source => 'https://dummyuser:dummypassword@#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
694         }
695         EOS
696
697         apply_manifest(pp, :catch_failures => true)
698         apply_manifest(pp, :catch_changes => true)
699         shell(PUPPETLABS_KEY_CHECK_COMMAND)
700       end
701
702       it 'fails with a 404' do
703         pp = <<-EOS
704         apt_key { 'puppetlabs':
705           id     => '#{SHOULD_NEVER_EXIST_ID}',
706           ensure => 'present',
707           source => 'https://#{PUPPETLABS_APT_URL}/herpderp.gpg',
708         }
709         EOS
710
711         apply_manifest(pp, :expect_failures => true) do |r|
712           expect(r.stderr).to match(/404 Not Found/)
713         end
714       end
715
716       it 'fails with a socket error' do
717         pp = <<-EOS
718         apt_key { 'puppetlabs':
719           id     => '#{SHOULD_NEVER_EXIST_ID}',
720           ensure => 'present',
721           source => 'https://apt.puppetlabss.com/herpderp.gpg',
722         }
723         EOS
724
725         apply_manifest(pp, :expect_failures => true) do |r|
726           expect(r.stderr).to match(/could not resolve/)
727         end
728       end
729     end
730
731     context '/path/that/exists' do
732       before(:each) do
733         shell("curl -o /tmp/puppetlabs-pubkey.gpg \
734               http://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}")
735       end
736
737       after(:each) do
738         shell('rm /tmp/puppetlabs-pubkey.gpg')
739       end
740
741       it 'works' do
742         pp = <<-EOS
743         apt_key { 'puppetlabs':
744           id     => 'EF8D349F',
745           ensure => 'present',
746           source => '/tmp/puppetlabs-pubkey.gpg',
747         }
748         EOS
749
750         apply_manifest(pp, :catch_failures => true)
751         apply_manifest(pp, :catch_changes => true)
752         shell(PUPPETLABS_KEY_CHECK_COMMAND)
753       end
754     end
755
756     context '/path/that/does/not/exist' do
757       it 'fails' do
758         pp = <<-EOS
759         apt_key { 'puppetlabs':
760           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
761           ensure => 'present',
762           source => '/tmp/totally_bogus.file',
763         }
764         EOS
765
766         apply_manifest(pp, :expect_failures => true) do |r|
767           expect(r.stderr).to match(/does not exist/)
768         end
769       end
770     end
771
772     context '/path/that/exists/with/bogus/content' do
773       before(:each) do
774         shell('echo "here be dragons" > /tmp/fake-key.gpg')
775       end
776
777       after(:each) do
778         shell('rm /tmp/fake-key.gpg')
779       end
780       it 'fails' do
781         pp = <<-EOS
782         apt_key { 'puppetlabs':
783           id     => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
784           ensure => 'present',
785           source => '/tmp/fake-key.gpg',
786         }
787         EOS
788
789         apply_manifest(pp, :expect_failures => true) do |r|
790           expect(r.stderr).to match(/no valid OpenPGP data found/)
791         end
792       end
793     end
794   end
795
796   describe 'options =>' do
797     context 'debug' do
798       it 'works' do
799         pp = <<-EOS
800         apt_key { 'puppetlabs':
801           id      => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
802           ensure  => 'present',
803           options => 'debug',
804         }
805         EOS
806
807         apply_manifest(pp, :catch_failures => true)
808         apply_manifest(pp, :catch_changes => true)
809         shell(PUPPETLABS_KEY_CHECK_COMMAND)
810       end
811     end
812   end
813
814   describe 'fingerprint validation against source/content' do
815     context 'fingerprint in id matches fingerprint from remote key' do
816       it 'works' do
817         pp = <<-EOS
818         apt_key { 'puppetlabs':
819           id      => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}',
820           ensure  => 'present',
821           source  => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
822         }
823         EOS
824
825         apply_manifest(pp, :catch_failures => true)
826         apply_manifest(pp, :catch_changes => true)
827       end
828     end
829
830     context 'fingerprint in id does NOT match fingerprint from remote key' do
831       it 'works' do
832         pp = <<-EOS
833         apt_key { 'puppetlabs':
834           id      => '6F6B15509CF8E59E6E469F327F438280EF8D9999',
835           ensure  => 'present',
836           source  => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
837         }
838         EOS
839
840         apply_manifest(pp, :expect_failures => true) do |r|
841           expect(r.stderr).to match(/do not match/)
842         end
843       end
844     end
845   end
846
847 end