From a46aa60353503387dd5089d74754ff8e8b56a361 Mon Sep 17 00:00:00 2001 From: Tim Smith Date: Tue, 28 Jan 2020 10:58:35 -0800 Subject: Move knife-acl gem commands into chef in their own namespaces Ship these knife commands so we can kill off knife-acl, but move them under their own namespaces. Signed-off-by: Tim Smith --- lib/chef/knife.rb | 2 - lib/chef/knife/acl_add.rb | 57 +++++++++++ lib/chef/knife/acl_base.rb | 183 +++++++++++++++++++++++++++++++++++ lib/chef/knife/acl_bulk_add.rb | 78 +++++++++++++++ lib/chef/knife/acl_bulk_remove.rb | 83 ++++++++++++++++ lib/chef/knife/acl_remove.rb | 62 ++++++++++++ lib/chef/knife/acl_show.rb | 56 +++++++++++ lib/chef/knife/group_add.rb | 55 +++++++++++ lib/chef/knife/group_create.rb | 49 ++++++++++ lib/chef/knife/group_destroy.rb | 53 ++++++++++ lib/chef/knife/group_list.rb | 43 ++++++++ lib/chef/knife/group_remove.rb | 56 +++++++++++ lib/chef/knife/group_show.rb | 49 ++++++++++ lib/chef/knife/user_dissociate.rb | 42 ++++++++ lib/chef/knife/user_invite_add.rb | 43 ++++++++ lib/chef/knife/user_invite_list.rb | 34 +++++++ lib/chef/knife/user_invite_recind.rb | 63 ++++++++++++ 17 files changed, 1006 insertions(+), 2 deletions(-) create mode 100644 lib/chef/knife/acl_add.rb create mode 100644 lib/chef/knife/acl_base.rb create mode 100644 lib/chef/knife/acl_bulk_add.rb create mode 100644 lib/chef/knife/acl_bulk_remove.rb create mode 100644 lib/chef/knife/acl_remove.rb create mode 100644 lib/chef/knife/acl_show.rb create mode 100644 lib/chef/knife/group_add.rb create mode 100644 lib/chef/knife/group_create.rb create mode 100644 lib/chef/knife/group_destroy.rb create mode 100644 lib/chef/knife/group_list.rb create mode 100644 lib/chef/knife/group_remove.rb create mode 100644 lib/chef/knife/group_show.rb create mode 100644 lib/chef/knife/user_dissociate.rb create mode 100644 lib/chef/knife/user_invite_add.rb create mode 100644 lib/chef/knife/user_invite_list.rb create mode 100644 lib/chef/knife/user_invite_recind.rb diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index 255636868f..2975dcb4e9 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -279,8 +279,6 @@ class Chef if CHEF_ORGANIZATION_MANAGEMENT.include?(args[0]) list_commands("CHEF ORGANIZATION MANAGEMENT") - elsif OPSCODE_HOSTED_CHEF_ACCESS_CONTROL.include?(args[0]) - list_commands("OPSCODE HOSTED CHEF ACCESS CONTROL") elsif category_commands = guess_category(args) list_commands(category_commands) elsif OFFICIAL_PLUGINS.include?(args[0]) # command was an uninstalled official chef knife plugin diff --git a/lib/chef/knife/acl_add.rb b/lib/chef/knife/acl_add.rb new file mode 100644 index 0000000000..df9bc86e70 --- /dev/null +++ b/lib/chef/knife/acl_add.rb @@ -0,0 +1,57 @@ +# +# Author:: Steven Danna (steve@chef.io) +# Author:: Jeremiah Snapp (jeremiah@chef.io) +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class AclAdd < Chef::Knife + category "acl" + banner "knife acl add MEMBER_TYPE MEMBER_NAME OBJECT_TYPE OBJECT_NAME PERMS" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + member_type, member_name, object_type, object_name, perms = name_args + + if name_args.length != 5 + show_usage + ui.fatal "You must specify the member type [client|group], member name, object type, object name and perms" + exit 1 + end + + unless %w{client group}.include?(member_type) + ui.fatal "ERROR: To enforce best practice, knife-acl can only add a client or a group to an ACL." + ui.fatal " See the knife-acl README for more information." + exit 1 + end + validate_perm_type!(perms) + validate_member_name!(member_name) + validate_object_name!(object_name) + validate_object_type!(object_type) + validate_member_exists!(member_type, member_name) + + add_to_acl!(member_type, member_name, object_type, object_name, perms) + end + end + end +end diff --git a/lib/chef/knife/acl_base.rb b/lib/chef/knife/acl_base.rb new file mode 100644 index 0000000000..14d80948b1 --- /dev/null +++ b/lib/chef/knife/acl_base.rb @@ -0,0 +1,183 @@ +# +# Author:: Steven Danna (steve@chef.io) +# Author:: Jeremiah Snapp () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + module AclBase + + PERM_TYPES = %w{create read update delete grant}.freeze unless defined? PERM_TYPES + MEMBER_TYPES = %w{client group user}.freeze unless defined? MEMBER_TYPES + OBJECT_TYPES = %w{clients containers cookbooks data environments groups nodes roles policies policy_groups}.freeze unless defined? OBJECT_TYPES + OBJECT_NAME_SPEC = /^[\-[:alnum:]_\.]+$/.freeze unless defined? OBJECT_NAME_SPEC + + def validate_object_type!(type) + unless OBJECT_TYPES.include?(type) + ui.fatal "Unknown object type \"#{type}\". The following types are permitted: #{OBJECT_TYPES.join(", ")}" + exit 1 + end + end + + def validate_object_name!(name) + unless OBJECT_NAME_SPEC.match(name) + ui.fatal "Invalid name: #{name}" + exit 1 + end + end + + def validate_member_type!(type) + unless MEMBER_TYPES.include?(type) + ui.fatal "Unknown member type \"#{type}\". The following types are permitted: #{MEMBER_TYPES.join(", ")}" + exit 1 + end + end + + def validate_member_name!(name) + # Same rules apply to objects and members + validate_object_name!(name) + end + + def validate_perm_type!(perms) + perms.split(",").each do |perm| + unless PERM_TYPES.include?(perm) + ui.fatal "Invalid permission \"#{perm}\". The following permissions are permitted: #{PERM_TYPES.join(",")}" + exit 1 + end + end + end + + def validate_member_exists!(member_type, member_name) + true if rest.get_rest("#{member_type}s/#{member_name}") + rescue NameError + # ignore "NameError: uninitialized constant Chef::ApiClient" when finding a client + true + rescue + ui.fatal "#{member_type} '#{member_name}' does not exist" + exit 1 + end + + def is_usag?(gname) + gname.length == 32 && gname =~ /^[0-9a-f]+$/ + end + + def get_acl(object_type, object_name) + rest.get_rest("#{object_type}/#{object_name}/_acl?detail=granular") + end + + def get_ace(object_type, object_name, perm) + get_acl(object_type, object_name)[perm] + end + + def add_to_acl!(member_type, member_name, object_type, object_name, perms) + acl = get_acl(object_type, object_name) + perms.split(",").each do |perm| + ui.msg "Adding '#{member_name}' to '#{perm}' ACE of '#{object_name}'" + ace = acl[perm] + + case member_type + when "client", "user" + # Our PUT body depends on the type of reply we get from _acl?detail=granular + # When the server replies with json attributes 'users' and 'clients', + # we'll want to modify entries under the same keys they arrived.- their presence + # in the body tells us that CS will accept them in a PUT. + # Older version of chef-server will continue to use 'actors' for a combined list + # and expect the same in the body. + key = "#{member_type}s" + key = "actors" unless ace.key? key + next if ace[key].include?(member_name) + + ace[key] << member_name + when "group" + next if ace["groups"].include?(member_name) + + ace["groups"] << member_name + end + + update_ace!(object_type, object_name, perm, ace) + end + end + + def remove_from_acl!(member_type, member_name, object_type, object_name, perms) + acl = get_acl(object_type, object_name) + perms.split(",").each do |perm| + ui.msg "Removing '#{member_name}' from '#{perm}' ACE of '#{object_name}'" + ace = acl[perm] + + case member_type + when "client", "user" + key = "#{member_type}s" + key = "actors" unless ace.key? key + next unless ace[key].include?(member_name) + + ace[key].delete(member_name) + when "group" + next unless ace["groups"].include?(member_name) + + ace["groups"].delete(member_name) + end + + update_ace!(object_type, object_name, perm, ace) + end + end + + def update_ace!(object_type, object_name, ace_type, ace) + rest.put_rest("#{object_type}/#{object_name}/_acl/#{ace_type}", ace_type => ace) + end + + def add_to_group!(member_type, member_name, group_name) + validate_member_exists!(member_type, member_name) + existing_group = rest.get_rest("groups/#{group_name}") + ui.msg "Adding '#{member_name}' to '#{group_name}' group" + unless existing_group["#{member_type}s"].include?(member_name) + existing_group["#{member_type}s"] << member_name + new_group = { + "groupname" => existing_group["groupname"], + "orgname" => existing_group["orgname"], + "actors" => { + "users" => existing_group["users"], + "clients" => existing_group["clients"], + "groups" => existing_group["groups"], + }, + } + rest.put_rest("groups/#{group_name}", new_group) + end + end + + def remove_from_group!(member_type, member_name, group_name) + validate_member_exists!(member_type, member_name) + existing_group = rest.get_rest("groups/#{group_name}") + ui.msg "Removing '#{member_name}' from '#{group_name}' group" + if existing_group["#{member_type}s"].include?(member_name) + existing_group["#{member_type}s"].delete(member_name) + new_group = { + "groupname" => existing_group["groupname"], + "orgname" => existing_group["orgname"], + "actors" => { + "users" => existing_group["users"], + "clients" => existing_group["clients"], + "groups" => existing_group["groups"], + }, + } + rest.put_rest("groups/#{group_name}", new_group) + end + end + end + end +end diff --git a/lib/chef/knife/acl_bulk_add.rb b/lib/chef/knife/acl_bulk_add.rb new file mode 100644 index 0000000000..ab99a2884b --- /dev/null +++ b/lib/chef/knife/acl_bulk_add.rb @@ -0,0 +1,78 @@ +# +# Author:: Jeremiah Snapp (jeremiah@chef.io) +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class AclBulkAdd < Chef::Knife + category "acl" + banner "knife acl bulk add MEMBER_TYPE MEMBER_NAME OBJECT_TYPE REGEX PERMS" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + member_type, member_name, object_type, regex, perms = name_args + object_name_matcher = /#{regex}/ + + if name_args.length != 5 + show_usage + ui.fatal "You must specify the member type [client|group], member name, object type, object name REGEX and perms" + exit 1 + end + + unless %w{client group}.include?(member_type) + ui.fatal "ERROR: To enforce best practice, knife-acl can only add a client or a group to an ACL." + ui.fatal " See the knife-acl README for more information." + exit 1 + end + validate_perm_type!(perms) + validate_member_name!(member_name) + validate_object_type!(object_type) + validate_member_exists!(member_type, member_name) + + if %w{containers groups}.include?(object_type) + ui.fatal "bulk modifying the ACL of #{object_type} is not permitted" + exit 1 + end + + objects_to_modify = [] + all_objects = rest.get_rest(object_type) + objects_to_modify = all_objects.keys.select { |object_name| object_name =~ object_name_matcher } + + if objects_to_modify.empty? + ui.info "No #{object_type} match the expression /#{regex}/" + exit 0 + end + + ui.msg("The ACL of the following #{object_type} will be modified:") + ui.msg("") + ui.msg(ui.list(objects_to_modify.sort, :columns_down)) + ui.msg("") + ui.confirm("Are you sure you want to modify the ACL of these #{object_type}?") + + objects_to_modify.each do |object_name| + add_to_acl!(member_type, member_name, object_type, object_name, perms) + end + end + end + end +end diff --git a/lib/chef/knife/acl_bulk_remove.rb b/lib/chef/knife/acl_bulk_remove.rb new file mode 100644 index 0000000000..a87f6464ed --- /dev/null +++ b/lib/chef/knife/acl_bulk_remove.rb @@ -0,0 +1,83 @@ +# +# Author:: Jeremiah Snapp (jeremiah@chef.io) +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class AclBulkRemove < Chef::Knife + category "acl" + banner "knife acl bulk remove MEMBER_TYPE MEMBER_NAME OBJECT_TYPE REGEX PERMS" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + member_type, member_name, object_type, regex, perms = name_args + object_name_matcher = /#{regex}/ + + if name_args.length != 5 + show_usage + ui.fatal "You must specify the member type [client|group|user], member name, object type, object name REGEX and perms" + exit 1 + end + + if member_name == "pivotal" && %w{client user}.include?(member_type) + ui.fatal "ERROR: 'pivotal' is a system user so knife-acl will not remove it from an ACL." + exit 1 + end + if member_name == "admins" && member_type == "group" && perms.to_s.split(",").include?("grant") + ui.fatal "ERROR: knife-acl will not remove the 'admins' group from the 'grant' ACE." + ui.fatal " Removal could prevent future attempts to modify permissions." + exit 1 + end + validate_perm_type!(perms) + validate_member_type!(member_type) + validate_member_name!(member_name) + validate_object_type!(object_type) + validate_member_exists!(member_type, member_name) + + if %w{containers groups}.include?(object_type) + ui.fatal "bulk modifying the ACL of #{object_type} is not permitted" + exit 1 + end + + objects_to_modify = [] + all_objects = rest.get_rest(object_type) + objects_to_modify = all_objects.keys.select { |object_name| object_name =~ object_name_matcher } + + if objects_to_modify.empty? + ui.info "No #{object_type} match the expression /#{regex}/" + exit 0 + end + + ui.msg("The ACL of the following #{object_type} will be modified:") + ui.msg("") + ui.msg(ui.list(objects_to_modify.sort, :columns_down)) + ui.msg("") + ui.confirm("Are you sure you want to modify the ACL of these #{object_type}?") + + objects_to_modify.each do |object_name| + remove_from_acl!(member_type, member_name, object_type, object_name, perms) + end + end + end + end +end diff --git a/lib/chef/knife/acl_remove.rb b/lib/chef/knife/acl_remove.rb new file mode 100644 index 0000000000..0f5dceeaff --- /dev/null +++ b/lib/chef/knife/acl_remove.rb @@ -0,0 +1,62 @@ +# +# Author:: Steven Danna (steve@chef.io) +# Author:: Jeremiah Snapp (jeremiah@chef.io) +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class AclRemove < Chef::Knife + category "acl" + banner "knife acl remove MEMBER_TYPE MEMBER_NAME OBJECT_TYPE OBJECT_NAME PERMS" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + member_type, member_name, object_type, object_name, perms = name_args + + if name_args.length != 5 + show_usage + ui.fatal "You must specify the member type [client|group|user], member name, object type, object name and perms" + exit 1 + end + + if member_name == "pivotal" && %w{client user}.include?(member_type) + ui.fatal "ERROR: 'pivotal' is a system user so knife-acl will not remove it from an ACL." + exit 1 + end + if member_name == "admins" && member_type == "group" && perms.to_s.split(",").include?("grant") + ui.fatal "ERROR: knife-acl will not remove the 'admins' group from the 'grant' ACE." + ui.fatal " Removal could prevent future attempts to modify permissions." + exit 1 + end + validate_perm_type!(perms) + validate_member_type!(member_type) + validate_member_name!(member_name) + validate_object_name!(object_name) + validate_object_type!(object_type) + validate_member_exists!(member_type, member_name) + + remove_from_acl!(member_type, member_name, object_type, object_name, perms) + end + end + end +end diff --git a/lib/chef/knife/acl_show.rb b/lib/chef/knife/acl_show.rb new file mode 100644 index 0000000000..1955b54969 --- /dev/null +++ b/lib/chef/knife/acl_show.rb @@ -0,0 +1,56 @@ +# +# Author:: Steven Danna (steve@chef.io) +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class AclShow < Chef::Knife + category "acl" + banner "knife acl show OBJECT_TYPE OBJECT_NAME" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + object_type, object_name = name_args + + if name_args.length != 2 + show_usage + ui.fatal "You must specify an object type and object name" + exit 1 + end + + validate_object_type!(object_type) + validate_object_name!(object_name) + acl = get_acl(object_type, object_name) + PERM_TYPES.each do |perm| + # Filter out the actors field if we have + # users and clients. Note that if one is present, + # both will be - but we're checking both for completeness. + if acl[perm].key?("users") && acl[perm].key?("clients") + acl[perm].delete "actors" + end + end + ui.output acl + end + end + end +end diff --git a/lib/chef/knife/group_add.rb b/lib/chef/knife/group_add.rb new file mode 100644 index 0000000000..3ed46060db --- /dev/null +++ b/lib/chef/knife/group_add.rb @@ -0,0 +1,55 @@ +# +# Author:: Seth Falcon () +# Author:: Jeremiah Snapp () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class GroupAdd < Chef::Knife + category "group" + banner "knife group add MEMBER_TYPE MEMBER_NAME GROUP_NAME" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + member_type, member_name, group_name = name_args + + if name_args.length != 3 + show_usage + ui.fatal "You must specify member type [client|group|user], member name and group name" + exit 1 + end + + validate_member_name!(group_name) + validate_member_type!(member_type) + validate_member_name!(member_name) + + if group_name.downcase == "users" + ui.fatal "knife group can not manage members of Chef Infra Server's 'users' group, which contains all users." + exit 1 + end + + add_to_group!(member_type, member_name, group_name) + end + end + end +end diff --git a/lib/chef/knife/group_create.rb b/lib/chef/knife/group_create.rb new file mode 100644 index 0000000000..e714192872 --- /dev/null +++ b/lib/chef/knife/group_create.rb @@ -0,0 +1,49 @@ +# +# Author:: Seth Falcon () +# Author:: Jeremiah Snapp () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class GroupCreate < Chef::Knife + category "group" + banner "knife group create GROUP_NAME" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + group_name = name_args[0] + + if name_args.length != 1 + show_usage + ui.fatal "You must specify group name" + exit 1 + end + + validate_member_name!(group_name) + + ui.msg "Creating '#{group_name}' group" + rest.post_rest("groups", { groupname: group_name }) + end + end + end +end diff --git a/lib/chef/knife/group_destroy.rb b/lib/chef/knife/group_destroy.rb new file mode 100644 index 0000000000..e890882af0 --- /dev/null +++ b/lib/chef/knife/group_destroy.rb @@ -0,0 +1,53 @@ +# +# Author:: Christopher Maier () +# Author:: Jeremiah Snapp () +# Copyright:: Copyright 2015-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class GroupDestroy < Chef::Knife + category "group" + banner "knife group destroy GROUP_NAME" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + group_name = name_args[0] + + if name_args.length != 1 + show_usage + ui.fatal "You must specify group name" + exit 1 + end + + validate_member_name!(group_name) + + if %w{admins billing-admins clients users}.include?(group_name.downcase) + ui.fatal "The '#{group_name}' group is a special group that cannot not be destroyed" + exit 1 + end + ui.msg "Destroying '#{group_name}' group" + rest.delete_rest("groups/#{group_name}") + end + end + end +end diff --git a/lib/chef/knife/group_list.rb b/lib/chef/knife/group_list.rb new file mode 100644 index 0000000000..7e6e18f12d --- /dev/null +++ b/lib/chef/knife/group_list.rb @@ -0,0 +1,43 @@ +# +# Author:: Seth Falcon () +# Author:: Jeremiah Snapp () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class GroupList < Chef::Knife + category "group" + banner "knife group list" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + groups = rest.get_rest("groups").keys.sort + ui.output(remove_usags(groups)) + end + + def remove_usags(groups) + groups.select { |gname| !is_usag?(gname) } + end + end + end +end diff --git a/lib/chef/knife/group_remove.rb b/lib/chef/knife/group_remove.rb new file mode 100644 index 0000000000..5707c82f8b --- /dev/null +++ b/lib/chef/knife/group_remove.rb @@ -0,0 +1,56 @@ +# +# Author:: Seth Falcon () +# Author:: Jeremiah Snapp () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class GroupRemove < Chef::Knife + category "group" + banner "knife group remove MEMBER_TYPE MEMBER_NAME GROUP_NAME" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + member_type, member_name, group_name = name_args + + if name_args.length != 3 + show_usage + ui.fatal "You must specify member type [client|group|user], member name and group name" + exit 1 + end + + validate_member_name!(group_name) + validate_member_type!(member_type) + validate_member_name!(member_name) + + if group_name.downcase == "users" + ui.fatal "knife-acl can not manage members of the Users group" + ui.fatal "please read knife-acl's README.md for more information" + exit 1 + end + + remove_from_group!(member_type, member_name, group_name) + end + end + end +end diff --git a/lib/chef/knife/group_show.rb b/lib/chef/knife/group_show.rb new file mode 100644 index 0000000000..3fd1708bfa --- /dev/null +++ b/lib/chef/knife/group_show.rb @@ -0,0 +1,49 @@ +# +# Author:: Seth Falcon () +# Author:: Jeremiah Snapp () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class GroupShow < Chef::Knife + category "group" + banner "knife group show GROUP_NAME" + + deps do + require_relative "acl_base" + include Chef::Knife::AclBase + end + + def run + group_name = name_args[0] + + if name_args.length != 1 + show_usage + ui.fatal "You must specify group name" + exit 1 + end + + validate_member_name!(group_name) + + group = rest.get_rest("groups/#{group_name}") + ui.output group + end + end + end +end diff --git a/lib/chef/knife/user_dissociate.rb b/lib/chef/knife/user_dissociate.rb new file mode 100644 index 0000000000..640b9543d1 --- /dev/null +++ b/lib/chef/knife/user_dissociate.rb @@ -0,0 +1,42 @@ +# +# Author:: Steven Danna () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class UserDissociate < Chef::Knife + category "user" + banner "knife user dissociate USERNAMES" + + def run + if name_args.length < 1 + show_usage + ui.fatal("You must specify a username.") + exit 1 + end + users = name_args + ui.confirm("Are you sure you want to dissociate the following users: #{users.join(", ")}") + users.each do |u| + api_endpoint = "users/#{u}" + rest.delete_rest(api_endpoint) + end + end + end + end +end diff --git a/lib/chef/knife/user_invite_add.rb b/lib/chef/knife/user_invite_add.rb new file mode 100644 index 0000000000..8907b363c0 --- /dev/null +++ b/lib/chef/knife/user_invite_add.rb @@ -0,0 +1,43 @@ +# +# Author:: Steven Danna () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class UserInviteAdd < Chef::Knife + category "user" + banner "knife user invite add USERNAMES" + + def run + if name_args.length < 1 + show_usage + ui.fatal("You must specify a username.") + exit 1 + end + + users = name_args + api_endpoint = "association_requests/" + users.each do |u| + body = { user: u } + rest.post_rest(api_endpoint, body) + end + end + end + end +end diff --git a/lib/chef/knife/user_invite_list.rb b/lib/chef/knife/user_invite_list.rb new file mode 100644 index 0000000000..22ca4212f1 --- /dev/null +++ b/lib/chef/knife/user_invite_list.rb @@ -0,0 +1,34 @@ +# +# Author:: Steven Danna () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class UserInviteList < Chef::Knife + category "user" + banner "knife user invite list" + + def run + api_endpoint = "association_requests/" + invited_users = rest.get_rest(api_endpoint).map { |i| i["username"] } + ui.output(invited_users) + end + end + end +end diff --git a/lib/chef/knife/user_invite_recind.rb b/lib/chef/knife/user_invite_recind.rb new file mode 100644 index 0000000000..288913650d --- /dev/null +++ b/lib/chef/knife/user_invite_recind.rb @@ -0,0 +1,63 @@ +# +# Author:: Steven Danna () +# Copyright:: Copyright 2011-2020 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../knife" + +class Chef + class Knife + class UserInviteRecind < Chef::Knife + category "user" + banner "knife user invite recind [USERNAMES] (options)" + + option :all, + short: "-a", + long: "--all", + description: "Recind all invites!" + + def run + if (name_args.length < 1) && ! config.key?(:all) + show_usage + ui.fatal("You must specify a username.") + exit 1 + end + + # To recind we need to send a DELETE to association_requests/INVITE_ID + # For user friendliness we look up the invite ID based on username. + @invites = {} + usernames = name_args + rest.get_rest("association_requests").each { |i| @invites[i["username"]] = i["id"] } + if config[:all] + ui.confirm("Are you sure you want to recind all association requests") + @invites.each do |u, i| + rest.delete_rest("association_requests/#{i}") + end + else + ui.confirm("Are you sure you want to recind the association requests for: #{usernames.join(", ")}") + usernames.each do |u| + if @invites.key?(u) + rest.delete_rest("association_requests/#{@invites[u]}") + else + ui.fatal("No association request for #{u}.") + exit 1 + end + end + end + end + end + end +end -- cgit v1.2.1