File: pem_store_spec.rb

package info (click to toggle)
puppet-agent 7.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 19,092 kB
  • sloc: ruby: 245,074; sh: 456; makefile: 38; xml: 33
file content (160 lines) | stat: -rw-r--r-- 4,463 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# coding: utf-8
require 'spec_helper'
require 'puppet/x509'

class Puppet::X509::TestPemStore
  include Puppet::X509::PemStore
end

describe Puppet::X509::PemStore do
  include PuppetSpec::Files

  let(:subject) { Puppet::X509::TestPemStore.new }

  def with_unreadable_file
    path = tmpfile('pem_store')
    Puppet::FileSystem.touch(path)
    Puppet::FileSystem.chmod(0, path)
    yield path
  ensure
    Puppet::FileSystem.chmod(0600, path)
  end

  def with_unwritable_file(&block)
    if Puppet::Util::Platform.windows?
      with_unwritable_file_win32(&block)
    else
      with_unwritable_file_posix(&block)
    end
  end

  def with_unwritable_file_win32
    dir = tmpdir('pem_store')
    path = File.join(dir, 'unwritable')

    # if file handle is open, then file can't be written by other processes
    File.open(path, 'w') do |f|
      yield path
    end
  end

  def with_unwritable_file_posix
    dir = tmpdir('pem_store')
    path = File.join(dir, 'unwritable')
    # if directory is not executable/traverseable, then file can't be written to
    Puppet::FileSystem.chmod(0, dir)
    begin
      yield path
    ensure
      Puppet::FileSystem.chmod(0700, dir)
    end
  end

  let(:cert_path) { File.join(PuppetSpec::FIXTURE_DIR, 'ssl', 'netlock-arany-utf8.pem') }

  context 'loading' do
    it 'returns nil if it does not exist' do
      expect(subject.load_pem('/does/not/exist')).to be_nil
    end

    it 'returns the file content as UTF-8' do
      expect(
        subject.load_pem(cert_path)
      ).to match(/\ANetLock Arany \(Class Gold\) Főtanúsítvány/)
    end

    it 'raises EACCES if the file is unreadable' do
      with_unreadable_file do |path|
        expect {
          subject.load_pem(path)
        }.to raise_error(Errno::EACCES, /Permission denied/)
      end
    end
  end

  context 'saving' do
    let(:path) { tmpfile('pem_store') }

    it 'writes the file content as UTF-8' do
      # read the file directly to preserve the comments
      utf8 = File.read(cert_path, encoding: 'UTF-8')

      subject.save_pem(utf8, path)

      expect(
        File.read(path, :encoding => 'UTF-8')
      ).to match(/\ANetLock Arany \(Class Gold\) Főtanúsítvány/)
    end

    it 'never changes the owner and group on Windows', if: Puppet::Util::Platform.windows? do
      expect(FileUtils).not_to receive(:chown)

      subject.save_pem('PEM', path, owner: 'Administrator', group: 'None')
    end

    it 'changes the owner and group when running as root', unless: Puppet::Util::Platform.windows? do
      allow(Puppet.features).to receive(:root?).and_return(true)
      expect(FileUtils).to receive(:chown).with('root', 'root', path)

      subject.save_pem('PEM', path, owner: 'root', group: 'root')
    end

    it 'does not change owner and group when running not as roo', unless: Puppet::Util::Platform.windows? do
      allow(Puppet.features).to receive(:root?).and_return(false)
      expect(FileUtils).not_to receive(:chown)

      subject.save_pem('PEM', path, owner: 'root', group: 'root')
    end

    it 'allows a mode of 0600 to be specified', unless: Puppet::Util::Platform.windows? do
      subject.save_pem('PEM', path, mode: 0600)

      expect(File.stat(path).mode & 0777).to eq(0600)
    end

    it 'defaults the mode to 0644' do
      subject.save_pem('PEM', path)

      expect(File.stat(path).mode & 0777).to eq(0644)
    end

    it 'raises EACCES if the file is unwritable' do
      with_unwritable_file do |path|
        expect {
          subject.save_pem('', path)
        }.to raise_error(Errno::EACCES, /Permission denied/)
      end
    end

    it 'raises if the directory does not exist' do
      dir = tmpdir('pem_store')
      Dir.unlink(dir)

      expect {
        subject.save_pem('', File.join(dir, 'something'))
      }.to raise_error(Errno::ENOENT, /No such file or directory/)
    end
  end

  context 'deleting' do
    it 'returns false if the file does not exist' do
      expect(subject.delete_pem('/does/not/exist')).to eq(false)
    end

    it 'returns true if the file exists' do
      path = tmpfile('pem_store')
      FileUtils.touch(path)

      expect(subject.delete_pem(path)).to eq(true)
      expect(File).to_not be_exist(path)
    end

    it 'raises EACCES if the file is undeletable' do
      with_unwritable_file do |path|
        expect {
          subject.delete_pem(path)
        }.to raise_error(Errno::EACCES, /Permission denied/)
      end
    end
  end
end