Spec-Zone.ru › Chef 18

Авторизация

[править на GitHub]

API сервера Chef Infra обрабатывает все взаимодействие между клиентом Chef Infra или рабочей станцией Chef. API сервера Chef Infra — это аутентифицированный REST-API, что означает, что все запросы требуют аутентификации и авторизации. Инструменты Chef Infra, такие как knife и chef-server команды, используют API сервера Chef Infra за вас.

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

  • Сервер Chef Infra хранит открытый ключ
  • Рабочая станция Chef сохраняет закрытый ключ в ~/.chef/
  • Клиент Chef Infra сохраняет закрытый ключ в /etc/chef

Клиент и рабочая станция Chef взаимодействуют с сервером Chef Infra, используя API сервера Chef Infra. Каждый раз, когда клиент или рабочая станция Chef делают запрос к серверу Chef Infra, они используют специальную группу HTTP-заголовков и подписывают остальную часть запроса с помощью своего закрытого ключа. Сервер Chef Infra затем использует открытый ключ для проверки заголовков и содержимого.

Открытые и закрытые ключи

Каждый запрос, отправляемый клиентом Chef Infra серверу Chef Infra, должен быть аутентифицированным запросом, использующим API сервера Chef Infra и закрытый ключ. Когда клиент Chef Infra отправляет запрос серверу Chef Infra, клиент Chef Infra аутентифицирует каждый запрос, используя закрытый ключ, расположенный в /etc/chef/client.pem.

Использование ключа сервера Chef Infra

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

  • Сервер Chef Infra хранит открытый ключ
  • Рабочая станция Chef сохраняет закрытый ключ в ~/.chef/
  • Клиент Chef Infra сохраняет закрытый ключ в /etc/chef

Клиент и рабочая станция Chef взаимодействуют с сервером Chef Infra, используя API сервера Chef Infra. Каждый раз, когда клиент или рабочая станция Chef делают запрос к серверу Chef Infra, они используют специальную группу HTTP-заголовков и подписывают остальную часть запроса с помощью своего закрытого ключа. Сервер Chef Infra затем использует открытый ключ для проверки заголовков и содержимого.

Клиент Chef Infra

Клиент Chef Infra аутентифицируется у сервера Chef Infra с использованием пар открытых и закрытых ключей RSA каждый раз, когда клиент Chef Infra нуждается в доступе к данным, хранящимся на сервере Chef Infra. Это предотвращает доступ любого узла к данным, к которым он не должен иметь доступ, и гарантирует, что управлять могут только узлы, должным образом зарегистрированные на сервере Chef Infra.

Knife

Пары открытых и закрытых ключей RSA используются для аутентификации knife у сервера Chef Infra каждый раз, когда knife пытается получить доступ к серверу Chef Infra. Это гарантирует, что каждый экземпляр knife должным образом зарегистрирован на сервере Chef Infra и что изменения в данных могут вносить только доверенные пользователи.

Knife также может использовать подкоманду knife exec для выполнения конкретных аутентифицированных запросов к серверу Chef Infra. Плагины knife также могут выполнять аутентифицированные запросы к серверу Chef Infra, используя подкоманду knife exec.

chef-validator

Закрытый ключ ещё не существует в первый раз, когда клиент Chef Infra запускается с нового узла.

Во время первого запуска клиента Chef Infra:

  1. Клиент Chef Infra использует закрытый ключ chef-validator, расположенный в /etc/chef/validation.pem для регистрации у сервера Chef Infra
  2. Сервер Chef Infra назначает клиенту Chef Infra закрытый ключ для всех будущих запросов на аутентификацию у сервера Chef Infra
  3. Клиент Chef Infra сохраняет закрытый ключ на узле как /etc/chef/client.pem

Если запрос на взаимодействие с сервером Chef Infra с помощью ключа chef-validator завершится неудачей, то весь первый запуск клиента Chef Infra завершится неудачей.

После успешного первого запуска клиента Chef Infra удалите закрытый ключ chef-validator по адресу /etc/chef/validation.pem

Хранение ключей сервера Chef Infra

Ключи хранятся в разных местах, в зависимости от того, является ли местоположение узлом или рабочей станцией.

Узлы

Каждый узел хранит свой закрытый ключ локально. Этот закрытый ключ генерируется в рамках процесса загрузки, который изначально устанавливает клиент Chef Infra на узел. В первый раз при запуске клиента Chef Infra на этом узле он использует chef-validator для аутентификации, но затем при каждом последующем запуске он использует закрытый ключ, сгенерированный для этого клиента сервером Chef Infra.

