knife-opc 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f81638cb44c3efb4b8b2a2c1e98ca1a48295a8e9
4
- data.tar.gz: 8166172b30bc738ac5ffb40ec8f492fb34fac43a
3
+ metadata.gz: 9f10de72126959cda281388a2e5ab0e4d0f01313
4
+ data.tar.gz: 3ed8f3d554ffa5b72b0d08c2e3b317184b6b1ce0
5
5
  SHA512:
6
- metadata.gz: 08ea03824872034a74c154a96f848614cc23c2cc870e20e546b2923de810f6257652ed0a6a48015ea3cac59f29a4aa5385e6c8a120b78e81a5030bff95a6cd1e
7
- data.tar.gz: 3f8ee073eb6e57d8f80b19e85e3a8288a2a69e6cf07f17451f3b6f9a10ed9f335f9d70d47241a88a22c939668aa5e8f4d792289065cb3ef1530b243a9a82e976
6
+ metadata.gz: 303ad9f15fbb77b3a5d1709c2df28e6b5c897885ba53b2b20a43491b159570240f64f0fbed6f17f0e5a761442724220acf418ec006e4550641e24e02fb741fd2
7
+ data.tar.gz: 2c09e76ff39ffaa8a0d6a459f11f834745370a5adac9be58ea94ed91a0a236249fd9ed12bf659e234fd676f50c48d1b523fbfcb06fa0564ab342c76cc5313f2d
data/README.md CHANGED
@@ -8,13 +8,24 @@
8
8
  # Description
9
9
 
10
10
  This knife plugin supports basic organization and user operations in
11
- Enterprise Chef (formerly Opscode Private Chef).
11
+ Enterprise Chef (formerly Opscode Private Chef) and Chef Server 12.
12
12
 
13
13
  # Installation
14
14
 
15
- This knife plugin is packaged as a gem. To install it, clone the
16
- git repository and run the following:
15
+ This knife plugin is packaged as a gem. To install it, run:
17
16
 
17
+ gem install knife-opc
18
+
19
+ If you are using ChefDK, run:
20
+
21
+ chef gem install knife-opc
22
+
23
+ ## Development version
24
+
25
+ To install the latest development version:
26
+
27
+ git clone https://github.com/opscode/knife-opc.git
28
+ cd knife-opc
18
29
  gem build knife-opc.gemspec
19
30
  gem install knife-opc-0.1.1.gem
20
31
 
@@ -36,17 +47,28 @@ of your OPC installation:
36
47
  chef_server_root https://chef.yourdomain.com/
37
48
 
38
49
  Note that most users in an OPC installation lack the permissions to
39
- run most of the commands from this plugin. In order to use commands
40
- such as `knife opc org create`, you must authenticate as the 'pivotal' user.
41
- Add the following to your knife.rb to use the user 'pivotal':
50
+ run most of the commands from this plugin. On Chef Server 12, the
51
+ majority of the commands provided by this plugin can be accessed via
52
+ `chef-server-ctl` wrapper commands that properly configure knife-opc
53
+ for administrative action. We recommend you use the wrapper commands
54
+ whenever possible
42
55
 
43
- node_name 'pivotal'
44
- client_key '/etc/opscode/pivotal.pem'
56
+ When using knife-opc directly, many of the commands require special
57
+ permissions. For instance, in order to use commands such as `knife opc
58
+ org create`, you must authenticate as the 'pivotal' user.
45
59
 
46
60
  Note that the key for the pivotal user is in /etc/opscode on any node
47
61
  in your Chef Server cluster. We recommend that you only use the
48
62
  pivotal user from a Chef Server itself and not copy this key off the
49
- machine.
63
+ machine. In that case, you should run knife opc on the **Frontend
64
+ server** as root, with a `knife.rb` in root's home directory.
65
+
66
+ current_dir = File.dirname(__FILE__)
67
+ log_level :info
68
+ log_location STDOUT
69
+ node_name "pivotal"
70
+ client_key "/etc/opscode/pivotal.pem"
71
+ chef_server_root "https://chef.yourdomain.com/"
50
72
 
51
73
  # Subcommands
52
74
 
@@ -83,6 +105,12 @@ Deletes the given OPC user.
83
105
 
84
106
  Will open $EDITOR. When finished, Knife will update the given OPC user.
85
107
 
108
+ ## knife opc user password USERNAME [PASSWORD | --enable_external_auth]
109
+
110
+ Command for managing password and authentication for a user.
111
+
112
+ The last argument should either be a string you want the password to or you can pass --enable_external_auth instead of a password to enable external authentication for this user.
113
+
86
114
  ## knife opc org list
