unicorn-lockdown 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3ce59cddf9d01567fd8a064530c8d1cc54e45a96eecb54fbacfc376ed73c030
4
- data.tar.gz: 7e52c5cc4e6ed7673e84fdce2b67516284a49409d1e5a5adcc0a489a401f52e6
3
+ metadata.gz: 95a450be80782d592a0b960b2855f27332371039ede4ce5459df32a273985240
4
+ data.tar.gz: 9fb35bc3da1921fb3562bc4f1aa35962e08e628da61c33e14e9beac0b51696e4
5
5
  SHA512:
6
- metadata.gz: 42147643aa1eb541874fc61ef91152800617b91fb69e57f3765d0ea33f372f787a1fa9074eb9eb74400fe2f4ec4f699213875a0ec9446ac08ae6b8f1baad3e08
7
- data.tar.gz: c74fb916793633f0da277b1541cce8d9773a985035b0f36bfef9f545abf28e1c8f38796d0fd18da5525ab49ff2a46e4be428cc25384461e53c8615095b9a1ec9
6
+ metadata.gz: dc4ca6d927ab239a144cc3b3f4f405c03d0280f2e6a1e148f32a8ac416d48eb7ebc898f7b7a7ff09b67863ea0676d0b2b8660e212347fe4466691c000eca591a
7
+ data.tar.gz: 3240933f222409c814dac82049c055cfd183c275e1a998cf2aa10f539d36a1c9dbec5abef32b35f8c5729dc32d9cc87e506e9d4bf6b2a602e026314dc7e3bd70
@@ -0,0 +1,9 @@
1
+ = 0.10.0 (2018-05-21)
2
+
3
+ * Use Mail.eager_autoload! if using the mail gem (jeremyevans)
4
+
5
+ * Add bin files to gemspec (jeremyevans)
6
+
7
+ = 0.9.0 (2018-05-02)
8
+
9
+ * Initial public release
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'etc'
4
+ require 'optparse'
5
+
6
+ def sh(*args)
7
+ puts "Running: #{args.join(' ')}"
8
+ system(*args) || raise("Error while running: #{args.join(' ')}")
9
+ end
10
+
11
+ unicorn = ''
12
+ rackup = ''
13
+ unicorn_file = 'unicorn.conf'
14
+ dir = nil
15
+ user = nil
16
+ new_user_uid = nil
17
+ owner = nil
18
+ owner_uid = nil
19
+ owner_gid = nil
20
+
21
+ options = OptionParser.new do |opts|
22
+ opts.banner = "Usage: unicorn-lockdown-add [options] app_name"
23
+ opts.separator "Options:"
24
+
25
+ opts.on_tail("-h", "-?", "--help", "Show this message") do
26
+ puts opts
27
+ exit
28
+ end
29
+
30
+ opts.on("-c rackup_file", "rackup configuration file") do |v|
31
+ rackup = "rackup_file=#{v}\n"
32
+ end
33
+
34
+ opts.on("-d dir", "application directory name") do |v|
35
+ dir = v
36
+ end
37
+
38
+ opts.on("-f unicorn_file", "unicorn configuration file relative to application directory") do |v|
39
+ unicorn_file = v
40
+ unicorn = "unicorn_conf=#{v}\n"
41
+ end
42
+
43
+ opts.on("-o owner", "operating system application owner") do |v|
44
+ owner = v
45
+ ent = Etc.getpwnam(v)
46
+ owner_uid = ent.uid
47
+ owner_gid = ent.gid
48
+ end
49
+
50
+ opts.on("-u user", "operating system user to run application") do |v|
51
+ user = v
52
+ end
53
+
54
+ opts.on("--uid uid", "user id to use if creating the user when -U is specified") do |v|
55
+ new_user_uid = Integer(v, 10)
56
+ end
57
+ end
58
+ options.parse!
59
+
60
+ app = ARGV.shift
61
+ dir ||= app
62
+ base_dir = dir
63
+
64
+ root_id = 0
65
+ bin_id = 7
66
+ www_id = 67
67
+
68
+ www_root = '/var/www'
69
+ dir = "#{www_root}/#{dir}"
70
+ etc_dir = "#{dir}/etc"
71
+ hosts_file = "#{etc_dir}/hosts"
72
+ resolv_file = "#{etc_dir}/resolv.conf"
73
+ rc_file = "/etc/rc.d/unicorn_#{app.tr('-', '_')}"
74
+ nginx_file = "/etc/nginx/#{app}.conf"
75
+ unicorn_conf_file = "#{dir}/#{unicorn_file}"
76
+ unicorn_log_file = "/var/log/unicorn/#{app}.log"
77
+ nginx_access_log_file = "/var/log/nginx/#{app}.access.log"
78
+ nginx_error_log_file = "/var/log/nginx/#{app}.error.log"
79
+
80
+ # Add application user if it doesn't exist
81
+ if user
82
+ passwd = begin
83
+ Etc.getpwnam(user)
84
+ rescue ArgumentError
85
+ args = ['/usr/sbin/useradd', '-d', '/var/empty', '-g', '=uid', '-G', '_unicorn', '-L', 'daemon', '-s', '/sbin/nologin']
86
+ if new_user_uid
87
+ args << '-u' << new_user_uid.to_s
88
+ end
89
+ args << user
90
+ sh(*args)
91
+ Etc.getpwnam(user)
92
+ end
93
+ app_uid = passwd.uid
94
+ end
95
+
96
+ # Create application directory and chroot directories if they doesn't exist
97
+ [dir, "#{dir}/var", "#{dir}/var/www", "#{dir}/etc", "#{dir}/public"].each do |d|
98
+ unless File.directory?(d)
99
+ puts "Creating #{d}"
100
+ Dir.mkdir(d)
101
+ File.chmod(0755, d)
102
+ File.chown(owner_uid, owner_gid, d) if owner
103
+ end
104
+ end
105
+
106
+ # DRY up file ownership code
107
+ setup_file_owner = lambda do |file|
108
+ File.chmod(0644, file)
109
+ File.chown(owner_uid, owner_gid, file) if owner
110
+ end
111
+
112
+ # Setup symlink to root so that the same paths work both when
113
+ # chrooted and when not chrooted.
114
+ chroot_link = "#{dir}#{dir}"
115
+ unless File.symlink?(chroot_link)
116
+ puts "Creating #{chroot_link}"
117
+ File.symlink('/', chroot_link)
118
+ end
119
+
120
+ # Add /etc/hosts files to chroot
121
+ unless File.file?(hosts_file)
122
+ puts "Creating #{hosts_file}"
123
+ File.binwrite(hosts_file, <<END)
124
+ 127.0.0.1 localhost
125
+ END
126
+ setup_file_owner.call(hosts_file)
127
+ end
128
+
129
+ # Add /etc/resolv.conf files to chroot
130
+ unless File.file?(resolv_file)
131
+ puts "Creating #{resolv_file}"
132
+ File.binwrite(resolv_file, <<END)
133
+ lookup file
134
+ END
135
+ setup_file_owner.call(resolv_file)
136
+ end
137
+
138
+ # Setup unicorn configuration file
139
+ unless File.file?(unicorn_conf_file)
140
+ puts "Creating #{unicorn_conf_file}"
141
+ File.binwrite(unicorn_conf_file, <<END)
142
+ require 'unicorn-lockdown'
143
+
144
+ Unicorn.lockdown(self,
145
+ :app=>#{app.inspect},
146
+ :user=>#{user.inspect}, # Set application user here
147
+ :pledge=>'rpath prot_exec inet unix', # More may be needed
148
+ :email=>'root' # update this with correct email
149
+ )
150
+ END
151
+ setup_file_owner.call(unicorn_conf_file)
152
+ end
153
+
154
+ # Setup /etc/nginx/* file for nginx configuration
155
+ unless File.file?(nginx_file)
156
+ puts "Creating #{nginx_file}"
157
+ File.binwrite(nginx_file, <<END)
158
+ upstream #{app}_unicorn {
159
+ server unix:/sockets/#{app}.sock fail_timeout=0;
160
+ }
161
+ server {
162
+ server_name #{app};
163
+ access_log #{nginx_access_log_file} main;
164
+ error_log #{nginx_error_log_file} warn;
165
+ root #{dir}/public;
166
+ error_page 500 503 /500.html;
167
+ error_page 502 504 /502.html;
168
+ proxy_set_header X-Real-IP $remote_addr;
169
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
170
+ proxy_set_header Host $http_host;
171
+ proxy_redirect off;
172
+ add_header X-Content-Type-Options nosniff;
173
+ add_header X-Frame-Options deny;
174
+ add_header X-XSS-Protection "1; mode=block";
175
+ try_files $uri @#{app}_unicorn;
176
+ location @#{app}_unicorn {
177
+ proxy_pass http://#{app}_unicorn;
178
+ }
179
+ }
180
+ END
181
+
182
+ setup_file_owner.call(nginx_file)
183
+ end
184
+
185
+ # Setup nginx log file
186
+ [nginx_access_log_file, nginx_error_log_file].each do |f|
187
+ unless File.file?(f)
188
+ puts "Creating #{f}"
189
+ File.binwrite(f, '')
190
+ File.chmod(0644, f)
191
+ File.chown(www_id, root_id, f)
192
+ end
193
+ end
194
+
195
+ # Setup unicorn log file
196
+ unless File.file?(unicorn_log_file)
197
+ puts "Creating #{unicorn_log_file}"
198
+ File.binwrite(unicorn_log_file, '')
199
+ File.chmod(0640, unicorn_log_file)
200
+ File.chown(app_uid, app_uid, unicorn_log_file) if app_uid
201
+ end
202
+
203
+ # Setup /etc/rc.d/unicorn_* file for daemon management
204
+ unless File.file?(rc_file)
205
+ puts "Creating #{rc_file}"
206
+ File.binwrite(rc_file, <<END)
207
+ #!/bin/ksh
208
+
209
+ unicorn_app=#{app}
210
+ unicorn_dir=#{dir}
211
+ #{unicorn}#{rackup}
212
+ . /etc/rc.d/rc.unicorn
213
+ END
214
+
215
+ File.chmod(0755, rc_file)
216
+ File.chown(root_id, bin_id, rc_file)
217
+ end
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'etc'
4
+
5
+ def sh(*args)
6
+ puts "Running: #{args.join(' ')}"
7
+ system(*args) || raise("Error while running: #{args.join(' ')}")
8
+ end
9
+
10
+ request_dir = '/var/www/requests'
11
+ socket_dir = '/var/www/sockets'
12
+ unicorn_log_dir = '/var/log/unicorn'
13
+ nginx_log_dir = "/var/log/nginx"
14
+ rc_unicorn_file = '/etc/rc.d/rc.unicorn'
15
+
16
+ unicorn_group = '_unicorn'
17
+ root_id = 0
18
+ daemon_id = 1
19
+ www_id = 67
20
+
21
+ # Add _unicorn group if it doesn't exist
22
+ group = begin
23
+ Etc.getgrnam(unicorn_group)
24
+ rescue ArgumentError
25
+ sh('groupadd', unicorn_group)
26
+ Etc.getgrnam(unicorn_group)
27
+ end
28
+ unicorn_group_id = group.gid
29
+
30
+ # Setup requests directory to hold per-request information for crash notifications
31
+ unless File.directory?(request_dir)
32
+ puts "Creating #{request_dir}"
33
+ Dir.mkdir(request_dir)
34
+ File.chmod(0700, request_dir)
35
+ File.chown(root_id, daemon_id, request_dir)
36
+ end
37
+
38
+ # Setup sockets directory to hold PostgreSQL database connection sockets
39
+ unless File.directory?(socket_dir)
40
+ puts "Creating #{socket_dir}"
41
+ Dir.mkdir(socket_dir)
42
+ File.chmod(0770, socket_dir)
43
+ File.chown(www_id, unicorn_group_id, socket_dir)
44
+ end
45
+
46
+ # Setup log directory to hold unicorn application logs
47
+ unless File.directory?(unicorn_log_dir)
48
+ puts "Creating #{unicorn_log_dir}"
49
+ Dir.mkdir(unicorn_log_dir)
50
+ File.chmod(0755, unicorn_log_dir)
51
+ File.chown(root_id, daemon_id, unicorn_log_dir)
52
+ end
53
+
54
+ # Setup log directory to hold nginx logs
55
+ unless File.directory?(nginx_log_dir)
56
+ puts "Creating #{nginx_log_dir}"
57
+ Dir.mkdir(nginx_log_dir)
58
+ File.chmod(0775, nginx_log_dir)
59
+ File.chown(www_id, root_id, nginx_log_dir)
60
+ end
61
+
62
+ # Setup rc.unicorn file
63
+ unless File.file?(rc_unicorn_file)
64
+ puts "Creating #{rc_unicorn_file}"
65
+ File.binwrite(rc_unicorn_file, File.binread(File.join(File.dirname(__dir__), 'files', 'rc.unicorn')))
66
+ File.chmod(0644, rc_unicorn_file)
67
+ File.chown(root_id, root_id, rc_unicorn_file)
68
+ end
@@ -133,12 +133,10 @@ class << Unicorn
133
133
  # that are probably needed at runtime. This must be done