Рабочие станции

Каждая рабочая станция хранит свой закрытый ключ в каталоге пользователя ~/.chef. Этот закрытый ключ генерируется сервером Chef Infra и должен быть загружен с сервера и скопирован в каталог ~/.chef вручную. Если вам нужен новый закрытый ключ, сгенерируйте его на сервере Chef Infra и снова скопируйте его в каталог ~/.chef.

Каталог chef-repo на вашей рабочей станции хранит всё необходимое для определения вашей инфраструктуры с помощью Chef Infra:

  • Кулинарные книги (включая рецепты, атрибуты, пользовательские ресурсы, библиотеки и шаблоны)
  • Мешки данных
  • Файлы политики

Каталог chef-repo должен быть синхронизирован с системой управления версиями, например, git. Все данные в каталоге chef-repo следует рассматривать как исходный код.

Вы будете использовать команды chef и knife для загрузки данных на сервер Chef Infra из каталога chef-repo. После загрузки клиент Chef Infra использует эти данные для управления зарегистрированными узлами на сервере Chef Infra и для обеспечения правильного применения кулинарных книг, файлов политики и настроек к соответствующим узлам в правильном порядке.

Каталог .chef — это скрытый каталог, используемый для хранения файлов ключей валидации и, необязательно, файла config.rb.

Аутентификация API сервера Chef Infra

Запросы API

Плагин knife — это набор одной (или нескольких) подкоманд, которые могут быть добавлены к knife для поддержки дополнительной функциональности, которая не включена в базовый набор подкоманд knife. Многие плагины knife создаются членами сообщества Chef, и несколько из них создаются и поддерживаются компанией Chef.

Плагин knife может быть использован для выполнения аутентифицированных запросов API к серверу Chef Infra с помощью следующих методов:

Метод Описание
rest.delete_rest Используется для удаления объекта с сервера Chef Infra.
rest.get_rest Используется для получения деталей объекта на сервере Chef Infra.
rest.post_rest Используется для добавления объекта на сервер Chef Infra.
rest.put_rest Используется для обновления объекта на сервере Chef Infra.

Например:

module MyCommands
  class MyNodeDelete < Chef::Knife
    #An implementation of knife node delete
    banner 'knife my node delete [NODE_NAME]'

    def run
      if name_args.length < 1
        show_usage
        ui.fatal('You must specify a node name.')
        exit 1
      end
      nodename = name_args[0]
      api_endpoint = "nodes/#{nodename}"
      # Again, we could just call rest.delete_rest
      nodey = rest.get_rest(api_endpoint)
      ui.confirm("Do you really want to delete #{nodey}")
      nodey.destroy
    end
  end
end

Из веб-интерфейса

Веб-интерфейс сервера Chef Infra использует API сервера Chef Infra для выполнения большинства операций. Это гарантирует, что запросы на аутентификацию у сервера Chef Infra авторизованы. Этот процесс аутентификации выполняется автоматически и не требует управления со стороны пользователей размещённого сервера Chef Infra. Для локального сервера Chef Infra ключи аутентификации, используемые веб-интерфейсом, должны поддерживаться отдельными администраторами, ответственными за управление сервером.

Другие варианты

Наиболее распространённые способы взаимодействия с сервером Chef Infra с использованием API сервера Chef Infra абстрагируют API от пользователя. Тем не менее, API сервера Chef Infra можно использовать напрямую. В следующих разделах описываются некоторые из доступных способов.

cURL

Запрос API можно выполнить с помощью cURL, что представляет собой скрипт оболочки Bash, для которого требуются две утилиты: awk и openssl. Следующий пример демонстрирует, как можно выполнить аутентифицированный запрос с помощью API сервера Chef Infra и cURL:

#!/usr/bin/env bash

_chef_dir () {
  # Helper function:
  # Recursive function that searches for chef configuration directory
  # It looks upward from the cwd until it hits /.  If no directory is found,
  # ~/.chef is chosen if it exists
  # You could simply hard-code the path below

  if [ "$PWD" = "/" ]; then
  if [ -d ".chef" ]; then
    echo "/.chef"
      elif [ -d "$HOME/.chef" ]; then
        echo "$HOME/.chef"
      fi
    return
  fi

  if [ -d '.chef' ];then
    echo "${PWD}/.chef"
  else
    (cd ..; _chef_dir)
  fi
}

