knife-opc 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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: