Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #29507 - Add puma-status for reporting #7578

Closed
wants to merge 2 commits into from

Conversation

sthirugn
Copy link
Contributor

@sthirugn sthirugn commented Apr 8, 2020

Note the foreman packaging change is still pending to include puma-status gem as rpm

@theforeman-bot
Copy link
Member

Issues: #29507

@sthirugn
Copy link
Contributor Author

sthirugn commented Apr 8, 2020

config/puma/production.rb Outdated Show resolved Hide resolved
bundler.d/service.rb Outdated Show resolved Hide resolved
config/puma/production.rb Outdated Show resolved Hide resolved
script/foreman-puma-status Outdated Show resolved Hide resolved
bundler.d/service.rb Outdated Show resolved Hide resolved
config/puma/production.rb Outdated Show resolved Hide resolved
config/puma/production.rb Outdated Show resolved Hide resolved
config/puma/production.rb Outdated Show resolved Hide resolved
config/puma/production.rb Outdated Show resolved Hide resolved
@sthirugn
Copy link
Contributor Author

sthirugn commented Apr 9, 2020

I squashed all the commits, test and the output is:

# systemctl restart foreman

# journalctl -u foreman -f
Apr 09 18:57:39 centos7-katello-nightly.apex.example.com systemd[1]: Started Foreman.
Apr 09 18:57:42 centos7-katello-nightly.apex.example.com foreman[7802]: /usr/share/foreman/lib/foreman.rb:8: warning: already initialized constant Foreman::UUID_REGEXP
Apr 09 18:57:42 centos7-katello-nightly.apex.example.com foreman[7802]: /usr/share/foreman/lib/foreman.rb:8: warning: previous definition of UUID_REGEXP was here
Apr 09 18:57:43 centos7-katello-nightly.apex.example.com foreman[7802]: => Booting Puma
Apr 09 18:57:43 centos7-katello-nightly.apex.example.com foreman[7802]: => Rails 5.2.1 application starting in production
Apr 09 18:57:43 centos7-katello-nightly.apex.example.com foreman[7802]: => Run `rails server -h` for more startup options
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] Puma starting in cluster mode...
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] * Version 4.3.3 (ruby 2.5.5-p157), codename: Mysterious Traveller
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] * Min threads: 0, max threads: 16
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] * Environment: production
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] * Process workers: 2
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] * Phased restart available
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] * Activated tcp://127.0.0.1:3000
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] Use Ctrl-C to stop
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] * Starting control server on unix:///var/run/foreman/foreman-pumactl.sock
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] - Worker 0 (pid: 7842) booted, phase: 0
Apr 09 18:57:55 centos7-katello-nightly.apex.example.com foreman[7802]: [7802] - Worker 1 (pid: 7846) booted, phase: 0

# ll /var/run/foreman/pids
total 12
-rw-r--r--. 1 foreman foreman   5 Apr  9 18:57 puma.pid
-rw-r--r--. 1 foreman foreman 124 Apr  9 18:57 puma.state
-rw-r--r--. 1 foreman foreman   4 Apr  9 18:57 server.pid

# cat /var/run/foreman/pids/puma.state
---
pid: 7802
control_url: unix:///var/run/foreman/foreman-pumactl.sock
control_auth_token: f498f3f689f023ee6afe6e82699f36c

# cat /var/run/foreman/pids/puma.pid
7802

# /bin/bash /usr/share/foreman/script/foreman-puma-status 
7802 (/var/run/foreman/pids/puma.state) Uptime:  2m17s | Phase: 0 | Load: 0[░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░]32
 └  7842 CPU:   0.0% Mem:  294 MB Uptime:  2m17s | Load: 0[░░░░░░░░░░░░░░░░]16
 └  7846 CPU:   0.0% Mem:  294 MB Uptime:  2m17s | Load: 0[░░░░░░░░░░░░░░░░]16

script/foreman-puma-status Outdated Show resolved Hide resolved
Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of /var/run is generally deprecated since systemd introduced /run. It is also a symlink on all platforms we support now. In packaging we ensure this directory exists by creating /usr/lib/tmpfiles.d/foreman.conf.

On a related, note, we still symlink /usr/share/foreman/tmp to /var/run/foreman instead of /run/foreman. A brief look tells me we should be using RuntimeDirectory=foreman in foreman.service but then we also need to take a look at the cache directory. The more I looked into this, the more things I saw to improve. https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RuntimeDirectory= has a nice list but Rails doesn't have a variable to change the tmp directory and just uses Rails.root.join('tmp') all over the place. That's why packaging symlinks it.

I also see that /run/foreman/sockets exists, but is empty. It appears this is a Rails convention and we should be making use of that.

You're now only configuring this for production, but shouldn't this be a general config? development also uses puma and it'd be nice to test the same tools there.

Comment on lines 1 to 7
pid_dir = '/var/run/foreman/pids'

# Store the pid of the server.
pidfile "#{pid_dir}/puma.pid"

# Store server info state.
state_path "#{pid_dir}/puma.state"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pid_dir = '/var/run/foreman/pids'
# Store the pid of the server.
pidfile "#{pid_dir}/puma.pid"
# Store server info state.
state_path "#{pid_dir}/puma.state"
run_dir = Rails.root.join('tmp')
# Store the pid of the server.
pidfile File.join(run_dir, 'pids', 'puma.pid')
# Store server info state.
state_path File.join(run_dir, 'puma.state')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @ekohl , to make it even simpler, should we perhaps just use
run_dir = "/run/foreman"

