Class: OodSupport::ACLs::PosixACL

Inherits:
OodSupport::ACL show all
Defined in:
lib/ood_support/acls/posix.rb

Overview

Object describing a Posix ACL

Constant Summary collapse

GET_FACL_BIN =

The binary used to get the file ACLs

'getfacl'
SET_FACL_BIN =

The binary used to set the file ACLs

'setfacl'

Instance Attribute Summary collapse

Attributes inherited from OodSupport::ACL

#default, #entries

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from OodSupport::ACL

#==, #eql?, #hash

Constructor Details

#initialize(owner:, group:, mask:, **kwargs) ⇒ PosixACL

Returns a new instance of PosixACL


95
96
97
98
99
100
# File 'lib/ood_support/acls/posix.rb', line 95

def initialize(owner:, group:, mask:, **kwargs)
  super(kwargs.merge(default: false))
  @owner = owner.to_s
  @group = group.to_s
  @mask = mask
end

Instance Attribute Details

#groupString (readonly)

Name of owning group for this ACL


19
20
21
# File 'lib/ood_support/acls/posix.rb', line 19

def group
  @group
end

#maskArray<Symbol> (readonly)

Mask set for this ACL


23
24
25
# File 'lib/ood_support/acls/posix.rb', line 23

def mask
  @mask
end

#ownerString (readonly)

Name of owner for this ACL


15
16
17
# File 'lib/ood_support/acls/posix.rb', line 15

def owner
  @owner
end

Class Method Details

.add_facl(path:, entry:) ⇒ PosixACL

Add ACL to file path

Raises:

  • (InvalidPath)

    file path doesn't exist

  • (BadExitCode)

    the command line called exited with non-zero status


45
46
47
48
49
50
51
# File 'lib/ood_support/acls/posix.rb', line 45

def self.add_facl(path:, entry:)
  path = Pathname.new path
  raise InvalidPath, "invalid path: #{path}" unless path.exist?
  _, err, s = Open3.capture3(SET_FACL_BIN, '-m', entry.to_s, path.to_s)
  raise BadExitCode, err unless s.success?
  get_facl(path: path)
end

.clear_facl(path:) ⇒ PosixACL

Clear all extended ACLs from file path

Raises:


70
71
72
73
74
75
76
# File 'lib/ood_support/acls/posix.rb', line 70

def self.clear_facl(path:)
  path = Pathname.new path
  raise InvalidPath, "invalid path: #{path}" unless path.exist?
  _, err, s = Open3.capture3(SET_FACL_BIN, '-b', path.to_s)
  raise BadExitCode, err unless s.success?
  get_facl(path: path)
end

.get_facl(path:) ⇒ PosixACL

Get ACL from file path

Raises:

  • (InvalidPath)

    file path doesn't exist

  • (BadExitCode)

    the command line called exited with non-zero status


30
31
32
33
34
35
36
37
# File 'lib/ood_support/acls/posix.rb', line 30

def self.get_facl(path:)
  path = Pathname.new path
  raise InvalidPath, "invalid path: #{path}" unless path.exist?
  stat = path.stat
  acl, err, s = Open3.capture3(GET_FACL_BIN, path.to_s)
  raise BadExitCode, err unless s.success?
  parse(acl, owner: User.new(stat.uid), group: Group.new(stat.gid))
end

.parse(acl, **kwargs) ⇒ PosixACL

Generate an ACL by parsing a string along with options


82
83
84
85
86
87
88
89
# File 'lib/ood_support/acls/posix.rb', line 82

def self.parse(acl, **kwargs)
  entries = []
  acl.to_s.strip.split(/\n|,/).grep(/^[^#]/).each do |entry|
    entries << entry_class.parse(entry)
  end
  mask = entries.detect {|e| e.flag == :mask}
  new(entries: entries - [mask], mask: mask, **kwargs)
end

.rem_facl(path:, entry:) ⇒ PosixACL

Remove ACL from file path

Raises:

  • (InvalidPath)

    file path doesn't exist

  • (BadExitCode)

    the command line called exited with non-zero status


59
60
61
62
63
64
65
# File 'lib/ood_support/acls/posix.rb', line 59

def self.rem_facl(path:, entry:)
  path = Pathname.new path
  raise InvalidPath, "invalid path: #{path}" unless path.exist?
  _, err, s = Open3.capture3(SET_FACL_BIN, '-x', entry.to_s(w_perms: false), path.to_s)
  raise BadExitCode, err unless s.success?
  get_facl(path: path)
end

Instance Method Details

#allow?(principle:, permission:) ⇒ Boolean

Check if queried principle has access to resource


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/ood_support/acls/posix.rb', line 106

def allow?(principle:, permission:)
  # First check owner entry then check rest of user entries (order
  # matters). If match, then this entry determines access.
  entries.select(&:user_entry?).sort_by {|e| e.user_owner_entry? ? 0 : 1}.each do |entry|
    return entry.has_permission?(permission: permission, mask: mask) if entry.match(principle: principle, owner: owner, group: group)
  end

  # Then check groups (order independent). Entry only determines access
  # if it contains requested permission.
  groups = entries.select {|e| e.group_entry? && e.match(principle: principle, owner: owner, group: group)}.map do |entry|
    entry.has_permission?(permission: permission, mask: mask)
  end

  unless groups.empty?
    # Found matching groups so check if any give access
    groups.any?
  else
    # Failed to find any matching groups so check "other" entry
    entries.detect(&:other_entry?).has_permission?(permission: permission, mask: mask)
  end
end

#to_hHash

Convert object to hash


136
137
138
# File 'lib/ood_support/acls/posix.rb', line 136

def to_h
  super.merge owner: owner, group: group, mask: mask
end

#to_sString

Convert object to string


130
131
132
# File 'lib/ood_support/acls/posix.rb', line 130

def to_s
  (entries + [mask]).join(",")
end