unix_user_manager 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 61d72c8cb4a4525f0b469a69733981832a7b2a45
4
+ data.tar.gz: 6605fa33c7dcdbfb093817d7837d1d4184d53660
5
+ SHA512:
6
+ metadata.gz: 098ff161ddfcae238d9f28585b142de8894573d5b549bb60459efc72e4b94d6339ccae38349fe269c9231a7c3b324df3227c2ef4722b3dd43bbfcb223f0a0010
7
+ data.tar.gz: 548a598da54347c551512fcf41951d2158ce79edf9640ecd17025ab898454d804f6ebb631fc018565595b6e4e021b9a156fd65eb77d89a80c34c895dc876b405
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in unix_user_manager.gemspec
4
+ gemspec
5
+
6
+ gem 'rspec'
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # UnixUserManager gem
2
+
3
+ Management tool for unix users. Manually edits `/etc/passwd`, `/etc/shadow` and `/etc/groups`.
4
+
5
+ It will not write anything to your files, but use it on your own risk!
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'unix_user_manager'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install unix_user_manager
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ passwd = `cat /etc/passwd`
27
+ group = `cat /etc/group`
28
+ shadow = `cat /etc/shadow`
29
+
30
+ # initialize
31
+ um = UnixUserManager.new passwd: passwd, group: group, shadow: shadow
32
+
33
+ # get some uniq id for you new group and user
34
+ new_id = um.available_id(min_id: 100, max_id: 500, preffered_ids: [200, 300, 333, 400, 500], recursive: false) # 42
35
+
36
+ # add new user
37
+ um.users.add(name: "risky_man", uid: new_id, gid: new_id) # true
38
+
39
+ # add new group
40
+ um.groups.add(name: "risky_group", uname: "risky_man", gid: new_id) # true
41
+
42
+ # build new configs
43
+ um.users.build_passwd # new contents for /etc/passwd
44
+ um.users.build_shadow # new contents for /etc/shadow
45
+ um.groups.build # new contents for /etc/group
46
+
47
+ # or
48
+ um.users.build # { passwd: "...content...", shadow: "...content..." } new contents for /etc/passwd and /etc/shadow
49
+
50
+ # or build only new lines
51
+ um.users.build_passwd_new_records # new lines for /etc/passwd, eg "risky_man:x:42:42::/dev/null:/bin/bash"
52
+ um.users.build_shadow_new_records # new lines for /etc/shadow, eg "risky_man:!!:::::::"
53
+ um.groups.build_new_records # new lines for /etc/group, eg "risky_group:x:42:risky_man"
54
+ ```
55
+
56
+ ## TODO
57
+
58
+ 1. Add support for edit users/groups
59
+ 2. Add support for destroy users/groups
60
+ 3. Add support for user with passwords
61
+ 5. Add support for gshadow
62
+
63
+ ## Development
64
+
65
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
66
+
67
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
68
+
69
+ ## Contributing
70
+
71
+ 1. Fork it ( https://github.com/[my-github-username]/unix_user_manager/fork )
72
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
73
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
74
+ 4. Push to the branch (`git push origin my-new-feature`)
75
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'unix_user_manager'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require 'pry'
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,44 @@
1
+ require "unix_user_manager/version"
2
+
3
+ require "unix_user_manager/file/base"
4
+ require "unix_user_manager/file/group"
5
+ require "unix_user_manager/file/passwd"
6
+ require "unix_user_manager/file/shadow"
7
+
8
+ require "unix_user_manager/base"
9
+ require "unix_user_manager/groups"
10
+ require "unix_user_manager/users"
11
+
12
+ class UnixUserManager
13
+ attr_reader :passwd, :shadow, :group,
14
+ :users, :groups
15
+
16
+ def initialize(passwd:, shadow:, group:)
17
+ @passwd = UnixUserManager::File::Passwd.new passwd
18
+ @shadow = UnixUserManager::File::Shadow.new shadow
19
+ @group = UnixUserManager::File::Group.new group
20
+
21
+ @users = UnixUserManager::Users.new(passwd: @passwd, shadow: @shadow)
22
+ @groups = UnixUserManager::Groups.new(group: @group)
23
+ end
24
+
25
+ def available_id(min_id: 100, max_id: 500, preffered_ids: [200, 300, 333, 400, 500], recursive: false)
26
+ ids = available_ids(min_id: min_id, max_id: max_id)
27
+
28
+ new_id = (ids & preffered_ids).any? ? (ids & preffered_ids)[0] : ids[0]
29
+
30
+ if recursive && new_id.nil?
31
+ available_id(min_id: min_id, preffered_ids: preffered_ids, recursive: recursive, max_id: max_id + 100)
32
+ else
33
+ new_id
34
+ end
35
+ end
36
+
37
+ def available_ids(min_id: 100, max_id: 500)
38
+ # Service ids must be from 100 to 500
39
+ available_uid = (min_id..max_id).to_a - users.ids
40
+ available_gid = (min_id..max_id).to_a - groups.ids
41
+
42
+ available_uid & available_gid
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ class UnixUserManager::Base
2
+ attr_reader :file
3
+ DELEGATED_METHODS = [:ids, :find, :find_by_id, :exist?, :add, :all, :build, :build_new_records].freeze
4
+
5
+ def initialize(*args)
6
+ raise NotImplementedError
7
+ end
8
+
9
+ def method_missing(method_name, *args, &block)
10
+ if DELEGATED_METHODS.include?(method_name)
11
+ file.send method_name, *args, &block
12
+ else
13
+ super
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,58 @@
1
+ module UnixUserManager::File
2
+ class Base
3
+ attr_reader :source, :data, :new_records
4
+
5
+ def initialize(source)
6
+ @source = source
7
+ @new_records = Hash.new { |h, k| h[k] = { id: nil } }
8
+
9
+ parse_file
10
+ end
11
+
12
+ def ids
13
+ data.values.sort
14
+ end
15
+
16
+ def find(name)
17
+ data[name]
18
+ end
19
+
20
+ def find_by_id(id)
21
+ data.key id
22
+ end
23
+
24
+ def exist?(name)
25
+ !!data[name]
26
+ end
27
+
28
+ def id_exist?(id)
29
+ return false if id.nil?
30
+
31
+ !!data.key(id)
32
+ end
33
+
34
+ def can_add?(name, id = nil)
35
+ !(exist?(name) || id_exist?(id) || @new_records.key?(name))
36
+ end
37
+
38
+ def all
39
+ data
40
+ end
41
+
42
+ def build
43
+ @new_records.any? ? (source + "\n" + build_new_records) : source
44
+ end
45
+
46
+ def build_new_records
47
+ raise NotImplementedError
48
+ end
49
+
50
+ private
51
+
52
+ def parse_file
53
+ @data = source.split("\n")
54
+ .reject { |line| line.strip[0] == '#' } # remove comments
55
+ .map { |line| data = line.split(':'); [data[0], data[2].to_i] }.to_h # name => id
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,12 @@
1
+ class UnixUserManager::File::Group < UnixUserManager::File::Base
2
+ def add(name:, uname:, gid:)
3
+ return false unless can_add?(name, gid)
4
+ @new_records[name] = { gid: gid, uname: uname }
5
+
6
+ true
7
+ end
8
+
9
+ def build_new_records
10
+ @new_records.map { |name, data| "#{name}:x:#{data[:gid]}:#{data[:uname]}" }.join("\n")
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class UnixUserManager::File::Passwd < UnixUserManager::File::Base
2
+ def add(name:, uid:, gid:)
3
+ return false unless can_add?(name, uid)
4
+ @new_records[name] = { uid: uid, gid: gid }
5
+
6
+ true
7
+ end
8
+
9
+ def build_new_records
10
+ @new_records.map { |name, data| "#{name}:x:#{data[:uid]}:#{data[:gid]}::/dev/null:/bin/bash" }.join("\n")
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ class UnixUserManager::File::Shadow < UnixUserManager::File::Base
2
+ def ids(*arg); raise NotImplementedError; end
3
+ def find(*arg); raise NotImplementedError; end
4
+ def find_by_id(*arg); raise NotImplementedError; end
5
+ def id_exist?(*arg); false end
6
+
7
+ def add(name:)
8
+ return false unless can_add?(name)
9
+ @new_records[name] = { id: nil }
10
+
11
+ true
12
+ end
13
+
14
+ def build_new_records
15
+ @new_records.map { |name, _| "#{name}:!!:::::::" }.join("\n")
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ class UnixUserManager::Groups < UnixUserManager::Base
2
+ def initialize(group:)
3
+ @file = group
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ class UnixUserManager::Users < UnixUserManager::Base
2
+ attr_reader :shadow_file
3
+
4
+ def initialize(passwd:, shadow:)
5
+ @file = passwd
6
+ @shadow_file = shadow
7
+ end
8
+
9
+ def build_passwd
10
+ file.build
11
+ end
12
+
13
+ def build_passwd_new_records
14
+ file.build_new_records
15
+ end
16
+
17
+ def build_shadow
18
+ shadow_file.build
19
+ end
20
+
21
+ def build_shadow_new_records
22
+ shadow_file.build_new_records
23
+ end
24
+
25
+ def build
26
+ { passwd: build_passwd, shadow: build_shadow }
27
+ end
28
+
29
+ def build_new_records
30
+ { passwd: build_passwd_new_records, shadow: build_shadow_new_records }
31
+ end
32
+
33
+ def add(name:, uid:, gid:)
34
+ return false unless file.can_add?(name, uid) && shadow_file.can_add?(name)
35
+
36
+ file.add(name: name, uid: uid, gid: gid) && shadow_file.add(name: name)
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ class UnixUserManager
2
+ VERSION = '0.1.1'.freeze
3
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'unix_user_manager/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "unix_user_manager"
8
+ spec.version = UnixUserManager::VERSION
9
+ spec.authors = ["mr.The"]
10
+ spec.email = ["me@mrthe.name"]
11
+
12
+ spec.summary = %q{Management tool for unix users.}
13
+ spec.description = %q{Management tool for unix users. Manually edits `/etc/passwd`, `/etc/shadow` and `/etc/groups`.}
14
+ spec.homepage = "http://github.com/mrThe/unix_user_manager"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.9"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unix_user_manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - mr.The
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Management tool for unix users. Manually edits `/etc/passwd`, `/etc/shadow`
42
+ and `/etc/groups`.
43
+ email:
44
+ - me@mrthe.name
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".rspec"
51
+ - Gemfile
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - lib/unix_user_manager.rb
57
+ - lib/unix_user_manager/base.rb
58
+ - lib/unix_user_manager/file/base.rb
59
+ - lib/unix_user_manager/file/group.rb
60
+ - lib/unix_user_manager/file/passwd.rb
61
+ - lib/unix_user_manager/file/shadow.rb
62
+ - lib/unix_user_manager/groups.rb
63
+ - lib/unix_user_manager/users.rb
64
+ - lib/unix_user_manager/version.rb
65
+ - unix_user_manager.gemspec
66
+ homepage: http://github.com/mrThe/unix_user_manager
67
+ licenses: []
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.4.5
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Management tool for unix users.
89
+ test_files: []