_chomp () {
  # helper function to remove newlines
  awk '{printf "%s", $0}'
}

chef_api_request() {
  # This is the meat-and-potatoes, or rice-and-vegetables, your preference really.

  local method path body timestamp chef_server_url client_name hashed_body hashed_path
  local canonical_request headers auth_headers

  chef_server_url="https://api.opscode.com/organizations/my_org"
  # '/organizations/ORG_NAME' is needed
  if echo $chef_server_url | grep -q "/organizations/" ; then
    endpoint=/organizations/${chef_server_url#*/organizations/}${2%%\?*}
  else
    endpoint=${2%%\?*}
  fi
  path=${chef_server_url}$2
  client_name="chef_user"
  method=$1
  body=$3

  hashed_path=$(echo -n "$endpoint" | openssl dgst -sha1 -binary | openssl enc -base64)
  hashed_body=$(echo -n "$body" | openssl dgst -sha1 -binary | openssl enc -base64)
  timestamp=$(date -u "+%Y-%m-%dT%H:%M:%SZ")

  canonical_request="Method:$method\nHashed Path:$hashed_path\nX-Ops-Content-Hash:$hashed_body\nX-Ops-Timestamp:$timestamp\nX-Ops-UserId:$client_name"
  headers="-H X-Ops-Timestamp:$timestamp \
    -H X-Ops-Userid:$client_name \
    -H X-Chef-Version:0.10.4 \
    -H Accept:application/json \
    -H X-Ops-Content-Hash:$hashed_body \
    -H X-Ops-Sign:version=1.0"

  auth_headers=$(printf "$canonical_request" | openssl rsautl -sign -inkey \
    "$(_chef_dir)/${client_name}.pem" | openssl enc -base64 | _chomp |  awk '{ll=int(length/60);i=0; \
    while (i<=ll) {printf " -H X-Ops-Authorization-%s:%s", i+1, substr($0,i*60+1,60);i=i+1}}')

  case $method in
    GET)
      curl_command="curl $headers$auth_headers$path"
      $curl_command
      ;;
    *)
      echo "Unknown Method. I only know: GET" >&2
      return 1
      ;;
    esac
  }

 chef_api_request "$@"

После сохранения этого скрипта оболочки в файл под именем chef_api_request, используйте его аналогично следующему:

bash chef_api_request GET "/clients"

PyChef

Запрос API можно выполнить с помощью PyChef, что представляет собой библиотеку Python, которая соответствует требованиям Mixlib::Authentication для легкого взаимодействия с сервером Chef Infra. Следующий пример демонстрирует, как можно выполнить аутентифицированный запрос с помощью API сервера Chef Infra и PyChef:

from chef import autoconfigure, Node

api = autoconfigure()
n = Node('web1')
print n['fqdn']
n['myapp']['version'] = '1.0'
n.save()

а следующий пример демонстрирует, как выполнить API-вызовы напрямую:

from chef import autoconfigure

api = autoconfigure()
print api.api_request('GET', '/clients')

В предыдущих примерах предполагается, что текущая рабочая директория такова, что PyChef может найти действительный конфигурационный файл таким же образом, как клиент Chef Infra или knife. Более подробную информацию о PyChef см. на странице: https://github.com/coderanger/pychef.

Ruby

На системе с установленным клиентом Chef Infra используйте Ruby для выполнения аутентифицированного запроса к серверу Chef Infra:

require 'chef/config'
require 'chef/log'
require 'chef/rest'

chef_server_url = 'https://chefserver.com'
client_name = 'clientname'
signing_key_filename = '/path/to/pem/for/clientname'

rest = Chef::REST.new(chef_server_url, client_name, signing_key_filename)
puts rest.get_rest('/clients')

или:

require 'mixlib/cli'
require 'chef'
require 'chef/node'
require 'chef/mixin/xml_escape'
require 'json'

config_file = 'c:/chef/client.rb'
Chef::Config.from_file(config_file)
Chef::Log.level = Chef::Config[:log_level]

def Usage()
  puts '/etc/chef/client.rb' # The config file location, e.g. ~/home/.chef/config.rb etc
  config_file = gets.chomp
  if (!File.exist?(config_file))
    puts 'config_file #{config_file} does not exist. Exiting.\n'
    exit
  end
  STDOUT.puts <<-EOF
    Choose options e.g. 1

    1 Display all nodes per environment
    2 Display all nodes in detail (can be slow if there a large number of nodes)
    9 Exit
  EOF
