diff options
Diffstat (limited to 'lib/chef_zero')
-rw-r--r-- | lib/chef_zero/chef_data/data_normalizer.rb | 1 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/actor_endpoint.rb | 124 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/actors_endpoint.rb | 40 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/organization_user_endpoint.rb | 19 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/principal_endpoint.rb | 99 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/rest_object_endpoint.rb | 42 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/server_api_version_endpoint.rb | 2 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/user_key_endpoint.rb | 32 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/user_keys_endpoint.rb | 80 | ||||
-rw-r--r-- | lib/chef_zero/rest_base.rb | 83 | ||||
-rw-r--r-- | lib/chef_zero/server.rb | 4 |
11 files changed, 441 insertions, 85 deletions
diff --git a/lib/chef_zero/chef_data/data_normalizer.rb b/lib/chef_zero/chef_data/data_normalizer.rb index 95f3daa..554bd70 100644 --- a/lib/chef_zero/chef_data/data_normalizer.rb +++ b/lib/chef_zero/chef_data/data_normalizer.rb @@ -36,7 +36,6 @@ module ChefZero def self.normalize_user(user, name, identity_keys, osc_compat, method=nil) user[identity_keys.first] ||= name - user['public_key'] ||= PUBLIC_KEY user['admin'] ||= false user['admin'] = !!user['admin'] user['openid'] ||= nil diff --git a/lib/chef_zero/endpoints/actor_endpoint.rb b/lib/chef_zero/endpoints/actor_endpoint.rb index 1572ac1..a491965 100644 --- a/lib/chef_zero/endpoints/actor_endpoint.rb +++ b/lib/chef_zero/endpoints/actor_endpoint.rb @@ -8,15 +8,26 @@ module ChefZero # /organizations/ORG/users/NAME # /users/NAME class ActorEndpoint < RestObjectEndpoint + DEFAULT_PUBLIC_KEY_NAME = "default" + DEFAULT_PUBLIC_KEY_EXPIRATION_DATE = "infinity" + def delete(request) result = super + username = request.rest_path[1] + if request.rest_path[0] == 'users' list_data(request, [ 'organizations' ]).each do |org| begin - delete_data(request, [ 'organizations', org, 'users', request.rest_path[1] ], :data_store_exceptions) + delete_data(request, [ 'organizations', org, 'users', username ], :data_store_exceptions) rescue DataStore::DataNotFoundError end end + + begin + path = [ 'user_keys', username ] + delete_data_dir(request, path, :data_store_exceptions) + rescue DataStore::DataNotFoundError + end end result end @@ -24,43 +35,46 @@ module ChefZero def put(request) # Find out if we're updating the public key. request_body = FFI_Yajl::Parser.parse(request.body, :create_additions => false) - if request_body['public_key'].nil? + + public_key = request_body.delete('public_key') + + if public_key.nil? # If public_key is null, then don't overwrite it. Weird patchiness. body_modified = true - request_body.delete('public_key') else updating_public_key = true end # Generate private_key if requested. - if request_body.has_key?('private_key') + if request_body.key?('private_key') body_modified = true - if request_body['private_key'] + + if request_body.delete('private_key') private_key, public_key = server.gen_key_pair updating_public_key = true - request_body['public_key'] = public_key end - request_body.delete('private_key') end - # Save request + # Put modified body back in `request.body` request.body = FFI_Yajl::Encoder.encode(request_body, :pretty => true) if body_modified # PUT /clients is patchy - request.body = patch_request_body(request) + request.body = patch_request_body(request, except: :public_key) result = super(request) # Inject private_key into response, delete public_key/password if applicable if result[0] == 200 || result[0] == 201 + username = identity_key_value(request) || request.rest_path[-1] + + # TODO Implement for clients + if request.rest_path[2] != 'clients' && is_rename?(request) + rename_user_keys!(request, username) + end + if request.rest_path[0] == 'users' - key = nil - identity_keys.each do |identity_key| - key ||= request_body[identity_key] - end - key ||= request.rest_path[-1] response = { - 'uri' => build_uri(request.base_uri, [ 'users', key ]) + 'uri' => build_uri(request.base_uri, [ 'users', username ]) } else response = FFI_Yajl::Parser.parse(result[2], :create_additions => false) @@ -70,25 +84,93 @@ module ChefZero response['private_key'] = private_key ? private_key : false else response['private_key'] = private_key if private_key + + if updating_public_key + update_user_default_key!(request, public_key) + end + end + + if request.rest_path[2] == 'users' && !updating_public_key + response.delete('public_key') end - response.delete('public_key') if !updating_public_key && request.rest_path[2] == 'users' response.delete('password') + json_response(result[0], response) else result end end + private + def populate_defaults(request, response_json) response = FFI_Yajl::Parser.parse(response_json, :create_additions => false) - if request.rest_path[2] == 'clients' - response = ChefData::DataNormalizer.normalize_client(response,request.rest_path[3], request.rest_path[1]) - else - response = ChefData::DataNormalizer.normalize_user(response, request.rest_path[3], identity_keys, server.options[:osc_compat], request.method) - end + + response = + if request.rest_path[2] == 'clients' + ChefData::DataNormalizer.normalize_client(response, request.rest_path[3], request.rest_path[1]) + else + public_key = get_user_default_public_key(request, response['username']) + + if public_key + response['public_key'] = public_key + end + + ChefData::DataNormalizer.normalize_user(response, request.rest_path[3], identity_keys, server.options[:osc_compat], request.method) + end + FFI_Yajl::Encoder.encode(response, :pretty => true) end + + # Returns the user's default public_key from user_keys store + def get_user_default_public_key(request, username) + path = [ "user_keys", username, "keys", DEFAULT_PUBLIC_KEY_NAME ] + key_json = get_data(request, path, :nil) + return unless key_json + + key_data = FFI_Yajl::Parser.parse(key_json, create_additions: false) + key_data && key_data["public_key"] + end + + # Move key data to new path + def rename_user_keys!(request, new_username) + orig_username = request.rest_path[-1] + orig_user_keys_path = [ 'user_keys', orig_username, 'keys' ] + new_user_keys_path = [ 'user_keys', new_username, 'keys' ] + + user_key_names = list_data(request, orig_user_keys_path, :data_store_exceptions) + + user_key_names.each do |key_name| + # Get old data + orig_path = orig_user_keys_path + [ key_name ] + data = get_data(request, orig_path, :data_store_exceptions) + + # Copy data to new path + create_data( + request, + new_user_keys_path, key_name, + data, + :create_dir + ) + end + + # Delete original data + delete_data_dir(request, orig_user_keys_path, :data_store_exceptions) + end + + def update_user_default_key!(request, public_key) + username = request.rest_path[1] + path = [ "user_keys", username, "keys", DEFAULT_PUBLIC_KEY_NAME ] + + data = FFI_Yajl::Encoder.encode( + "name" => DEFAULT_PUBLIC_KEY_NAME, + "public_key" => public_key, + "expiration_date" => DEFAULT_PUBLIC_KEY_EXPIRATION_DATE + ) + + set_data(request, path, data, :create, :data_store_exceptions) + end end end end diff --git a/lib/chef_zero/endpoints/actors_endpoint.rb b/lib/chef_zero/endpoints/actors_endpoint.rb index c6c676f..df6111c 100644 --- a/lib/chef_zero/endpoints/actors_endpoint.rb +++ b/lib/chef_zero/endpoints/actors_endpoint.rb @@ -5,6 +5,8 @@ module ChefZero module Endpoints # /users, /organizations/ORG/clients or /organizations/ORG/users class ActorsEndpoint < RestListEndpoint + DEFAULT_PUBLIC_KEY_NAME = "default" + def get(request) response = super(request) @@ -37,19 +39,29 @@ module ChefZero end def post(request) - # First, find out if the user actually posted a public key. If not, make - # one. request_body = FFI_Yajl::Parser.parse(request.body, :create_additions => false) - public_key = request_body['public_key'] - if !public_key + username = request_body['username'] + + public_key = request_body["public_key"] + + # Did the user post a public_key? If not, generate one. + unless public_key private_key, public_key = server.gen_key_pair + end + + if request.rest_path[2] == "clients" request_body['public_key'] = public_key - request.body = FFI_Yajl::Encoder.encode(request_body, :pretty => true) + else + request_body.delete('public_key') end + request.body = FFI_Yajl::Encoder.encode(request_body, :pretty => true) result = super(request) if result[0] == 201 + # Store the received or generated public key + create_user_default_key!(request, username, public_key) + # If we generated a key, stuff it in the response. response = FFI_Yajl::Parser.parse(result[2], :create_additions => false) response['private_key'] = private_key if private_key @@ -59,6 +71,24 @@ module ChefZero result end end + + private + + # Store the public key in user_keys + def create_user_default_key!(request, username, public_key) + # TODO Implement for clients + return if request.rest_path[2] == "clients" + + path = [ "user_keys", username, "keys" ] + + data = FFI_Yajl::Encoder.encode( + "name" => DEFAULT_PUBLIC_KEY_NAME, + "public_key" => public_key, + "expiration_date" => "infinity" + ) + + create_data(request, path, DEFAULT_PUBLIC_KEY_NAME, data, :create_dir) + end end end end diff --git a/lib/chef_zero/endpoints/organization_user_endpoint.rb b/lib/chef_zero/endpoints/organization_user_endpoint.rb index 8fd97d4..d0c5b3c 100644 --- a/lib/chef_zero/endpoints/organization_user_endpoint.rb +++ b/lib/chef_zero/endpoints/organization_user_endpoint.rb @@ -5,11 +5,17 @@ module ChefZero module Endpoints # /organizations/ORG/users/NAME class OrganizationUserEndpoint < RestBase + DEFAULT_PUBLIC_KEY_NAME = "default" + def get(request) username = request.rest_path[3] get_data(request) # 404 if user is not in org + user = get_data(request, [ 'users', username ]) user = FFI_Yajl::Parser.parse(user, :create_additions => false) + + user["public_key"] = get_user_default_public_key(request, username) + json_response(200, ChefData::DataNormalizer.normalize_user(user, username, ['username'], server.options[:osc_compat], request.method)) end @@ -20,7 +26,18 @@ module ChefZero json_response(200, ChefData::DataNormalizer.normalize_user(user, request.rest_path[3], ['username'], server.options[:osc_compat])) end - # Note: post to a named org user is not permitted, alllow invalid method handling (405) + # Note: post to a named org user is not permitted, allow invalid method handling (405) + + private + # Returns the user's default public_key from user_keys store + def get_user_default_public_key(request, username) + path = [ "user_keys", username, "keys", DEFAULT_PUBLIC_KEY_NAME ] + key_json = get_data(request, path, :nil) + return unless key_json + + key_data = FFI_Yajl::Parser.parse(key_json, create_additions: false) + key_data && key_data["public_key"] + end end end end diff --git a/lib/chef_zero/endpoints/principal_endpoint.rb b/lib/chef_zero/endpoints/principal_endpoint.rb index b1f4efb..2dcec1b 100644 --- a/lib/chef_zero/endpoints/principal_endpoint.rb +++ b/lib/chef_zero/endpoints/principal_endpoint.rb @@ -6,40 +6,79 @@ module ChefZero module Endpoints # /principals/NAME class PrincipalEndpoint < RestBase + DEFAULT_PUBLIC_KEY_NAME = "default" + def get(request) name = request.rest_path[-1] - # If /organizations/ORG/users/NAME exists, use this user (only org members have precedence over clients). hey are an org member. - json = get_data(request, request.rest_path[0..1] + [ 'users', name ], :nil) - if json - type = 'user' - org_member = true - else - # If /organizations/ORG/clients/NAME exists, use the client. - json = get_data(request, request.rest_path[0..1] + [ 'clients', name ], :nil) - if json - type = 'client' - org_member = true - else - # If there is no client with that name, check for a user (/users/NAME) and return that with - # org_member = false. - json = get_data(request, [ 'users', name ], :nil) - if json - type = 'user' - org_member = false - end - end - end - if json - json_response(200, { - 'name' => name, - 'type' => type, - 'public_key' => FFI_Yajl::Parser.parse(json)['public_key'] || PUBLIC_KEY, + data = get_principal_data(request, name) + + if data + return json_response(200, data.merge( 'authz_id' => '0'*32, - 'org_member' => org_member - }) - else - error(404, 'Principal not found') + 'name' => name, + )) end + + error(404, 'Principal not found') + end + + private + + def get_principal_data(request, name) + # If /organizations/ORG/users/NAME exists, use this user (only org members have precedence over clients). hey are an org member. + get_org_users_data(request, name) || + # If /organizations/ORG/clients/NAME exists, use the client. + get_clients_data(request, name) || + # If there is no client with that name, check for a user (/users/NAME) and return that with + # org_member = false. + get_users_data(request, name) + end + + def get_org_users_data(request, name) + path = [ *request.rest_path[0..1], 'users', name ] + return if get_data(request, path, :nil).nil? + + user_keys_json = get_data(request, + [ 'user_keys', name, 'keys', DEFAULT_PUBLIC_KEY_NAME ], + :data_store_exceptions + ) + + public_key = FFI_Yajl::Parser.parse(user_keys_json)['public_key'] + + { "type" => "user", + "org_member" => true, + "public_key" => public_key + } + end + + def get_clients_data(request, name) + path = [ *request.rest_path[0..1], 'clients', name ] + json = get_data(request, path, :nil) + return if json.nil? + + public_key = FFI_Yajl::Parser.parse(json)['public_key'] + + { "type" => "client", + "org_member" => true, + "public_key" => public_key || PUBLIC_KEY + } + end + + def get_users_data(request, name) + path = [ 'users', name ] + return if get_data(request, path, :nil).nil? + + user_keys_json = get_data(request, + [ 'user_keys', name, 'keys', DEFAULT_PUBLIC_KEY_NAME ], + :data_store_exceptions + ) + + public_key = FFI_Yajl::Parser.parse(user_keys_json)['public_key'] + + { "type" => "user", + "org_member" => false, + "public_key" => public_key + } end end end diff --git a/lib/chef_zero/endpoints/rest_object_endpoint.rb b/lib/chef_zero/endpoints/rest_object_endpoint.rb index 9e978b4..efadf82 100644 --- a/lib/chef_zero/endpoints/rest_object_endpoint.rb +++ b/lib/chef_zero/endpoints/rest_object_endpoint.rb @@ -21,12 +21,11 @@ module ChefZero def put(request) # We grab the old body to trigger a 404 if it doesn't exist old_body = get_data(request) - request_json = FFI_Yajl::Parser.parse(request.body, :create_additions => false) - key = identity_keys.map { |k| request_json[k] }.select { |v| v }.first - key ||= request.rest_path[-1] + # If it's a rename, check for conflict and delete the old value - rename = key != request.rest_path[-1] - if rename + if is_rename?(request) + key = identity_key_value(request) + begin create_data(request, request.rest_path[0..-2], key, request.body, :data_store_exceptions) rescue DataStore::DataAlreadyExistsError @@ -46,18 +45,49 @@ module ChefZero already_json_response(200, populate_defaults(request, result)) end - def patch_request_body(request) + # Merge the request body with the existing data, if one exists in + # the data store + # + # @param [ChefZero::RestRequest] request + # @param [Hash] options + # @option options [Symbol, Array<Symbol>] :except (nil) Key(s) from + # the existing data to discard + def patch_request_body(request, options={}) existing_value = get_data(request, nil, :nil) + if existing_value request_json = FFI_Yajl::Parser.parse(request.body, :create_additions => false) existing_json = FFI_Yajl::Parser.parse(existing_value, :create_additions => false) + + if options[:except] + Array(options[:except]).each do |except_key| + existing_json.delete(except_key) + end + end + merged_json = existing_json.merge(request_json) + if merged_json.size > request_json.size return FFI_Yajl::Encoder.encode(merged_json, :pretty => true) end end + request.body end + + private + + # Get the value of the (first existing) identity key from the request body or nil + def identity_key_value(request) + request_json = FFI_Yajl::Parser.parse(request.body, :create_additions => false) + identity_keys.map { |k| request_json[k] }.compact.first + end + + # Does this request change the value of the identity key? + def is_rename?(request) + return false unless key = identity_key_value(request) + key != request.rest_path[-1] + end end end end diff --git a/lib/chef_zero/endpoints/server_api_version_endpoint.rb b/lib/chef_zero/endpoints/server_api_version_endpoint.rb index 631f105..8ddeaba 100644 --- a/lib/chef_zero/endpoints/server_api_version_endpoint.rb +++ b/lib/chef_zero/endpoints/server_api_version_endpoint.rb @@ -7,7 +7,7 @@ module ChefZero API_VERSION = 1 def get(request) json_response(200, {"min_api_version"=>MIN_API_VERSION, "max_api_version"=>MAX_API_VERSION}, - request.api_version, API_VERSION) + request_version: request.api_version, response_version: API_VERSION) end end end diff --git a/lib/chef_zero/endpoints/user_key_endpoint.rb b/lib/chef_zero/endpoints/user_key_endpoint.rb new file mode 100644 index 0000000..4e4872b --- /dev/null +++ b/lib/chef_zero/endpoints/user_key_endpoint.rb @@ -0,0 +1,32 @@ +require 'ffi_yajl' +require 'chef_zero/rest_base' + +module ChefZero + module Endpoints + # /users/USER/keys/NAME + class UserKeyEndpoint < RestBase + def get(request) + path = [ "user_keys", *request.rest_path[1..-1] ] + already_json_response(200, get_data(request, path)) + end + + def delete(request) + path = [ "user_keys", *request.rest_path[1..-1] ] + + data = get_data(request, path) + delete_data(request, path) + + already_json_response(200, data) + end + + def put(request) + path = [ "user_keys", *request.rest_path[1..-1] ] + + # We grab the old data to trigger a 404 if it doesn't exist + get_data(request, path) + + set_data(request, path, request.body) + end + end + end +end diff --git a/lib/chef_zero/endpoints/user_keys_endpoint.rb b/lib/chef_zero/endpoints/user_keys_endpoint.rb new file mode 100644 index 0000000..c6aea07 --- /dev/null +++ b/lib/chef_zero/endpoints/user_keys_endpoint.rb @@ -0,0 +1,80 @@ +require 'ffi_yajl' +require 'chef_zero/rest_base' + +module ChefZero + module Endpoints + # /users/USER/keys + + class UserKeysEndpoint < RestBase + DATE_FORMAT = "%FT%TZ" # e.g. 2015-12-24T21:00:00Z + + def get(request) + username = request.rest_path[1] + path = [ "user_keys", username, "keys" ] + + result = list_data(request, path).map do |key_name| + list_key(request, [ *path, key_name ]) + end + + json_response(200, result) + end + + def post(request) + username = request.rest_path[1] + request_body = FFI_Yajl::Parser.parse(request.body) + + validate_user!(request) + + generate_keys = request_body["public_key"].nil? + + if generate_keys + private_key, public_key = server.gen_key_pair + else + public_key = request_body['public_key'] + end + + key_name = request_body["name"] + path = [ "user_keys", username, "keys" ] + + data = FFI_Yajl::Encoder.encode( + "name" => key_name, + "public_key" => public_key, + "expiration_date" => request_body["expiration_date"] + ) + + create_data(request, path, key_name, data, :create_dir) + + response_body = { + "uri" => build_uri(request.base_uri, + [ "users", username, "keys", key_name ]) + } + response_body["private_key"] = private_key if generate_keys + + json_response(201, response_body, + headers: { "Location" => response_body["uri"] }) + end + + private + + def list_key(request, data_path) + data = FFI_Yajl::Parser.parse(get_data(request, data_path), create_additions: false) + uri = build_uri(request.base_uri, [ "users", *data_path[1..-1] ]) + + expiration_date = if data["expiration_date"] == "infinity" + Float::INFINITY + else + DateTime.strptime(data["expiration_date"], DATE_FORMAT) + end + + { "name" => data_path[-1], + "uri" => uri, + "expired" => DateTime.now > expiration_date } + end + + def validate_user!(request) + # Try loading the user so a 404 is returned if the user doesn't + get_data(request, request.rest_path[0, 2]) + end + end + end +end diff --git a/lib/chef_zero/rest_base.rb b/lib/chef_zero/rest_base.rb index a03f4aa..f276426 100644 --- a/lib/chef_zero/rest_base.rb +++ b/lib/chef_zero/rest_base.rb @@ -5,6 +5,9 @@ require 'chef_zero/chef_data/acl_path' module ChefZero class RestBase + DEFAULT_REQUEST_VERSION = 0 + DEFAULT_RESPONSE_VERSION = 0 + def initialize(server) @server = server end @@ -16,21 +19,28 @@ module ChefZero end def check_api_version(request) - version = request.api_version - return nil if version.nil? # Not present in headers + return if request.api_version.nil? # Not present in headers + version = request.api_version.to_i + + unless version.to_s == request.api_version.to_s # Version is not an Integer + return json_response(406, + { "username" => request.requestor }, + request_version: -1, response_version: -1 + ) + end - if version.to_i.to_s != version.to_s # Version is not an Integer - return json_response(406, { "username" => request.requestor }, -1, -1) - elsif version.to_i > MAX_API_VERSION or version.to_i < MIN_API_VERSION + if version > MAX_API_VERSION || version < MIN_API_VERSION response = { "error" => "invalid-x-ops-server-api-version", "message" => "Specified version #{version} not supported", "min_api_version" => MIN_API_VERSION, "max_api_version" => MAX_API_VERSION } - return json_response(406, response, version, -1) - else - return nil + + return json_response(406, + response, + request_version: version, response_version: -1 + ) end end @@ -196,26 +206,59 @@ module ChefZero end def error(response_code, error, opts={}) - json_response(response_code, {"error" => [error]}, 0, 0, opts) + json_response(response_code, { "error" => [ error ] }, opts) end - def json_response(response_code, json, request_version=0, response_version=0, opts={pretty: true}) - do_pretty_json = !!opts[:pretty] # make sure we have a proper Boolean. - already_json_response(response_code, FFI_Yajl::Encoder.encode(json, :pretty => do_pretty_json), request_version, response_version) + # Serializes `data` to JSON and returns an Array with the + # response code, HTTP headers and JSON body. + # + # @param [Fixnum] response_code HTTP response code + # @param [Hash] data The data for the response body as a Hash + # @param [Hash] options + # @option options [Hash] :headers (see #already_json_response) + # @option options [Boolean] :pretty (true) Pretty-format the JSON + # @option options [Fixnum] :request_version (see #already_json_response) + # @option options [Fixnum] :response_version (see #already_json_response) + # + # @return (see #already_json_response) + # + def json_response(response_code, data, options={}) + options = { pretty: true }.merge(options) + do_pretty_json = !!options.delete(:pretty) # make sure we have a proper Boolean. + json = FFI_Yajl::Encoder.encode(data, pretty: do_pretty_json) + already_json_response(response_code, json, options) end def text_response(response_code, text) [response_code, {"Content-Type" => "text/plain"}, text] end - def already_json_response(response_code, json_text, request_version=0, response_version=0) - header = { "min_version" => MIN_API_VERSION.to_s, "max_version" => MAX_API_VERSION.to_s, - "request_version" => request_version.to_s, - "response_version" => response_version.to_s } - [ response_code, - { "Content-Type" => "application/json", - "X-Ops-Server-API-Version" => FFI_Yajl::Encoder.encode(header) }, - json_text ] + # Returns an Array with the response code, HTTP headers, and JSON body. + # + # @param [Fixnum] response_code The HTTP response code + # @param [String] json_text The JSON body for the response + # @param [Hash] options + # @option options [Hash] :headers ({}) HTTP headers (may override default headers) + # @option options [Fixnum] :request_version (0) Request API version + # @option options [Fixnum] :response_version (0) Response API version + # + # @return [Array(Fixnum, Hash{String => String}, String)] + # + def already_json_response(response_code, json_text, options={}) + version_header = FFI_Yajl::Encoder.encode( + "min_version" => MIN_API_VERSION.to_s, + "max_version" => MAX_API_VERSION.to_s, + "request_version" => options[:request_version] || DEFAULT_REQUEST_VERSION.to_s, + "response_version" => options[:response_version] || DEFAULT_RESPONSE_VERSION.to_s + ) + + headers = { + "Content-Type" => "application/json", + "X-Ops-Server-API-Version" => version_header + } + headers.merge!(options[:headers]) if options[:headers] + + [ response_code, headers, json_text ] end # To be called from inside rest endpoints diff --git a/lib/chef_zero/server.rb b/lib/chef_zero/server.rb index d6f27c4..f0ad9b1 100644 --- a/lib/chef_zero/server.rb +++ b/lib/chef_zero/server.rb @@ -94,6 +94,8 @@ require 'chef_zero/endpoints/system_recovery_endpoint' require 'chef_zero/endpoints/user_association_requests_endpoint' require 'chef_zero/endpoints/user_association_requests_count_endpoint' require 'chef_zero/endpoints/user_association_request_endpoint' +require 'chef_zero/endpoints/user_key_endpoint' +require 'chef_zero/endpoints/user_keys_endpoint' require 'chef_zero/endpoints/user_organizations_endpoint' require 'chef_zero/endpoints/file_store_file_endpoint' require 'chef_zero/endpoints/not_found_endpoint' @@ -537,6 +539,8 @@ module ChefZero [ "/users/*/association_requests", UserAssociationRequestsEndpoint.new(self) ], [ "/users/*/association_requests/count", UserAssociationRequestsCountEndpoint.new(self) ], [ "/users/*/association_requests/*", UserAssociationRequestEndpoint.new(self) ], + [ "/users/*/keys", UserKeysEndpoint.new(self) ], + [ "/users/*/keys/*", UserKeyEndpoint.new(self) ], [ "/users/*/organizations", UserOrganizationsEndpoint.new(self) ], [ "/authenticate_user", AuthenticateUserEndpoint.new(self) ], [ "/system_recovery", SystemRecoveryEndpoint.new(self) ], |