87
115
 
88
116
  * `-w`, `--with-uri`:
@@ -110,16 +138,16 @@ validator client is returned.
110
138
 
111
139
  ## knife opc org delete ORG_NAME
112
140
 
113
- Deletes the given OPC user.
141
+ Deletes the given OPC organization.
114
142
 
115
- ## knife opc associate ORGNAME USERNAME
143
+ ## knife opc org user add ORGNAME USERNAME
116
144
 
117
- Associates a user with an organization. Requires that the named
118
- organization and user both exist.
145
+ Adds a user to an organization. Requires that the named organization
146
+ and user both exist.
119
147
 
120
- ## knife opc disassociate ORGNAME USERNAME
148
+ ## knife opc org user remove ORGNAME USERNAME
121
149
 
122
- Dissociates a user with an organization. Requires that the named
150
+ Removes a user from an organization. Requires that the named
123
151
  organization and user both exist, and that the user is currently
124
152
  associated with the organization.
125
153
 
@@ -134,7 +162,6 @@ associated with the organization.
134
162
  # TODO
135
163
 
136
164
  * `--with-users` option for `org show` subcommand.
137
- * Filter unused fields from `org show`.
138
165
 
139
166
  ## License ##
140
167
 
@@ -33,6 +33,10 @@ module Opc
33
33
 
34
34
  attr_accessor :org_name, :org_full_name
35
35
 
36
+ deps do
37
+ require 'chef/org'
38
+ end
39
+
36
40
  def run
37
41
  @org_name, @org_full_name = @name_args
38
42
 
@@ -42,45 +46,21 @@ module Opc
42
46
  exit 1
43
47
  end
44
48
 
45
- org_args = { :name => org_name, :full_name => org_full_name}
46
- @chef_rest = Chef::REST.new(Chef::Config[:chef_server_root])
47
- result = @chef_rest.post_rest("organizations/", org_args)
49
+ org = Chef::Org.from_hash({ 'name' => org_name,
50
+ 'full_name' => org_full_name}).create
48
51
  if config[:filename]
49
52
  File.open(config[:filename], "w") do |f|
50
- f.print(result['private_key'])
53
+ f.print(org.private_key)
51
54
  end
52
55
  else
53
- ui.msg result['private_key']
56
+ ui.msg org.private_key
54
57
  end
55
- associate_user config[:association_user] if config[:association_user]
56
- end
57
-
58
- def associate_user(username)
59
-
60
- # First, create and accept the organization invite
61
- request_body = {:user => username}
62
- response = @chef_rest.post_rest "organizations/#{org_name}/association_requests", request_body
63
- association_id = response["uri"].split("/").last
64
- @chef_rest.put_rest "users/#{username}/association_requests/#{association_id}", { :response => 'accept' }
65
58
 
66
- # Next, add the user to the admin and billing-admin group
67
- add_user_to_group(username, "admins")
68
- add_user_to_group(username, "billing-admins")
69
- end
70
-
71
-
72
- # Note, this should *really* use the same method
73
- # used in knife-acl
74
- def add_user_to_group(username, groupname)
75
- group = @chef_rest.get_rest "organizations/#{org_name}/groups/#{groupname}"
76
- body_hash = {
77
- :groupname => "#{groupname}",
78
- :actors => {
79
- "users" => group["actors"].concat([username]),
80
- "groups" => group["groups"]
81
- }
82
- }
83
- @chef_rest.put_rest "organizations/#{org_name}/groups/#{groupname}", body_hash
59
+ if config[:association_user]
60
+ org.associate_user(config[:association_user])
61
+ org.add_user_to_group('admins', config[:association_user])
62
+ org.add_user_to_group('billing-admins', config[:association_user])
63
+ end
84
64
  end
85
65
  end
86
66
  end
