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

rename ChefKey to Actor #234

Merged
merged 1 commit into from
Oct 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/chef-vault.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
require "chef-vault/user"
require "chef-vault/certificate"
require "chef-vault/chef_api"
require "chef-vault/chef_key"
require "chef-vault/actor"

require "mixlib/log"

Expand Down
30 changes: 15 additions & 15 deletions lib/chef-vault/chef_key.rb → lib/chef-vault/actor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@
require "json"

class ChefVault
class ChefKey
class Actor

attr_accessor :key_string
attr_reader :actor_type
attr_reader :actor_name
attr_reader :type
attr_reader :name

def initialize(actor_type, actor_name)
if actor_type != "clients" && actor_type != "admins"
raise "You must pass either 'clients' or 'admins' as the first argument to ChefVault::ChefKey.new."
raise "You must pass either 'clients' or 'admins' as the first argument to ChefVault::Actor.new."
end
@actor_type = actor_type
@actor_name = actor_name
@type = actor_type
@name = actor_name
end

def key
Expand All @@ -46,13 +46,13 @@ def get_admin_key
raise http_error
when "404"
begin
ChefVault::Log.warn "The default key for #{actor_name} not found in users, trying client keys."
ChefVault::Log.warn "The default key for #{name} not found in users, trying client keys."
get_key("clients")
rescue Net::HTTPServerException => http_error
case http_error.response.code
when "404"
raise ChefVault::Exceptions::AdminNotFound,
"FATAL: Could not find default key for #{actor_name} in users or clients!"
"FATAL: Could not find default key for #{name} in users or clients!"
when "403"
print_forbidden_error
raise http_error
Expand All @@ -74,19 +74,19 @@ def get_client_key
raise http_error
elsif http_error.response.code.eql?("404")
raise ChefVault::Exceptions::ClientNotFound,
"#{actor_name} is not a valid chef client and/or node"
"#{name} is not a valid chef client and/or node"
else
raise http_error
end
end
end

def is_client?
actor_type == "clients"
type == "clients"
end

def is_admin?
actor_type == "admins"
type == "admins"
end

# @private
Expand All @@ -113,20 +113,20 @@ def chef_user
end

def get_key(request_actor_type)
api.org_scoped_rest_v1.get("#{request_actor_type}/#{actor_name}/keys/default").fetch("public_key")
api.org_scoped_rest_v1.get("#{request_actor_type}/#{name}/keys/default").fetch("public_key")
# If the keys endpoint doesn't exist, try getting it directly from the V0 chef object.
rescue Net::HTTPServerException => http_error
raise http_error unless http_error.response.code.eql?("404")
if request_actor_type.eql?("clients")
chef_api_client.load(actor_name).public_key
chef_api_client.load(name).public_key
else
chef_user.load(actor_name).public_key
chef_user.load(name).public_key
end
end

def print_forbidden_error
ChefVault::Log.error <<EOF
You received a 403 FORBIDDEN while requesting an #{actor_type} key for #{actor_name}.
ERROR: You received a 403 FORBIDDEN while requesting an #{type} key for #{name}.

If you are on Chef Server < 12.5:
Clients do not have access to all public keys within their org.
Expand Down
41 changes: 13 additions & 28 deletions lib/chef-vault/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def clients(search_or_client, action = :add)
handle_client_action(search_or_client, action)
elsif search_or_client.is_a?(Array)
search_or_client.each do |name|
client = load_client(name)
client = load_actor(name, "clients")
handle_client_action(client, action)
end
else
Expand All @@ -91,7 +91,7 @@ def clients(search_or_client, action = :add)
case action
when :add
begin
client_key = load_public_key(node.name, "clients")
client_key = load_actor(node.name, "clients")
add_client(client_key)
rescue ChefVault::Exceptions::ClientNotFound
ChefVault::Log.warn "node '#{node.name}' has no private key; skipping"
Expand Down Expand Up @@ -126,7 +126,7 @@ def search(search_query = nil)
def admins(admin_string, action = :add)
admin_string.split(",").each do |admin|
admin.strip!
admin_key = load_public_key(admin, "admins")
admin_key = load_actor(admin, "admins")
case action
when :add
keys.add(admin_key, @secret)
Expand Down Expand Up @@ -296,7 +296,7 @@ def self.load(vault, name, opts = {})
end

def delete_client(client_name)
client_key = load_public_key(client_name, "clients")
client_key = load_actor(client_name, "clients")
keys.delete(client_key)
end