134
134
  # before chrooting as attempting to load the constants after
135
135
  # chrooting will break things.
136
- #
137
- # This part is the most prone to breakage, as new versions
138
- # of the rack or mail libraries (or new libraries that
139
- # use autoload) could break things, as well as existing
140
- # applications using new features at runtime that were
141
- # not loaded at load time.
136
+
137
+ # Start with rack, which uses autoload for all constants.
138
+ # Most of rack's constants are not used at runtime, this
139
+ # lists the ones most commonly needed.
142
140
  Rack::Multipart
143
141
  Rack::Multipart::Parser
144
142
  Rack::Multipart::Generator
@@ -150,17 +148,13 @@ class << Unicorn
150
148
  Rack::Lint
151
149
  Rack::ShowExceptions
152
150
  end
151
+
152
+ # If using the mail library, eagerly autoload all constants.
153
+ # This costs about 9MB of memory, but the mail gem changes
154
+ # their autoloaded constants on a regular basis, so it's
155
+ # better to be safe than sorry.
153
156
  if defined?(Mail)
154
- Mail::Address
155
- Mail::AddressList
156
- Mail::Parsers::AddressListsParser
157
- Mail::ContentTransferEncodingElement
158
- Mail::ContentDispositionElement
159
- Mail::MessageIdsElement
160
- Mail::MimeVersionElement
161
- Mail::OptionalField
162
- Mail::ContentTypeElement
163
- Mail::SMTP
157
+ Mail.eager_autoload!
164
158
  end
165
159
 
166
160
  # Strip path prefixes from the reloader. This is only
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unicorn-lockdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-02 00:00:00.000000000 Z
11
+ date: 2018-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pledge
@@ -40,12 +40,17 @@ dependencies:
40
40
  version: '0'
41
41
  description:
42
42
  email: code@jeremyevans.net
43
- executables: []
43
+ executables:
44
+ - unicorn-lockdown-add
45
+ - unicorn-lockdown-setup
44
46
  extensions: []
45
47
  extra_rdoc_files: []
46
48
  files:
49
+ - CHANGELOG
47
50
  - MIT-LICENSE
48
51
  - README.rdoc
52
+ - bin/unicorn-lockdown-add
53
+ - bin/unicorn-lockdown-setup
49
54
  - files/rc.unicorn
50
55
  - lib/chrooter.rb
51
56
  - lib/rack/email_exceptions.rb