@@ -0,0 +1,48 @@
1
+ #
2
+ # Author:: Steven Danna (<steve@opscode.com>)
3
+ # Copyright:: Copyright 2011 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module Opc
20
+ class OpcOrgEdit < Chef::Knife
21
+ category "OPSCODE PRIVATE CHEF ORGANIZATION MANAGEMENT"
22
+ banner "knife opc org edit ORG"
23
+
24
+ def run
25
+ org_name = @name_args[0]
26
+
27
+ if org_name.nil?
28
+ show_usage
29
+ ui.fatal("You must specify an organization name")
30
+ exit 1
31
+ end
32
+
33
+ @chef_rest = Chef::REST.new(Chef::Config[:chef_server_root])
34
+ original_org = @chef_rest.get_rest("organizations/#{org_name}")
35
+ edited_org = edit_data(original_org)
36
+
37
+ if original_org == edited_org
38
+ ui.msg("Organization unchanged, not saving.")
39
+ exit
40
+ end
41
+
42
+ @chef_rest = Chef::REST.new(Chef::Config[:chef_server_root])
43
+ ui.msg edited_org
44
+ result = @chef_rest.put_rest("organizations/#{org_name}", edited_org)
45
+ ui.msg("Saved #{org_name}.")
46
+ end
47
+ end
48
+ end
@@ -17,11 +17,20 @@
17
17
  #
18
18
 
19
19
  module Opc
20
- class OpcOrgAssociate < Chef::Knife
20
+ class OpcOrgUserAdd < Chef::Knife
21
21
  category "OPSCODE PRIVATE CHEF ORGANIZATION MANAGEMENT"
22
- banner "knife opc org associate ORG_NAME USER_NAME"
22
+ banner "knife opc org user add ORG_NAME USER_NAME"
23
23
  attr_accessor :org_name, :username
24
24
 
25
+ option :admin,
26
+ :long => '--admin',
27
+ :short => '-a',
28
+ :description => 'Add user to admin group'
29
+
30
+ deps do
31
+ require 'chef/org'
32
+ end
33
+
25
34
  def run
26
35
  @org_name, @username = @name_args
27
36
 
@@ -31,20 +40,17 @@ module Opc
31
40
  exit 1
32
41
  end
33
42
 
34
- @chef_rest = Chef::REST.new(Chef::Config[:chef_server_root])
35
- request_body = {:user => username}
36
- response = @chef_rest.post_rest "organizations/#{org_name}/association_requests", request_body
37
- if response["error"]
38
- ui.msg response["error"]
39
- else
40
- association_id = response["uri"].split("/").last
41
- response = @chef_rest.put_rest "users/#{username}/association_requests/#{association_id}", { :response => 'accept' }
42
- if response["error"]
43
- ui.msg response["error"]
43
+ org = Chef::Org.new(@org_name)
44
+ begin
45
+ org.associate_user(@username)
46
+ rescue Net::HTTPServerException => e
47
+ if e.response.code == "409"
48
+ ui.msg "User #{username} already associated with organization #{org_name}"
44
49
  else
45
- ui.msg "User #{username} is now associated with organization #{org_name}"
50
+ raise e
46
51
  end
47
52
  end
53
+ org.add_user_to_group('admins', @username) if config[:admin]
48
54
  end
49
55
  end
50
56
  end
@@ -17,11 +17,15 @@
17
17
  #
18
18
 
19
19
  module Opc
20
- class OpcOrgDissociate < Chef::Knife
20
+ class OpcOrgUserRemove < Chef::Knife
21
21
  category "OPSCODE PRIVATE CHEF ORGANIZATION MANAGEMENT"
22
- banner "knife opc org dissociate ORG_NAME USER_NAME"
22
+ banner "knife opc org user remove ORG_NAME USER_NAME"
23
23
  attr_accessor :org_name, :username
24
24
 
25
+ deps do
26
+ require 'chef/org'
27
+ end
28
+
25
29
  def run
26
30
  @org_name, @username = @name_args
27
31
 
@@ -31,12 +35,16 @@ module Opc
31
35
  exit 1
32
36
  end
33
37
 
34
- @chef_rest = Chef::REST.new(Chef::Config[:chef_server_root])
35
- response = @chef_rest.delete_rest "organizations/#{org_name}/users/#{username}"
36
- if response["error"]
37
- ui.msg response["error"]
38
- else
39
- ui.msg "User #{username} has been dissociated from organization #{org_name}"
38
+ org = Chef::Org.new(@org_name)
39
+ begin
40
+ org.dissociate_user(@username)
41
+ rescue Net::HTTPServerException => e
42
+ if e.response.code == "404"
43
+ ui.msg "User #{username} is not associated with organization #{org_name}"
44
+ exit 1
45
+ else
46
+ raise e
47
+ end
40
48
  end
41
49
  end
42
50
  end