Expand Down Expand Up @@ -383,23 +383,8 @@ def reload_raw_data
@raw_data
end

def load_client(client)
begin
client = Chef::ApiClient.load(client)
rescue Net::HTTPServerException => http_error
if http_error.response.code == "404"
raise ChefVault::Exceptions::ClientNotFound,
"#{client} is not a valid chef client"
else
raise http_error
end
end

client
end

def load_public_key(actor_name, type)
ChefVault::ChefKey.new(type, actor_name)
def load_actor(actor_name, type)
ChefVault::Actor.new(type, actor_name)
end

# removes unknown nodes by performing a node search
Expand All @@ -417,7 +402,7 @@ def remove_unknown_nodes
# now delete any flagged clients from the keys data bag
clients_to_remove.each do |client|
ChefVault::Log.warn "Removing unknown client '#{client}'"
keys.delete(load_public_key(client, "clients"))
keys.delete(load_actor(client, "clients"))
end
end

Expand Down Expand Up @@ -460,8 +445,8 @@ def client_exists?(clientname)
def handle_client_action(api_client, action)
case action
when :add
client_key = load_public_key(api_client.name, "clients")
add_client(client_key)
client = load_actor(api_client.name, "clients")
add_client(client)
when :delete
delete_client_or_node(api_client)
end
Expand All @@ -470,16 +455,16 @@ def handle_client_action(api_client, action)
# adds a client to the vault item keys
# @param client [Chef::ApiClient] the API client to add
# @return [void]
def add_client(client_key)
keys.add(client_key, @secret)
def add_client(client)
keys.add(client, @secret)
end

# removes a client to the vault item keys
# @param client_or_node [Chef::ApiClient, Chef::Node] the API client or node to remove
# @return [void]
def delete_client_or_node(client_or_node)
client_key = load_public_key(client_or_node.name, "clients")
keys.delete(client_key)
client = load_actor(client_or_node.name, "clients")
keys.delete(client)
end
end
end
10 changes: 5 additions & 5 deletions lib/chef-vault/item_keys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,19 @@ def include?(key)
end

def add(chef_key, data_bag_shared_secret)
type = chef_key.actor_type
type = chef_key.type
unless @raw_data.key?(type)
raise ChefVault::Exceptions::V1Format,
"cannot manage a v1 vault. See UPGRADE.md for help"
end
self[chef_key.actor_name] = ChefVault::ItemKeys.encode_key(chef_key.key, data_bag_shared_secret)
@raw_data[type] << chef_key.actor_name unless @raw_data[type].include?(chef_key.actor_name)
self[chef_key.name] = ChefVault::ItemKeys.encode_key(chef_key.key, data_bag_shared_secret)
@raw_data[type] << chef_key.name unless @raw_data[type].include?(chef_key.name)
@raw_data[type]
end

def delete(chef_key)
raw_data.delete(chef_key.actor_name)
raw_data[chef_key.actor_type].delete(chef_key.actor_name)
raw_data.delete(chef_key.name)
raw_data[chef_key.type].delete(chef_key.name)
end

def search_query(search_query = nil)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "spec_helper"

RSpec.describe ChefVault::ChefKey do
RSpec.describe ChefVault::Actor do
let(:actor_name) { "actor" }
let(:public_key_string) do
"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMXT9IOV9pkQsxsnhSx8\n8RX6GW3caxkjcXFfHg6E7zUVBFAsfw4B1D+eHAks3qrDB7UrUxsmCBXwU4dQHaQy\ngAn5Sv0Jc4CejDNL2EeCBLZ4TF05odHmuzyDdPkSZP6utpR7+uF7SgVQedFGySIB\nih86aM+HynhkJqgJYhoxkrdo/JcWjpk7YEmWb6p4esnvPWOpbcjIoFs4OjavWBOF\niTfpkS0SkygpLi/iQu9RQfd4hDMWCc6yh3Th/1nVMUd+xQCdUK5wxluAWSv8U0zu\nhiIlZNazpCGHp+3QdP3f6rebmQA8pRM8qT5SlOvCYPk79j+IMUVSYrR4/DTZ+VM+\naQIDAQAB\n-----END PUBLIC KEY-----\n"
Expand Down
4 changes: 2 additions & 2 deletions spec/chef-vault/item_keys_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
end