end

def ExecuteUserChoice()
  testoption = gets.chomp
  case testoption
  when '1'
    Execute(method(:DisplayNodesPerEnv))
  when '2'
    Execute(method(:DisplayNodesDetail))
  when '9'
    puts 'exit'
  else
    puts 'Unknown option #{testoption}. Exiting\n'
    exit
  end
end

def DisplayNodesPerEnv()
  Chef::Environment.list(false).each do |envr|
    print 'ENVIRONMENT: ', envr[0], '\n'
    Chef::Node.list_by_environment(envr[0], false).each do |node_info|
      print '\tNODE: ', node_info[0], '\n'
      print '\t\tURL: ', node_info[1], '\n'
    end
  end
end

def DisplayNodesDetail()
  Chef::Node.list(true).each do |node_array|
    node = node_array[1]
    print '#{node.name}\n'
    print '\t#{node['fqdn']}\n'
    print '\t#{node['kernel']['machine']}\n'
    print '\t#{node['kernel']['os']}\n'
    print '\t#{node['platform']}\n'
    print '\t#{node['platform_version']}\n'
    print '\t#{node.chef_environment}\n'
    print '\t#{node.run_list.roles}\n'
  end
end

def Execute(option)
  begin
    profilestart = Time.now
    option.call()
    profileend = Time.now
    timeofrun = profileend - profilestart
    print 'Time taken = #{timeofrun}'
  rescue Exception => ex
    print 'Error calling chef API'
    print ex.message
    print ex.backtrace.join('\n')
  end
end

Usage()
ExecuteUserChoice()

Другой способ использования Ruby с API сервера Chef Infra — получить объекты с сервера Chef Infra и затем взаимодействовать с возвращёнными данными с помощью методов Ruby. Всякий раз, когда это возможно, API сервера Chef Infra вернёт объект соответствующего типа. Возвращённый объект затем доступен для вызова другими методами. Например, метод api.get может быть использован для возвращения узла с именем foobar, а затем .destroy может быть использован для удаления этого узла:

silly_node = api.get('/nodes/foobar')
silly_node.destroy

Отладка проблем с аутентификацией

В некоторых случаях клиент Chef Infra может получить ответ 401 на запрос аутентификации и ответ 403 на запрос авторизации. Ошибка аутентификации может выглядеть следующим образом:

[Wed, 05 Oct 2011 15:43:34 -0700] INFO: HTTP Request Returned 401
Unauthorized: Failed to authenticate as node_name. Ensure that your node_name and client key are correct.

Для отладки проблем с аутентификацией определите, какой клиент Chef Infra пытается пройти аутентификацию. Это часто можно найти в сообщениях журнала для этого клиента Chef Infra. Отладочная запись журналов может быть включена на клиенте Chef Infra с помощью следующей команды:

chef-client -l debug

При включённой отладочной записи журнала запись в журнале будет выглядеть следующим образом:

[Wed, 05 Oct 2011 22:05:35 +0000] DEBUG: Signing the request as NODE_NAME

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

Если аутентификация происходит на узле, есть ряд распространённых причин:

  • Файл client.pem некорректен. Это можно исправить, удалив файл client.pem и повторно запустив Chef Infra Client. При повторном запуске Chef Infra Client он снова попытается зарегистрироваться на сервере Chef Infra Server и сгенерировать правильный ключ.
  • Значение node_name отличается от значения, используемого при начальном запуске Chef Infra Client. Это может произойти по нескольким причинам. Например, если в файле client.rb не указано правильное имя узла, а имя хоста недавно изменилось. Эту проблему можно решить, явно задав имя узла в файле client.rb или используя опцию -N для исполняемого файла Chef Infra Client.
  • Системные часы отклонились от реального времени более чем на 15 минут. Это можно исправить, синхронизировав часы с сервером Network Time Protocol (NTP).

Авторизация

Дополнительную информацию об авторизации Chef Infra Server см. в разделе Организации и группы.

API Chef Infra Server

Дополнительную информацию об использовании конечных точек API Chef Infra Server см. в разделе API Chef Infra Server.

© Chef Software, Inc.
Licensed under the Creative Commons Attribution 3.0 Unported License.
The Chef™ Mark and Chef Logo are either registered trademarks/service marks or trademarks/servicemarks of Chef, in the United States and other countries and are used with Chef Inc's permission.
We are not affiliated with, endorsed or sponsored by Chef Inc.
https://docs.chef.io/server/auth/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API