@@ -0,0 +1,73 @@
1
+ #
2
+ # Author:: Tyler Cloke (<tyler@getchef.com>)
3
+ # Copyright:: Copyright 2014 Chef, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module Opc
20
+ class OpcUserPassword < Chef::Knife
21
+ category "OPSCODE PRIVATE CHEF ORGANIZATION MANAGEMENT"
22
+ banner "knife opc user password USERNAME [PASSWORD | --enable_external_auth]"
23
+
24
+ option :enable_external_auth,
25
+ :long => "--enable-external-auth",
26
+ :short => "-e",
27
+ :description => "Enable external authentication for this user (such as LDAP)"
28
+
29
+ def run
30
+ # check that correct number of args was passed, should be either
31
+ # USERNAME PASSWORD or USERNAME --enable-external-auth
32
+ #
33
+ # note that you can't pass USERNAME PASSWORD --enable-external-auth
34
+ if !((@name_args.length == 2 && !config[:enable_external_auth]) || (@name_args.length == 1 && config[:enable_external_auth]))
35
+ show_usage
36
+ ui.fatal("You must pass two arguments")
37
+ ui.fatal("Note that --enable-external-auth cannot be passed with a password")
38
+ exit 1
39
+ end
40
+
41
+ user_name = @name_args[0]
42
+
43
+ # note that this will be nil if config[:enable_external_auth] is true
44
+ password = @name_args[1]
45
+
46
+ @chef_rest = Chef::REST.new(Chef::Config[:chef_server_root])
47
+
48
+ # since the API does not pass back whether recovery_authentication_enabled is
49
+ # true or false, there is no way of knowing if the user is using ldap or not,
50
+ # so we will update the user every time, instead of checking if we are actually
51
+ # changing anything before we PUT.
52
+ user = @chef_rest.get_rest("users/#{user_name}")
53
+
54
+ user["password"] = password if not password.nil?
55
+
56
+ # if --enable-external-auth was passed, enable it, else disable it.
57
+ # there is never a situation where we would want to enable ldap
58
+ # AND change the password. changing the password means that the user
59
+ # wants to disable ldap and put user in recover (if they are using ldap).
60
+ user["recovery_authentication_enabled"] = !config[:enable_external_auth]
61
+
62
+ @chef_rest = Chef::REST.new(Chef::Config[:chef_server_root])
63
+ begin
64
+ result = @chef_rest.put_rest("users/#{user_name}", user)
65
+ rescue => e
66
+ raise e
67
+ exit 1
68
+ end
69
+ ui.msg user
70
+ ui.msg("Authentication info updated for #{user_name}.")
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,143 @@
1
+ require 'chef/json_compat'
2
+ require 'chef/mixin/params_validate'
3
+ require 'chef/rest'
4
+
5
+ class Chef
6
+ class Org
7
+
8
+ include Chef::Mixin::ParamsValidate
9
+
10
+ def initialize(name='')
11
+ @name = name
12
+ @full_name = ''
13
+ # The Chef API returns the private key of the validator
14
+ # client on create
15
+ @private_key = nil
16
+ @guid = nil
17
+ end
18
+
19
+ def chef_rest
20
+ @chef_rest ||= Chef::REST.new(Chef::Config[:chef_server_root])
21
+ end
22
+
23
+ def name(arg=nil)
24
+ set_or_return(:name, arg,
25
+ :regex => /^[a-z0-9\-_]+$/)
26
+ end
27
+
28
+ def full_name(arg=nil)
29
+ set_or_return(:full_name,
30
+ arg, :kind_of => String)
31
+ end
32
+
33
+ def private_key(arg=nil)
34
+ set_or_return(:private_key,
35
+ arg, :kind_of => String)
36
+ end
37
+
38
+ def guid(arg=nil)
39
+ set_or_return(:guid,
40
+ arg, :kind_of => String)
41
+ end
42
+
43
+ def to_hash
44
+ result = {
45
+ "name" => @name,
46
+ "full_name" => @full_name
47
+ }
48
+ result["private_key"] = @private_key if @private_key
49
+ result["guid"] = @guid if @guid
50
+ result
51
+ end
52
+
53
+ def to_json(*a)
54
+ Chef::JSONCompat.to_json(to_hash, *a)
55
+ end
56
+
57
+ def create
58
+ payload = {:name => self.name, :full_name => self.full_name}
59
+ new_org = chef_rest.post_rest("organizations", payload)
60
+ Chef::Org.from_hash(self.to_hash.merge(new_org))
61
+ end
62
+
63
+ def update
64
+ payload = {:name => self.name, :full_name => self.full_name}
65
+ new_org = chef_rest.put_rest("organizations/#{name}", payload)
66
+ Chef::Org.from_hash(self.to_hash.merge(new_org))
67
+ end
68
+
69
+ def destroy
70
+ chef_rest.delete_rest("organizations/#{@name}")
71
+ end
72
+
73
+ def save
74
+ begin
75
+ create
76
+ rescue Net::HTTPServerException => e
77
+ if e.response.code == "409"
78
+ update
79
+ else
80
+ raise e
81
+ end
82
+ end
83
+ end
84
+
85
+ def associate_user(username)
86
+ request_body = {:user => username}
87
+ response = chef_rest.post_rest "organizations/#{@name}/association_requests", request_body
88
+ association_id = response["uri"].split("/").last
89
+ chef_rest.put_rest "users/#{username}/association_requests/#{association_id}", { :response => 'accept' }
90
+ end
91
+
92
+ def dissociate_user(username)
93
+ chef_rest.delete_rest "organizations/#{name}/users/#{username}"
94
+ end
95
+
96
+ def add_user_to_group(groupname, username)
97
+ group = chef_rest.get_rest "organizations/#{name}/groups/#{groupname}"
98
+ body_hash = {
99
+ :groupname => "#{groupname}",
100
+ :actors => {
101
+ "users" => group["actors"].concat([username]),
102
+ "groups" => group["groups"]
103
+ }
104
+ }
105
+ chef_rest.put_rest "organizations/#{name}/groups/#{groupname}", body_hash
106
+ end
107
+
108
+ # Class methods
109
+ def self.from_hash(org_hash)
110
+ org = Chef::Org.new
111
+ org.name org_hash['name']
112
+ org.full_name org_hash['full_name']
113
+ org.private_key org_hash['private_key'] if org_hash.key?('private_key')
114
+ org.guid org_hash['guid'] if org_hash.key?('guid')
115
+ org
116
+ end
117
+
118
+ def self.from_json(json)
119
+ Chef::Org.from_hash(Chef::JSONCompat.from_json(json))
120
+ end
121
+
122
+ class <<self
123
+ alias_method :json_create, :from_json
124
+ end
125
+
126
+ def self.load(org_name)
127
+ response = Chef::REST.new(Chef::Config[:chef_server_root]).get_rest("organizations/#{org_name}")
128
+ Chef::Org.from_hash(response)
129
+ end
130
+
131
+ def self.list(inflate=false)
132
+ orgs = Chef::REST.new(Chef::Config[:chef_server_root]).get_rest('organizations')
133
+ if inflate
134
+ orgs.inject({}) do |org_map, (name, _url)|
135
+ org_map[name] = Chef::Org.load(name)
136
+ org_map
137
+ end
138
+ else
139
+ orgs
140
+ end
141
+ end
142
+ end
143
+ end
@@ -1,3 +1,3 @@
1
1
  module KnifeOPC
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-opc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Danna
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-08 00:00:00.000000000 Z
11
+ date: 2014-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -76,17 +76,20 @@ extra_rdoc_files:
76
76
  files:
