Антон Рябов bio photo

Антон Рябов

Не люблю бриться и у меня умный взгляд.

Email Twitter Telegram Github PGP RSS

Управление пользователями в системе, неважно Linux или любой другой, это первичная задача, с которой сталкивается любой администратор. В моей работе речь идет об управлении парком серверов, и для этого конечно используется система управления конфигурацией. На текущем месте работы (OneTwoTrip) это Chef, а до этого был Ansible.

Про другие инструменты DevOps я писал здесь.

На самом деле, неважно какую CM использовать - принцип остается неизменным:

Работая с системой управления конфигурации, ты описываешь состояние системы, каким оно должно быть, а не изменения.

Ну т.е. технически ты конечно же описываешь изменения, но твой финальный скрипт управления должен постоянно поддерживать правильное состояние системы. Пример с пользователями отлично подходит для демонстрации данного принципа, перейду к сути.

Как чаще всего решается задача создания пользователей в системе?

node['users'].each do |name|
  user name do
    comment 'system user'
    system true
  end
end

Что произойдет, когда сотрудник уволится? Вы удалите запись из атрибута и данный пользователь не будет создаваться на новых серверах, но на старых он по-прежнему останется, потому что мы написали код для создания пользователей, но не написали код для удаления тех, кого нет в атрибуте (не считая системных и специальных пользователей, конечно же).

Более того, со временем мы заметим странную штуку, что UID/GID одного и того же пользователя на разных серверах будет отличаться. Все это приводит к так называемому Configuration drift, когда конфигурация на серверах начинает различаться, хотя управляется одними и теми же правилами.

В шефе, я предлагаю следующий вариант:

  • Делим пользователей на админов и простых смертных
  • Жестко контролируем UID/GID
  • Автоматически удаляем тех, кого нет в системе
  • Создаем тех, кого не хватает в системе

Итак, выделим для админов пул с 500 по 600 UID, а для простых смертных с 1000 и до 65533. Будем проходиться по всем пользователям в системе, и если находим того, кого не существует - удаляем.

node['etc']['passwd'].each do |user, data|
  uid = data['uid'] ? data['uid'] : user
  if uid.to_i.between?(500, 600)
    s = search('users', "groups:admin AND id:#{user}")
    if s.empty?
      user(user) do
        force true
        action :remove
      end
    end
  end

  if uid.to_i.between?(1000, 65533)
    s = search('users', "groups:users AND id:#{user}")
    if s.empty?
      user(user) do
        force true
        action :remove
      end
    end
  end
end

node[‘etc’][‘passwd’] атрибут, который Ohai автоматически заполняет при каждом прогоне chef-client

Ресурс user, используемый в данном коде, который мы берем из официальной кукбуки, работает с дата багом users. Пользователей нужно перечислять в следующем виде:

{
  "id": "ivanivanov",
  "uid": 501,
  "shell": "/bin/bash",
  "groups": [
    "admin"
  ],
  "ssh_keys": [
    "ssh-rsa xxx"
  ],
  "comment": "devops | Ivan Ivanov"
}

Следовательно, вот такой код:

users_manage 'admin' do
  action [:remove, :create]
end

Будет искать всех пользователей, у которых в groups есть admin. Запись для обычных пользователей почти не отличается:

{
  "id": "petya",
  "uid": 1001,
  "shell": "/bin/bash",
  "groups": [
    "users"
  ],
  "ssh_keys": [
    "ssh-rsa xxx"
  ],
  "comment": "trivial | Petya programmist"
}

Как и код в рецепте:

users_manage 'users' do
  action [:remove, :create]
end

Вот так я предлагаю управлять пользователями в Chef и применять данный принцип в других системах управления конфигурацией. Если у вас есть что добавить или исправить, пишите в твиттер или на почту, ссылки слева под аватаркой 😉

#Linux #DevOps