shared_examples_for "proper key management" do
let(:chef_key) { ChefVault::ChefKey.new(type, name) }
let(:chef_key) { ChefVault::Actor.new(type, name) }
before do
allow(chef_key).to receive(:key) { public_key_string }
keys.add(chef_key, shared_secret)
Expand All @@ -51,7 +51,7 @@

it "removes the actor's name from the data bag and from the array for the actor's type" do
keys.delete(chef_key)
expect(keys.has_key?(chef_key.actor_name)).to eq(false)
expect(keys.has_key?(chef_key.name)).to eq(false)
expect(keys[type].include?(name)).to eq(false)
end
end
Expand Down
31 changes: 15 additions & 16 deletions spec/chef-vault/item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
client_key = double("client_key",
name: "testnode",
public_key: OpenSSL::PKey::RSA.new(1024).public_key)
allow(item).to receive(:load_public_key).with("testnode", "clients").and_return(client_key)
allow(item).to receive(:load_actor).with("testnode", "clients").and_return(client_key)

expect(item).not_to receive(:save)
expect(keys).to receive(:save)
Expand All @@ -210,24 +210,24 @@
before do
# node with valid client proper loads client key
allow(node_with_valid_client).to receive(:name).and_return("foo")
allow(item).to receive(:load_public_key).with("foo", "clients").and_return(client_key)
allow(item).to receive(:load_actor).with("foo", "clients").and_return(client_key)
privkey = OpenSSL::PKey::RSA.new(1024)
pubkey = privkey.public_key
allow(client_key).to receive(:key).and_return(pubkey.to_pem)
allow(client_key).to receive(:actor_name).and_return("foo")
allow(client_key).to receive(:actor_type).and_return("clients")
allow(client_key).to receive(:name).and_return("foo")
allow(client_key).to receive(:type).and_return("clients")

# node without client throws relevant error on key load
allow(node_without_valid_client).to receive(:name).and_return("bar")
allow(item).to receive(:load_public_key).with("bar", "clients").and_raise(ChefVault::Exceptions::ClientNotFound)
allow(item).to receive(:load_actor).with("bar", "clients").and_raise(ChefVault::Exceptions::ClientNotFound)

allow(query_result)
.to receive(:search)
.with(Symbol, String)
.and_yield(node_with_valid_client).and_yield(node_without_valid_client)
.with(Symbol, String)
.and_yield(node_with_valid_client).and_yield(node_without_valid_client)
allow(Chef::Search::Query)
.to receive(:new)
.and_return(query_result)
.and_return(query_result)
end

it "should not blow up when search returns a node without a public key" do
Expand All @@ -252,10 +252,10 @@
client.name client_name
privkey = OpenSSL::PKey::RSA.new(1024)
pubkey = privkey.public_key
allow(item).to receive(:load_public_key).with(client_name, "clients").and_return(client_key)
allow(item).to receive(:load_actor).with(client_name, "clients").and_return(client_key)
allow(client_key).to receive(:key).and_return(pubkey.to_pem)
allow(client_key).to receive(:actor_name).and_return(client_name)
allow(client_key).to receive(:actor_type).and_return("clients")
allow(client_key).to receive(:name).and_return(client_name)
allow(client_key).to receive(:type).and_return("clients")
end

context "when no action is passed" do
Expand Down Expand Up @@ -299,11 +299,10 @@
client.name client_name
privkey = OpenSSL::PKey::RSA.new(1024)
pubkey = privkey.public_key
allow(item).to receive(:load_client).with("foo").and_return(client)
allow(item).to receive(:load_public_key).with(client_name, "clients").and_return(client_key)
allow(item).to receive(:load_actor).with(client_name, "clients").and_return(client_key)
allow(client_key).to receive(:key).and_return(pubkey.to_pem)
allow(client_key).to receive(:actor_name).and_return(client_name)
allow(client_key).to receive(:actor_type).and_return("clients")
allow(client_key).to receive(:name).and_return(client_name)
allow(client_key).to receive(:type).and_return("clients")
end

context "when no action is passed" do
Expand Down Expand Up @@ -339,7 +338,7 @@

describe "#admins" do
before do
allow(item).to receive(:load_public_key).with("foo", "admins").and_raise(ChefVault::Exceptions::AdminNotFound)
allow(item).to receive(:load_actor).with("foo", "admins").and_raise(ChefVault::Exceptions::AdminNotFound)
end

it "should blow up if you try to use a node without a public key as an admin" do
Expand Down