77
77
  - LICENSE
78
78
  - README.md
79
- - lib/chef/knife/opc_org_associate.rb
80
79
  - lib/chef/knife/opc_org_create.rb
81
80
  - lib/chef/knife/opc_org_delete.rb
82
- - lib/chef/knife/opc_org_dissociate.rb
81
+ - lib/chef/knife/opc_org_edit.rb
83
82
  - lib/chef/knife/opc_org_list.rb
84
83
  - lib/chef/knife/opc_org_show.rb
84
+ - lib/chef/knife/opc_org_user_add.rb
85
+ - lib/chef/knife/opc_org_user_remove.rb
85
86
  - lib/chef/knife/opc_user_create.rb
86
87
  - lib/chef/knife/opc_user_delete.rb
87
88
  - lib/chef/knife/opc_user_edit.rb
88
89
  - lib/chef/knife/opc_user_list.rb
90
+ - lib/chef/knife/opc_user_password.rb
89
91
  - lib/chef/knife/opc_user_show.rb
92
+ - lib/chef/org.rb
90
93
  - lib/knife-opc/version.rb
91
94
  homepage: http://wiki.opscode.com/display/chef
92
95
  licenses: []
@@ -107,9 +110,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
110
  version: '0'
108
111
  requirements: []
109
112
  rubyforge_project:
110
- rubygems_version: 2.2.1
113
+ rubygems_version: 2.2.2
111
114
  signing_key:
112
115
  specification_version: 4
113
116
  summary: Knife Tools for Opscode Chef Server
114
117
  test_files: []
115
- has_rdoc: