From 31139fdca6e94e74a9c34bb0e0f51f127b1666e1 Mon Sep 17 00:00:00 2001 From: Shaun Davis Date: Sat, 1 Apr 2017 10:58:30 -0500 Subject: [PATCH 1/4] Few bug fixes and exposing grant permission to role --- Gemfile | 1 + README.md | 5 ++++- lib/etcdv3.rb | 15 ++++++++++++--- lib/etcdv3/auth.rb | 23 +++++++++++++++-------- spec/etcdv3/auth_spec.rb | 15 ++++++++++++--- spec/helpers/test_instance.rb | 2 +- 6 files changed, 45 insertions(+), 16 deletions(-) diff --git a/Gemfile b/Gemfile index a981d21..7bd0525 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,4 @@ source 'https://rubygems.org' gem "grpc" gem 'rspec' +gem 'guard-rspec', require: false diff --git a/README.md b/README.md index 9971149..c27bb7d 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,10 @@ conn.user_list **Role Management** ``` # Add Role -conn.add_role('rolename', 'readwrite', 'a', 'Z') +conn.add_role('rolename') + +# Grant Permission to Role +conn.grant_permission_to_role('rolename', 'readwrite', 'a', 'z') # Delete Role conn.delete_role('rolename') diff --git a/lib/etcdv3.rb b/lib/etcdv3.rb index a2f68d5..1336590 100644 --- a/lib/etcdv3.rb +++ b/lib/etcdv3.rb @@ -81,8 +81,8 @@ def authenticate(user, password) @options[:password] = password return true end + return false rescue GRPC::InvalidArgument => exception - print exception.message return false end @@ -90,26 +90,35 @@ def role_list auth.role_list end - def add_role(name, permission, key, range_end='') - auth.add_role(name, permission, key, range_end) + def add_role(name) + auth.add_role(name) end + # Fetches a specified role. def get_role(name) auth.get_role(name) end + # Delete role. def delete_role(name) auth.delete_role(name) end + # Grants role to an existing user. def grant_role_to_user(user, role) auth.grant_role_to_user(user, role) end + # Revokes role from a specified user. def revoke_role_from_user(user, role) auth.revoke_role_from_user(user, role) end + # Grants a new permission to an existing role. + def grant_permission_to_role(name, permission, key, range_end='') + auth.grant_permission_to_role(name, permission, key, range_end) + end + def enable_auth auth.enable_auth end diff --git a/lib/etcdv3/auth.rb b/lib/etcdv3/auth.rb index faab3af..ec5834f 100644 --- a/lib/etcdv3/auth.rb +++ b/lib/etcdv3/auth.rb @@ -49,14 +49,8 @@ def change_user_password(user, new_password) @stub.user_change_password(request, metadata: @metadata) end - def add_role(name, permission, key, range_end) - permission = Authpb::Permission.new( - permType: Etcd::Auth::PERMISSIONS[permission], key: key, range_end: range_end - ) - @stub.role_add( - Authpb::Role.new(name: name, keyPermission: [permission]), - metadata: @metadata - ) + def add_role(name) + @stub.role_add(Authpb::Role.new(name: name), metadata: @metadata) end def get_role(name) @@ -78,6 +72,19 @@ def revoke_role_from_user(user, role) @stub.user_revoke_role(request, metadata: @metadata) end + def grant_permission_to_role(name, permission, key, range_end) + permission = Authpb::Permission.new( + permType: Etcd::Auth::PERMISSIONS[permission], key: key, range_end: range_end + ) + @stub.role_grant_permission( + Etcdserverpb::AuthRoleGrantPermissionRequest.new( + name: name, + perm: permission + ), + metadata: @metadata + ) + end + def role_list @stub.role_list(Authpb::Role.new, metadata: @metadata) end diff --git a/spec/etcdv3/auth_spec.rb b/spec/etcdv3/auth_spec.rb index 0beaac9..3cb5a58 100644 --- a/spec/etcdv3/auth_spec.rb +++ b/spec/etcdv3/auth_spec.rb @@ -54,7 +54,7 @@ describe '#add_role' do after { conn.delete_role('add_role') } - subject { conn.add_role('add_role', 'readwrite', 'a', 'Z') } + subject { conn.add_role('add_role') } it 'adds a role' do expect(subject).to be_an_instance_of(Etcdserverpb::AuthRoleAddResponse) expect(conn.role_list.roles).to include('add_role') @@ -62,14 +62,14 @@ end describe '#get_role' do - before { conn.add_role('get_role', 'readwrite', 'a', 'Z') } + before { conn.add_role('get_role') } after { conn.delete_role('get_role') } subject { conn.get_role('get_role') } it { is_expected.to be_an_instance_of(Etcdserverpb::AuthRoleGetResponse) } end describe '#delete_role' do - before { conn.add_role('delete_role', 'readwrite', 'a', 'Z') } + before { conn.add_role('delete_role') } subject { conn.delete_role('delete_role') } it 'deletes role' do expect(subject).to be_an_instance_of(Etcdserverpb::AuthRoleDeleteResponse) @@ -82,6 +82,15 @@ it { is_expected.to be_an_instance_of(Etcdserverpb::AuthRoleListResponse) } end + describe '#grant_permission_to_role' do + before { conn.add_role('grant_perm') } + after { conn.delete_role('grant_perm') } + subject { conn.grant_permission_to_role('grant_perm', 'write', 'c', 'cc') } + it 'sets permission' do + expect(subject).to be_an_instance_of(Etcdserverpb::AuthRoleGrantPermissionResponse) + end + end + describe '#disable_auth' do before do conn.add_user('root', 'test') diff --git a/spec/helpers/test_instance.rb b/spec/helpers/test_instance.rb index f6323b4..dac478d 100644 --- a/spec/helpers/test_instance.rb +++ b/spec/helpers/test_instance.rb @@ -42,7 +42,7 @@ def spawn_etcd_instance end def stop - @pids.each { |pid| Process.kill('TERM', pid) } + @pids.each { |pid| Process.kill('TERM', pid) } rescue nil FileUtils.remove_entry_secure(@tmpdir, true) @pids.clear end From efd15818a71c6249ed90bf411627c2573d6d32b9 Mon Sep 17 00:00:00 2001 From: Shaun Davis Date: Sat, 1 Apr 2017 11:11:57 -0500 Subject: [PATCH 2/4] Adding revoke permission from role --- Guardfile | 31 +++++++++++++++++++++++++++++++ lib/etcdv3.rb | 18 ++++++++++++++++++ lib/etcdv3/auth.rb | 11 +++++++++++ spec/etcdv3/auth_spec.rb | 13 +++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 Guardfile diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..00bcf6a --- /dev/null +++ b/Guardfile @@ -0,0 +1,31 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +# Note: The cmd option is now required due to the increasing number of ways +# rspec may be run, below are examples of the most common uses. +# * bundler: 'bundle exec rspec' +# * bundler binstubs: 'bin/rspec' +# * spring: 'bin/rspec' (This will use spring if running and you have +# installed the spring binstubs per the docs) +# * zeus: 'zeus rspec' (requires the server to be started separately) +# * 'just' rspec: 'rspec' + +guard :rspec, cmd: 'rspec' do + watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } + watch('spec/spec_helper.rb') { "spec" } +end diff --git a/lib/etcdv3.rb b/lib/etcdv3.rb index 1336590..d354465 100644 --- a/lib/etcdv3.rb +++ b/lib/etcdv3.rb @@ -45,34 +45,43 @@ def initialize(options = {}) @metadata[:token] = auth.generate_token(user, password) unless user.nil? end + # Inserts a new key. def put(key, value) kv.put(key, value) end + # Fetches key(s). def get(key, range_end='') kv.get(key, range_end) end + # Creates new user. def add_user(user, password) auth.add_user(user, password) end + # Fetch specified user def get_user(user) auth.get_user(user) end + # Delete specified user. def delete_user(user) auth.delete_user(user) end + # Changes the specified users password. def change_user_password(user, new_password) auth.change_user_password(user, new_password) end + # List all users. def user_list auth.user_list end + # Authenticate using specified user and password. + # On successful authentication, an auth token will be assigned to the instance. def authenticate(user, password) token = auth.generate_token(user, password) if token @@ -86,10 +95,12 @@ def authenticate(user, password) return false end + # List all roles. def role_list auth.role_list end + # Add role with specified name. def add_role(name) auth.add_role(name) end @@ -119,10 +130,17 @@ def grant_permission_to_role(name, permission, key, range_end='') auth.grant_permission_to_role(name, permission, key, range_end) end + def revoke_permission_from_role(name, permission, key, range_end='') + auth.revoke_permission_from_role(name, permission, key, range_end) + end + + # Enables authentication. def enable_auth auth.enable_auth end + # Disables authentication. + # This will clear any active auth / token data. def disable_auth response = auth.disable_auth if response diff --git a/lib/etcdv3/auth.rb b/lib/etcdv3/auth.rb index ec5834f..e9b8568 100644 --- a/lib/etcdv3/auth.rb +++ b/lib/etcdv3/auth.rb @@ -85,6 +85,17 @@ def grant_permission_to_role(name, permission, key, range_end) ) end + def revoke_permission_from_role(name, permission, key, range_end) + @stub.role_revoke_permission( + Etcdserverpb::AuthRoleRevokePermissionRequest.new( + role: name, + key: key, + range_end: range_end + ), + metadata: @metadata + ) + end + def role_list @stub.role_list(Authpb::Role.new, metadata: @metadata) end diff --git a/spec/etcdv3/auth_spec.rb b/spec/etcdv3/auth_spec.rb index 3cb5a58..82ff0b2 100644 --- a/spec/etcdv3/auth_spec.rb +++ b/spec/etcdv3/auth_spec.rb @@ -91,6 +91,19 @@ end end + describe '#revoke_permission_from_role' do + before do + conn.add_role('myrole') + conn.grant_permission_to_role('myrole', 'write', 'c', 'cc') + end + after { conn.delete_role('myrole') } + subject { conn.revoke_permission_from_role('myrole', 'write', 'c', 'cc') } + it 'revokes permission' do + expect(subject).to be_an_instance_of(Etcdserverpb::AuthRoleRevokePermissionResponse) + expect(conn.get_role('myrole').perm.size).to eq(0) + end + end + describe '#disable_auth' do before do conn.add_user('root', 'test') From 75d4d3665b340935377cd8c7fd277f44c9bcc3f8 Mon Sep 17 00:00:00 2001 From: Shaun Davis Date: Sat, 1 Apr 2017 11:14:59 -0500 Subject: [PATCH 3/4] Ditching guardfile dependency --- Gemfile | 1 - Guardfile | 31 ------------------------------- 2 files changed, 32 deletions(-) delete mode 100644 Guardfile diff --git a/Gemfile b/Gemfile index 7bd0525..a981d21 100644 --- a/Gemfile +++ b/Gemfile @@ -2,4 +2,3 @@ source 'https://rubygems.org' gem "grpc" gem 'rspec' -gem 'guard-rspec', require: false diff --git a/Guardfile b/Guardfile deleted file mode 100644 index 00bcf6a..0000000 --- a/Guardfile +++ /dev/null @@ -1,31 +0,0 @@ -# A sample Guardfile -# More info at https://github.com/guard/guard#readme - -## Uncomment and set this to only include directories you want to watch -# directories %w(app lib config test spec features) \ -# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} - -## Note: if you are using the `directories` clause above and you are not -## watching the project directory ('.'), then you will want to move -## the Guardfile to a watched dir and symlink it back, e.g. -# -# $ mkdir config -# $ mv Guardfile config/ -# $ ln -s config/Guardfile . -# -# and, you'll have to watch "config/Guardfile" instead of "Guardfile" - -# Note: The cmd option is now required due to the increasing number of ways -# rspec may be run, below are examples of the most common uses. -# * bundler: 'bundle exec rspec' -# * bundler binstubs: 'bin/rspec' -# * spring: 'bin/rspec' (This will use spring if running and you have -# installed the spring binstubs per the docs) -# * zeus: 'zeus rspec' (requires the server to be started separately) -# * 'just' rspec: 'rspec' - -guard :rspec, cmd: 'rspec' do - watch(%r{^spec/.+_spec\.rb$}) - watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { "spec" } -end From 5281aae3bfa33a91f094335ede18c31f672b21cc Mon Sep 17 00:00:00 2001 From: Shaun Davis Date: Sat, 1 Apr 2017 11:25:23 -0500 Subject: [PATCH 4/4] Faraday 0.12.0 has some checksum issues pparently --- Gemfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index a981d21..63611a6 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,6 @@ source 'https://rubygems.org' gem "grpc" gem 'rspec' +gem 'faraday', '0.11.0' + +