config/puma/production.rb Outdated Show resolved Hide resolved
@@ -0,0 +1,2 @@
#!/bin/bash
puma-status /var/run/foreman/pids/puma.state
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
puma-status /var/run/foreman/pids/puma.state
puma-status /run/foreman/puma.state

pid_dir = '/var/run/foreman/pids'

# Store the pid of the server.
pidfile "#{pid_dir}/puma.pid"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading further about this, the default pid is tmp/pids/server.pid and I don't see the need to change this. I also think that rails server has a --pid option to change this and there's no real reason to hardcode it. In systemd we don't even care about pids at all since it's all managed for us. Am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, we are concerned about the state_path option only and there is no need to change pidfile option. I changed it to make sure the pid and state files live together, but it doesn't matter. I will remove this entry.

@sthirugn
Copy link
Contributor Author

You're now only configuring this for production, but shouldn't this be a general config? development also uses puma and it'd be nice to test the same tools there.

I can submit a change for dev environment, which repository should this change be submitted to?

config/puma/production.rb Outdated Show resolved Hide resolved
@ehelms ehelms requested a review from ekohl April 16, 2020 14:03
@ekohl
Copy link
Member

ekohl commented Apr 16, 2020

Are there packaging PRs (both deb and RPM) to make sure foreman-puma-status is installed to the correct location?

@sthirugn
Copy link
Contributor Author

Are there packaging PRs (both deb and RPM) to make sure foreman-puma-status is installed to the correct location?

I see this PR theforeman/foreman-packaging#5031 manipulates foreman-puma-status. What other changes are needed?

@ehelms
Copy link
Member

ehelms commented Apr 20, 2020

Packaging change for RPM:

theforeman/foreman-packaging#5031

@ehelms
Copy link
Member

ehelms commented Apr 21, 2020

Any further comments or concerns with this? With packaging PRs open, I believe this is GTG.

ehelms
ehelms previously approved these changes Apr 22, 2020
ekohl
ekohl previously approved these changes Apr 22, 2020
Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving if my assumption is correct.

@@ -17,3 +22,6 @@
dynflow = ::Rails.application.dynflow
dynflow.initialize! unless dynflow.config.lazy_initialization
end

# === Puma control rack application ===
activate_control_app "unix://#{run_dir}/sockets/pumactl.sock"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't checked the permissions on this, but I'm assuming it's foreman:foreman and 0644 which should prevent from everyone writing to it. Correct?

Copy link
Contributor Author

@sthirugn sthirugn Apr 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how it looks now:

# ll -d /run/foreman/ /run/foreman/sockets
drwxr-xr-x. 5 foreman foreman 200 Apr 22 14:30 /run/foreman/
drwxr-xr-x. 2 foreman foreman  60 Apr 22 14:23 /run/foreman/sockets

# ll /run/foreman/sockets
total 0
srwxrwxrwx. 1 foreman foreman 0 Apr 22 14:23 pumactl.sock

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean that any user can connect to the socket and restart the server?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these determined by packaging?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, looks like a postgres user is able to restart the puma server if right control_url and control_auth_token is known. Any suggestions on how to lock this down further?

# ll /var/run/foreman/puma.state 
-rw-r--r--. 1 foreman foreman 120 Apr 22 15:23 /var/run/foreman/puma.state

# cat /var/run/foreman/puma.state 
---
pid: 1672
control_url: unix:///run/foreman/sockets/pumactl.sock
control_auth_token: 6c445af0312fff70fe0f190a65644cf

# sudo -u postgres scl enable tfm 'pumactl --control-url 'unix:///var/run/foreman/sockets/pumactl.sock' --control-token 6c445af0312fff70fe0f190a65644cf  restart'
Command restart sent success

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the permissions on viewing the control token?

Copy link
Contributor Author

@sthirugn sthirugn Apr 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see the first line of my post above. the control token is present in puma.state file which has permissions 644

Copy link
Member

@ehelms ehelms Apr 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All I can think is having something to adjust the permissions after creation but really the answer is to get a change into Puma to allow configuring the state file permissions.

Is it possible to put the state file in a directory that is not globally readable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All I can think is having something to adjust the permissions after creation but really the answer is to get a change into Puma to allow configuring the state file permissions.

I am working to get a fix to the puma project.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitted patch to puma project puma/puma#2238 to address the state file security issue.

@tbrisker
Copy link
Member

tbrisker commented May 3, 2020

@sthirugn @ekohl What's the status here?

@ekohl
Copy link
Member

ekohl commented May 3, 2020

Blocked on the linked PR (puma/puma#2238). There's good progress on it.

@sthirugn
Copy link
Contributor Author

sthirugn commented May 7, 2020

Note that puma/puma#2238 is merged now. So I added a new commit to this PR to add state_permission of 0644

@ekohl
Copy link
Member

ekohl commented May 7, 2020

Note that puma/puma#2238 is merged now. So I added a new commit to this PR to add state_permission of 0644

Note that merged doesn't mean available. You'll need to wait for a gem to include it and require at least puma x.y.z.

@ehelms
Copy link
Member

ehelms commented May 28, 2020

The related Puma fix is merged and released in Puma.

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should now require the right puma version but other than that 👍

@tbrisker
Copy link
Member

closing in favor of gh-7735

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants