WIP for on-the-fly users.

master
Luka Vandervelden 2019-11-17 20:06:42 +01:00
parent ab9a76326e
commit c8c0be9804
6 changed files with 70 additions and 15 deletions

View File

@ -5,3 +5,7 @@ ports: http=80, https=443
reload-command: kill -HUP ${SERVICE_PID}
%configuration nginx.conf
# Theyre defined in the template, be careful to match.
%file access.log
%file error.log

View File

@ -14,5 +14,8 @@ dependencies:
git: https://git.karchnu.fr/WeirdOS/recipes-parser
crinja:
github: straight-shoota/crinja
passwd:
git: https://git.karchnu.fr/WeirdOS/passwd.cr
branch: master
license: MIT

View File

@ -1,5 +1,7 @@
require "crinja"
require "passwd"
require "./service/service.cr"
require "./config.cr"
@ -8,7 +10,7 @@ def sanitize_path(path)
end
class Service
alias CrinjaHash = Hash(String, Hash(String, Int32) | String | Crinja::Callable::Instance | Nil)
alias CrinjaHash = Hash(String, Hash(String, Int32) | String | Crinja::Callable::Instance | Int32 | Nil)
def to_genconfig
CrinjaHash.new.tap do |entry|
entry["name"] = name
@ -18,6 +20,13 @@ class Service
entry["domain"] = domain
entry["ports"] = ports
user = Passwd.new("/etc/passwd", "/etc/group")
.try &.get_user(user_name).not_nil!
entry["uid"] = user.uid
entry["gid"] = user.gid
entry["user"] = user.login
entry["consumers"] = Crinja.function do
token = arguments.varargs[0].to_s

View File

@ -25,13 +25,15 @@ module System
passwd = pointer.value
r = LibC.setgid passwd.pw_gid
become_user passwd.pw_uid, passwd.pw_uid
end
def self.become_user(uid, gid)
r = LibC.setgid gid
raise Errno.new "setgid" if r != 0
r = LibC.setuid passwd.pw_uid
r = LibC.setuid uid
raise Errno.new "setuid" if r != 0
passwd
end
end
#def get_uid_gid(user_name : String)

View File

@ -2,6 +2,8 @@ require "yaml"
require "colorize"
require "file_utils"
require "passwd"
require "./context.cr"
require "./service_definition.cr"
require "./environment.cr"
@ -215,6 +217,7 @@ class Service
env["SERVICE_NAME"] = name
env["SERVICE_ROOT"] = root
env["SERVICE_ID"] = full_id
env["SERVICE_USER"] = user_name
if _pid = pid @context.pid_directory
env["SERVICE_PID"] = _pid.to_s
end
@ -222,11 +225,10 @@ class Service
env["ENVIRONMENT"] = @environment.name
env["ENVIRONMENT_TYPE"] = @environment.type.to_s
@providers.each do |token, provider|
service_provider = @context.get_service_by_id provider
# FIXME: Warning?
# FIXME: Warning if mandatory?
next if service_provider.nil?
env["#{token.upcase}_PROVIDER"] = provider
@ -294,9 +296,13 @@ class Service
context.info "Creating #{file.name}"
uid, gid = get_uid_gid
child = Process.fork do
Dir.cd root
System.become_user uid, gid
Process.exec "sh", ["-c", creation_command],
output: Process::Redirect::Inherit,
error: Process::Redirect::Inherit,
@ -319,7 +325,11 @@ class Service
context.title "Starting #{to_s}"
end
create_user_and_group!
uid, gid = get_uid_gid
FileUtils.mkdir_p root
File.chown root, uid, gid
build_files! context
@ -337,12 +347,7 @@ class Service
LibC.dup2 stdout_file.fd, 1
LibC.dup2 stderr_file.fd, 2
@reference.user.try do |user|
unless System.become_user user
STDERR << "service: child could not setuid() to user '#{user}'.\n"
exit 1
end
end
System.become_user uid, gid
Process.exec command, args,
chdir: (@reference.directory.try { |x| evaluate x } || root),
@ -583,7 +588,11 @@ class Service
end
end
remove_user_and_group!
File.delete "#{context.services_directory}/#{name}.#{@environment.name}.spec"
FileUtils.rm_rf root
end
def is_id?(id)
@ -660,6 +669,34 @@ class Service
def get_consumers(token)
@context.services.select(&.consumes?(token, self))
end
def user_name
full_id.sub('/', '.')
end
def get_uid_gid
passwd = Passwd.new("/etc/passwd", "/etc/group")
user = passwd.get_user(user_name).not_nil!
{user.uid, user.gid}
end
def create_user_and_group!
Passwd.new("/etc/passwd", "/etc/group").tap do |passwd|
return if passwd.get_user user_name
passwd.add_user user_name,
full_name: "Service[#{id}]"
end
end
def remove_user_and_group!
Passwd.new("/etc/passwd", "/etc/group").tap do |passwd|
passwd.remove_user user_name
passwd.remove_group user_name
end
end
end

View File

@ -10,8 +10,8 @@ events {
}
http {
error_log /var/log/{{ service.id | replace("/", "_") }}_error.log warn;
access_log /var/log/{{ service.id | replace("/", "_") }}_access.log;
error_log {{ service.root }}/error.log warn;
access_log {{ service.root }}/access.log;
include /etc/nginx/mime.types;
default_type application/octet-stream;